| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <limits.h> // For LONG_MIN, LONG_MAX. | 5 #include <limits.h> // For LONG_MIN, LONG_MAX. |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_MIPS64 | 7 #if V8_TARGET_ARCH_MIPS64 |
| 8 | 8 |
| 9 #include "src/base/division-by-constant.h" | 9 #include "src/base/division-by-constant.h" |
| 10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
| (...skipping 2506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2517 | 2517 |
| 2518 void MacroAssembler::Movt(Register rd, Register rs, uint16_t cc) { | 2518 void MacroAssembler::Movt(Register rd, Register rs, uint16_t cc) { |
| 2519 movt(rd, rs, cc); | 2519 movt(rd, rs, cc); |
| 2520 } | 2520 } |
| 2521 | 2521 |
| 2522 | 2522 |
| 2523 void MacroAssembler::Movf(Register rd, Register rs, uint16_t cc) { | 2523 void MacroAssembler::Movf(Register rd, Register rs, uint16_t cc) { |
| 2524 movf(rd, rs, cc); | 2524 movf(rd, rs, cc); |
| 2525 } | 2525 } |
| 2526 | 2526 |
| 2527 #define __ masm-> | |
| 2528 | |
| 2529 static bool ZeroHelper_d(MacroAssembler* masm, MaxMinKind kind, FPURegister dst, | |
| 2530 FPURegister src1, FPURegister src2, Label* equal) { | |
| 2531 if (src1.is(src2)) { | |
| 2532 __ Move(dst, src1); | |
| 2533 return true; | |
| 2534 } | |
| 2535 | |
| 2536 Label other, compare_not_equal; | |
| 2537 FPURegister left, right; | |
| 2538 if (kind == MaxMinKind::kMin) { | |
| 2539 left = src1; | |
| 2540 right = src2; | |
| 2541 } else { | |
| 2542 left = src2; | |
| 2543 right = src1; | |
| 2544 } | |
| 2545 | |
| 2546 __ BranchF64(&compare_not_equal, nullptr, ne, src1, src2); | |
| 2547 // Left and right hand side are equal, check for -0 vs. +0. | |
| 2548 __ dmfc1(t8, src1); | |
| 2549 __ Branch(&other, eq, t8, Operand(0x8000000000000000)); | |
| 2550 __ Move_d(dst, right); | |
| 2551 __ Branch(equal); | |
| 2552 __ bind(&other); | |
| 2553 __ Move_d(dst, left); | |
| 2554 __ Branch(equal); | |
| 2555 __ bind(&compare_not_equal); | |
| 2556 return false; | |
| 2557 } | |
| 2558 | |
| 2559 static bool ZeroHelper_s(MacroAssembler* masm, MaxMinKind kind, FPURegister dst, | |
| 2560 FPURegister src1, FPURegister src2, Label* equal) { | |
| 2561 if (src1.is(src2)) { | |
| 2562 __ Move(dst, src1); | |
| 2563 return true; | |
| 2564 } | |
| 2565 | |
| 2566 Label other, compare_not_equal; | |
| 2567 FPURegister left, right; | |
| 2568 if (kind == MaxMinKind::kMin) { | |
| 2569 left = src1; | |
| 2570 right = src2; | |
| 2571 } else { | |
| 2572 left = src2; | |
| 2573 right = src1; | |
| 2574 } | |
| 2575 | |
| 2576 __ BranchF32(&compare_not_equal, nullptr, ne, src1, src2); | |
| 2577 // Left and right hand side are equal, check for -0 vs. +0. | |
| 2578 __ FmoveLow(t8, src1); | |
| 2579 __ dsll32(t8, t8, 0); | |
| 2580 __ Branch(&other, eq, t8, Operand(0x8000000000000000)); | |
| 2581 __ Move_s(dst, right); | |
| 2582 __ Branch(equal); | |
| 2583 __ bind(&other); | |
| 2584 __ Move_s(dst, left); | |
| 2585 __ Branch(equal); | |
| 2586 __ bind(&compare_not_equal); | |
| 2587 return false; | |
| 2588 } | |
| 2589 | |
| 2590 #undef __ | |
| 2591 | |
| 2592 void MacroAssembler::MinNaNCheck_d(FPURegister dst, FPURegister src1, | |
| 2593 FPURegister src2, Label* nan) { | |
| 2594 if (nan) { | |
| 2595 BranchF64(nullptr, nan, eq, src1, src2); | |
| 2596 } | |
| 2597 if (kArchVariant >= kMips64r6) { | |
| 2598 min_d(dst, src1, src2); | |
| 2599 } else { | |
| 2600 Label skip; | |
| 2601 if (!ZeroHelper_d(this, MaxMinKind::kMin, dst, src1, src2, &skip)) { | |
| 2602 if (dst.is(src1)) { | |
| 2603 BranchF64(&skip, nullptr, le, src1, src2); | |
| 2604 Move_d(dst, src2); | |
| 2605 } else if (dst.is(src2)) { | |
| 2606 BranchF64(&skip, nullptr, ge, src1, src2); | |
| 2607 Move_d(dst, src1); | |
| 2608 } else { | |
| 2609 Label right; | |
| 2610 BranchF64(&right, nullptr, gt, src1, src2); | |
| 2611 Move_d(dst, src1); | |
| 2612 Branch(&skip); | |
| 2613 bind(&right); | |
| 2614 Move_d(dst, src2); | |
| 2615 } | |
| 2616 } | |
| 2617 bind(&skip); | |
| 2618 } | |
| 2619 } | |
| 2620 | |
| 2621 void MacroAssembler::MaxNaNCheck_d(FPURegister dst, FPURegister src1, | |
| 2622 FPURegister src2, Label* nan) { | |
| 2623 if (nan) { | |
| 2624 BranchF64(nullptr, nan, eq, src1, src2); | |
| 2625 } | |
| 2626 if (kArchVariant >= kMips64r6) { | |
| 2627 max_d(dst, src1, src2); | |
| 2628 } else { | |
| 2629 Label skip; | |
| 2630 if (!ZeroHelper_d(this, MaxMinKind::kMax, dst, src1, src2, &skip)) { | |
| 2631 if (dst.is(src1)) { | |
| 2632 BranchF64(&skip, nullptr, ge, src1, src2); | |
| 2633 Move_d(dst, src2); | |
| 2634 } else if (dst.is(src2)) { | |
| 2635 BranchF64(&skip, nullptr, le, src1, src2); | |
| 2636 Move_d(dst, src1); | |
| 2637 } else { | |
| 2638 Label right; | |
| 2639 BranchF64(&right, nullptr, lt, src1, src2); | |
| 2640 Move_d(dst, src1); | |
| 2641 Branch(&skip); | |
| 2642 bind(&right); | |
| 2643 Move_d(dst, src2); | |
| 2644 } | |
| 2645 } | |
| 2646 bind(&skip); | |
| 2647 } | |
| 2648 } | |
| 2649 | |
| 2650 void MacroAssembler::MinNaNCheck_s(FPURegister dst, FPURegister src1, | |
| 2651 FPURegister src2, Label* nan) { | |
| 2652 if (nan) { | |
| 2653 BranchF32(nullptr, nan, eq, src1, src2); | |
| 2654 } | |
| 2655 if (kArchVariant >= kMips64r6) { | |
| 2656 min_s(dst, src1, src2); | |
| 2657 } else { | |
| 2658 Label skip; | |
| 2659 if (!ZeroHelper_s(this, MaxMinKind::kMin, dst, src1, src2, &skip)) { | |
| 2660 if (dst.is(src1)) { | |
| 2661 BranchF32(&skip, nullptr, le, src1, src2); | |
| 2662 Move_s(dst, src2); | |
| 2663 } else if (dst.is(src2)) { | |
| 2664 BranchF32(&skip, nullptr, ge, src1, src2); | |
| 2665 Move_s(dst, src1); | |
| 2666 } else { | |
| 2667 Label right; | |
| 2668 BranchF32(&right, nullptr, gt, src1, src2); | |
| 2669 Move_s(dst, src1); | |
| 2670 Branch(&skip); | |
| 2671 bind(&right); | |
| 2672 Move_s(dst, src2); | |
| 2673 } | |
| 2674 } | |
| 2675 bind(&skip); | |
| 2676 } | |
| 2677 } | |
| 2678 | |
| 2679 void MacroAssembler::MaxNaNCheck_s(FPURegister dst, FPURegister src1, | |
| 2680 FPURegister src2, Label* nan) { | |
| 2681 if (nan) { | |
| 2682 BranchF32(nullptr, nan, eq, src1, src2); | |
| 2683 } | |
| 2684 if (kArchVariant >= kMips64r6) { | |
| 2685 max_s(dst, src1, src2); | |
| 2686 } else { | |
| 2687 Label skip; | |
| 2688 if (!ZeroHelper_s(this, MaxMinKind::kMax, dst, src1, src2, &skip)) { | |
| 2689 if (dst.is(src1)) { | |
| 2690 BranchF32(&skip, nullptr, ge, src1, src2); | |
| 2691 Move_s(dst, src2); | |
| 2692 } else if (dst.is(src2)) { | |
| 2693 BranchF32(&skip, nullptr, le, src1, src2); | |
| 2694 Move_s(dst, src1); | |
| 2695 } else { | |
| 2696 Label right; | |
| 2697 BranchF32(&right, nullptr, lt, src1, src2); | |
| 2698 Move_s(dst, src1); | |
| 2699 Branch(&skip); | |
| 2700 bind(&right); | |
| 2701 Move_s(dst, src2); | |
| 2702 } | |
| 2703 } | |
| 2704 bind(&skip); | |
| 2705 } | |
| 2706 } | |
| 2707 | 2527 |
| 2708 void MacroAssembler::Clz(Register rd, Register rs) { | 2528 void MacroAssembler::Clz(Register rd, Register rs) { |
| 2709 clz(rd, rs); | 2529 clz(rd, rs); |
| 2710 } | 2530 } |
| 2711 | 2531 |
| 2712 | 2532 |
| 2713 void MacroAssembler::EmitFPUTruncate(FPURoundingMode rounding_mode, | 2533 void MacroAssembler::EmitFPUTruncate(FPURoundingMode rounding_mode, |
| 2714 Register result, | 2534 Register result, |
| 2715 DoubleRegister double_input, | 2535 DoubleRegister double_input, |
| 2716 Register scratch, | 2536 Register scratch, |
| (...skipping 3756 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6473 Register scratch2, | 6293 Register scratch2, |
| 6474 Label* failure) { | 6294 Label* failure) { |
| 6475 // Check that neither is a smi. | 6295 // Check that neither is a smi. |
| 6476 STATIC_ASSERT(kSmiTag == 0); | 6296 STATIC_ASSERT(kSmiTag == 0); |
| 6477 And(scratch1, first, Operand(second)); | 6297 And(scratch1, first, Operand(second)); |
| 6478 JumpIfSmi(scratch1, failure); | 6298 JumpIfSmi(scratch1, failure); |
| 6479 JumpIfNonSmisNotBothSequentialOneByteStrings(first, second, scratch1, | 6299 JumpIfNonSmisNotBothSequentialOneByteStrings(first, second, scratch1, |
| 6480 scratch2, failure); | 6300 scratch2, failure); |
| 6481 } | 6301 } |
| 6482 | 6302 |
| 6303 void MacroAssembler::Float32Max(FPURegister dst, FPURegister src1, |
| 6304 FPURegister src2, Label* out_of_line) { |
| 6305 DCHECK(!src1.is(src2)); |
| 6306 |
| 6307 // Check if one of operands is NaN. |
| 6308 BranchF32(nullptr, out_of_line, eq, src1, src2); |
| 6309 |
| 6310 if (kArchVariant >= kMips64r6) { |
| 6311 max_s(dst, src1, src2); |
| 6312 } else { |
| 6313 Label return_left, return_right, done; |
| 6314 |
| 6315 c(OLT, S, src1, src2); |
| 6316 bc1t(&return_right); |
| 6317 nop(); |
| 6318 |
| 6319 c(OLT, S, src2, src1); |
| 6320 bc1t(&return_left); |
| 6321 nop(); |
| 6322 |
| 6323 // Operands are equal, but check for +/-0. |
| 6324 mfc1(t8, src1); |
| 6325 dsll32(t8, t8, 0); |
| 6326 beq(t8, zero_reg, &return_left); |
| 6327 nop(); |
| 6328 b(&return_right); |
| 6329 nop(); |
| 6330 |
| 6331 bind(&return_right); |
| 6332 if (!src2.is(dst)) { |
| 6333 Move_s(dst, src2); |
| 6334 } |
| 6335 b(&done); |
| 6336 nop(); |
| 6337 |
| 6338 bind(&return_left); |
| 6339 if (!src1.is(dst)) { |
| 6340 Move_s(dst, src1); |
| 6341 } |
| 6342 |
| 6343 bind(&done); |
| 6344 } |
| 6345 } |
| 6346 |
| 6347 void MacroAssembler::Float32MaxOutOfLine(FPURegister dst, FPURegister src1, |
| 6348 FPURegister src2) { |
| 6349 DCHECK(!src1.is(src2)); |
| 6350 add_s(dst, src1, src2); |
| 6351 } |
| 6352 |
| 6353 void MacroAssembler::Float32Min(FPURegister dst, FPURegister src1, |
| 6354 FPURegister src2, Label* out_of_line) { |
| 6355 DCHECK(!src1.is(src2)); |
| 6356 |
| 6357 // Check if one of operands is NaN. |
| 6358 BranchF32(nullptr, out_of_line, eq, src1, src2); |
| 6359 |
| 6360 if (kArchVariant >= kMips64r6) { |
| 6361 min_s(dst, src1, src2); |
| 6362 } else { |
| 6363 Label return_left, return_right, done; |
| 6364 |
| 6365 c(OLT, S, src1, src2); |
| 6366 bc1t(&return_left); |
| 6367 nop(); |
| 6368 |
| 6369 c(OLT, S, src2, src1); |
| 6370 bc1t(&return_right); |
| 6371 nop(); |
| 6372 |
| 6373 // Left equals right => check for -0. |
| 6374 mfc1(t8, src1); |
| 6375 dsll32(t8, t8, 0); |
| 6376 beq(t8, zero_reg, &return_right); |
| 6377 nop(); |
| 6378 b(&return_left); |
| 6379 nop(); |
| 6380 |
| 6381 bind(&return_right); |
| 6382 if (!src2.is(dst)) { |
| 6383 Move_s(dst, src2); |
| 6384 } |
| 6385 b(&done); |
| 6386 nop(); |
| 6387 |
| 6388 bind(&return_left); |
| 6389 if (!src1.is(dst)) { |
| 6390 Move_s(dst, src1); |
| 6391 } |
| 6392 |
| 6393 bind(&done); |
| 6394 } |
| 6395 } |
| 6396 |
| 6397 void MacroAssembler::Float32MinOutOfLine(FPURegister dst, FPURegister src1, |
| 6398 FPURegister src2) { |
| 6399 DCHECK(!src1.is(src2)); |
| 6400 add_s(dst, src1, src2); |
| 6401 } |
| 6402 |
| 6403 void MacroAssembler::Float64Max(FPURegister dst, FPURegister src1, |
| 6404 FPURegister src2, Label* out_of_line) { |
| 6405 DCHECK(!src1.is(src2)); |
| 6406 |
| 6407 // Check if one of operands is NaN. |
| 6408 BranchF64(nullptr, out_of_line, eq, src1, src2); |
| 6409 |
| 6410 if (kArchVariant >= kMips64r6) { |
| 6411 max_d(dst, src1, src2); |
| 6412 } else { |
| 6413 Label return_left, return_right, done; |
| 6414 |
| 6415 c(OLT, D, src1, src2); |
| 6416 bc1t(&return_right); |
| 6417 nop(); |
| 6418 |
| 6419 c(OLT, D, src2, src1); |
| 6420 bc1t(&return_left); |
| 6421 nop(); |
| 6422 |
| 6423 // Left equals right => check for -0. |
| 6424 dmfc1(t8, src1); |
| 6425 beq(t8, zero_reg, &return_left); |
| 6426 nop(); |
| 6427 b(&return_right); |
| 6428 nop(); |
| 6429 |
| 6430 bind(&return_right); |
| 6431 if (!src2.is(dst)) { |
| 6432 Move_d(dst, src2); |
| 6433 } |
| 6434 b(&done); |
| 6435 nop(); |
| 6436 |
| 6437 bind(&return_left); |
| 6438 if (!src1.is(dst)) { |
| 6439 Move_d(dst, src1); |
| 6440 } |
| 6441 |
| 6442 bind(&done); |
| 6443 } |
| 6444 } |
| 6445 |
| 6446 void MacroAssembler::Float64MaxOutOfLine(FPURegister dst, FPURegister src1, |
| 6447 FPURegister src2) { |
| 6448 DCHECK(!src1.is(src2)); |
| 6449 add_d(dst, src1, src2); |
| 6450 } |
| 6451 |
| 6452 void MacroAssembler::Float64Min(FPURegister dst, FPURegister src1, |
| 6453 FPURegister src2, Label* out_of_line) { |
| 6454 DCHECK(!src1.is(src2)); |
| 6455 |
| 6456 // Check if one of operands is NaN. |
| 6457 BranchF64(nullptr, out_of_line, eq, src1, src2); |
| 6458 |
| 6459 if (kArchVariant >= kMips64r6) { |
| 6460 min_d(dst, src1, src2); |
| 6461 } else { |
| 6462 Label return_left, return_right, done; |
| 6463 |
| 6464 c(OLT, D, src1, src2); |
| 6465 bc1t(&return_left); |
| 6466 nop(); |
| 6467 |
| 6468 c(OLT, D, src2, src1); |
| 6469 bc1t(&return_right); |
| 6470 nop(); |
| 6471 |
| 6472 // Left equals right => check for -0. |
| 6473 dmfc1(t8, src1); |
| 6474 beq(t8, zero_reg, &return_right); |
| 6475 nop(); |
| 6476 b(&return_left); |
| 6477 nop(); |
| 6478 |
| 6479 bind(&return_right); |
| 6480 if (!src2.is(dst)) { |
| 6481 Move_d(dst, src2); |
| 6482 } |
| 6483 b(&done); |
| 6484 nop(); |
| 6485 |
| 6486 bind(&return_left); |
| 6487 if (!src1.is(dst)) { |
| 6488 Move_d(dst, src1); |
| 6489 } |
| 6490 |
| 6491 bind(&done); |
| 6492 } |
| 6493 } |
| 6494 |
| 6495 void MacroAssembler::Float64MinOutOfLine(FPURegister dst, FPURegister src1, |
| 6496 FPURegister src2) { |
| 6497 DCHECK(!src1.is(src2)); |
| 6498 add_d(dst, src1, src2); |
| 6499 } |
| 6483 | 6500 |
| 6484 void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialOneByte( | 6501 void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialOneByte( |
| 6485 Register first, Register second, Register scratch1, Register scratch2, | 6502 Register first, Register second, Register scratch1, Register scratch2, |
| 6486 Label* failure) { | 6503 Label* failure) { |
| 6487 const int kFlatOneByteStringMask = | 6504 const int kFlatOneByteStringMask = |
| 6488 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask; | 6505 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask; |
| 6489 const int kFlatOneByteStringTag = | 6506 const int kFlatOneByteStringTag = |
| 6490 kStringTag | kOneByteStringTag | kSeqStringTag; | 6507 kStringTag | kOneByteStringTag | kSeqStringTag; |
| 6491 DCHECK(kFlatOneByteStringTag <= 0xffff); // Ensure this fits 16-bit immed. | 6508 DCHECK(kFlatOneByteStringTag <= 0xffff); // Ensure this fits 16-bit immed. |
| 6492 andi(scratch1, first, kFlatOneByteStringMask); | 6509 andi(scratch1, first, kFlatOneByteStringMask); |
| (...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7028 if (mag.shift > 0) sra(result, result, mag.shift); | 7045 if (mag.shift > 0) sra(result, result, mag.shift); |
| 7029 srl(at, dividend, 31); | 7046 srl(at, dividend, 31); |
| 7030 Addu(result, result, Operand(at)); | 7047 Addu(result, result, Operand(at)); |
| 7031 } | 7048 } |
| 7032 | 7049 |
| 7033 | 7050 |
| 7034 } // namespace internal | 7051 } // namespace internal |
| 7035 } // namespace v8 | 7052 } // namespace v8 |
| 7036 | 7053 |
| 7037 #endif // V8_TARGET_ARCH_MIPS64 | 7054 #endif // V8_TARGET_ARCH_MIPS64 |
| OLD | NEW |