Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: src/mips/code-stubs-mips.cc

Issue 23534011: MIPS: VFP cleanup now that VFP2 is the baseline. (Closed) Base URL: git@github.com:paul99/v8m-rb.git@master
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/mips/code-stubs-mips.h ('k') | src/mips/ic-mips.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after
514 // Compute lower part of fraction (last 12 bits). 514 // Compute lower part of fraction (last 12 bits).
515 __ sll(mantissa, source_, HeapNumber::kMantissaBitsInTopWord); 515 __ sll(mantissa, source_, HeapNumber::kMantissaBitsInTopWord);
516 // And the top (top 20 bits). 516 // And the top (top 20 bits).
517 __ srl(source_, source_, 32 - HeapNumber::kMantissaBitsInTopWord); 517 __ srl(source_, source_, 32 - HeapNumber::kMantissaBitsInTopWord);
518 518
519 __ Ret(USE_DELAY_SLOT); 519 __ Ret(USE_DELAY_SLOT);
520 __ or_(exponent, exponent, source_); 520 __ or_(exponent, exponent, source_);
521 } 521 }
522 522
523 523
524 void FloatingPointHelper::LoadSmis(MacroAssembler* masm,
525 FloatingPointHelper::Destination destination,
526 Register scratch1,
527 Register scratch2) {
528 __ sra(scratch1, a0, kSmiTagSize);
529 __ mtc1(scratch1, f14);
530 __ cvt_d_w(f14, f14);
531 __ sra(scratch1, a1, kSmiTagSize);
532 __ mtc1(scratch1, f12);
533 __ cvt_d_w(f12, f12);
534 if (destination == kCoreRegisters) {
535 __ Move(a2, a3, f14);
536 __ Move(a0, a1, f12);
537 }
538 }
539
540
541 void FloatingPointHelper::LoadNumber(MacroAssembler* masm,
542 Destination destination,
543 Register object,
544 FPURegister dst,
545 Register dst1,
546 Register dst2,
547 Register heap_number_map,
548 Register scratch1,
549 Register scratch2,
550 Label* not_number) {
551 __ AssertRootValue(heap_number_map,
552 Heap::kHeapNumberMapRootIndex,
553 kHeapNumberMapRegisterClobbered);
554
555 Label is_smi, done;
556
557 // Smi-check
558 __ UntagAndJumpIfSmi(scratch1, object, &is_smi);
559 // Heap number check
560 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number);
561
562 // Handle loading a double from a heap number.
563 if (destination == kFPURegisters) {
564 // Load the double from tagged HeapNumber to double register.
565
566 // ARM uses a workaround here because of the unaligned HeapNumber
567 // kValueOffset. On MIPS this workaround is built into ldc1 so there's no
568 // point in generating even more instructions.
569 __ ldc1(dst, FieldMemOperand(object, HeapNumber::kValueOffset));
570 } else {
571 ASSERT(destination == kCoreRegisters);
572 // Load the double from heap number to dst1 and dst2 in double format.
573 __ lw(dst1, FieldMemOperand(object, HeapNumber::kValueOffset));
574 __ lw(dst2, FieldMemOperand(object,
575 HeapNumber::kValueOffset + kPointerSize));
576 }
577 __ Branch(&done);
578
579 // Handle loading a double from a smi.
580 __ bind(&is_smi);
581 // Convert smi to double using FPU instructions.
582 __ mtc1(scratch1, dst);
583 __ cvt_d_w(dst, dst);
584 if (destination == kCoreRegisters) {
585 // Load the converted smi to dst1 and dst2 in double format.
586 __ Move(dst1, dst2, dst);
587 }
588 __ bind(&done);
589 }
590
591
592 void FloatingPointHelper::ConvertNumberToInt32(MacroAssembler* masm,
593 Register object,
594 Register dst,
595 Register heap_number_map,
596 Register scratch1,
597 Register scratch2,
598 Register scratch3,
599 FPURegister double_scratch,
600 Label* not_number) {
601 __ AssertRootValue(heap_number_map,
602 Heap::kHeapNumberMapRootIndex,
603 kHeapNumberMapRegisterClobbered);
604 Label done;
605 Label not_in_int32_range;
606
607 __ UntagAndJumpIfSmi(dst, object, &done);
608 __ lw(scratch1, FieldMemOperand(object, HeapNumber::kMapOffset));
609 __ Branch(not_number, ne, scratch1, Operand(heap_number_map));
610 __ ConvertToInt32(object,
611 dst,
612 scratch1,
613 scratch2,
614 double_scratch,
615 &not_in_int32_range);
616 __ jmp(&done);
617
618 __ bind(&not_in_int32_range);
619 __ lw(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset));
620 __ lw(scratch2, FieldMemOperand(object, HeapNumber::kMantissaOffset));
621
622 __ EmitOutOfInt32RangeTruncate(dst,
623 scratch1,
624 scratch2,
625 scratch3);
626
627 __ bind(&done);
628 }
629
630
631 void FloatingPointHelper::ConvertIntToDouble(MacroAssembler* masm,
632 Register int_scratch,
633 Destination destination,
634 FPURegister double_dst,
635 Register dst_mantissa,
636 Register dst_exponent,
637 Register scratch2,
638 FPURegister single_scratch) {
639 ASSERT(!int_scratch.is(scratch2));
640 ASSERT(!int_scratch.is(dst_mantissa));
641 ASSERT(!int_scratch.is(dst_exponent));
642
643 __ mtc1(int_scratch, single_scratch);
644 __ cvt_d_w(double_dst, single_scratch);
645 if (destination == kCoreRegisters) {
646 __ Move(dst_mantissa, dst_exponent, double_dst);
647 }
648 }
649
650
651 void FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm,
652 Register object,
653 Destination destination,
654 DoubleRegister double_dst,
655 DoubleRegister double_scratch,
656 Register dst_mantissa,
657 Register dst_exponent,
658 Register heap_number_map,
659 Register scratch1,
660 Register scratch2,
661 FPURegister single_scratch,
662 Label* not_int32) {
663 ASSERT(!scratch1.is(object) && !scratch2.is(object));
664 ASSERT(!scratch1.is(scratch2));
665 ASSERT(!heap_number_map.is(object) &&
666 !heap_number_map.is(scratch1) &&
667 !heap_number_map.is(scratch2));
668
669 Label done, obj_is_not_smi;
670
671 __ JumpIfNotSmi(object, &obj_is_not_smi);
672 __ SmiUntag(scratch1, object);
673 ConvertIntToDouble(masm, scratch1, destination, double_dst, dst_mantissa,
674 dst_exponent, scratch2, single_scratch);
675 __ Branch(&done);
676
677 __ bind(&obj_is_not_smi);
678 __ AssertRootValue(heap_number_map,
679 Heap::kHeapNumberMapRootIndex,
680 kHeapNumberMapRegisterClobbered);
681 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32);
682
683 // Load the number.
684 // Load the double value.
685 __ ldc1(double_dst, FieldMemOperand(object, HeapNumber::kValueOffset));
686
687 Register except_flag = scratch2;
688 __ EmitFPUTruncate(kRoundToZero,
689 scratch1,
690 double_dst,
691 at,
692 double_scratch,
693 except_flag,
694 kCheckForInexactConversion);
695
696 // Jump to not_int32 if the operation did not succeed.
697 __ Branch(not_int32, ne, except_flag, Operand(zero_reg));
698 if (destination == kCoreRegisters) {
699 __ Move(dst_mantissa, dst_exponent, double_dst);
700 }
701 __ bind(&done);
702 }
703
704
705 void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm,
706 Register object,
707 Register dst,
708 Register heap_number_map,
709 Register scratch1,
710 Register scratch2,
711 Register scratch3,
712 DoubleRegister double_scratch0,
713 DoubleRegister double_scratch1,
714 Label* not_int32) {
715 ASSERT(!dst.is(object));
716 ASSERT(!scratch1.is(object) && !scratch2.is(object) && !scratch3.is(object));
717 ASSERT(!scratch1.is(scratch2) &&
718 !scratch1.is(scratch3) &&
719 !scratch2.is(scratch3));
720
721 Label done, maybe_undefined;
722
723 __ UntagAndJumpIfSmi(dst, object, &done);
724
725 __ AssertRootValue(heap_number_map,
726 Heap::kHeapNumberMapRootIndex,
727 kHeapNumberMapRegisterClobbered);
728
729 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, &maybe_undefined);
730
731 // Object is a heap number.
732 // Convert the floating point value to a 32-bit integer.
733 // Load the double value.
734 __ ldc1(double_scratch0, FieldMemOperand(object, HeapNumber::kValueOffset));
735
736 Register except_flag = scratch2;
737 __ EmitFPUTruncate(kRoundToZero,
738 dst,
739 double_scratch0,
740 scratch1,
741 double_scratch1,
742 except_flag,
743 kCheckForInexactConversion);
744
745 // Jump to not_int32 if the operation did not succeed.
746 __ Branch(not_int32, ne, except_flag, Operand(zero_reg));
747 __ Branch(&done);
748
749 __ bind(&maybe_undefined);
750 __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
751 __ Branch(not_int32, ne, object, Operand(at));
752 // |undefined| is truncated to 0.
753 __ li(dst, Operand(Smi::FromInt(0)));
754 // Fall through.
755
756 __ bind(&done);
757 }
758
759
760 void FloatingPointHelper::CallCCodeForDoubleOperation(
761 MacroAssembler* masm,
762 Token::Value op,
763 Register heap_number_result,
764 Register scratch) {
765 // Using core registers:
766 // a0: Left value (least significant part of mantissa).
767 // a1: Left value (sign, exponent, top of mantissa).
768 // a2: Right value (least significant part of mantissa).
769 // a3: Right value (sign, exponent, top of mantissa).
770
771 // Assert that heap_number_result is saved.
772 // We currently always use s0 to pass it.
773 ASSERT(heap_number_result.is(s0));
774
775 // Push the current return address before the C call.
776 __ push(ra);
777 __ PrepareCallCFunction(4, scratch); // Two doubles are 4 arguments.
778 if (!IsMipsSoftFloatABI) {
779 // We are not using MIPS FPU instructions, and parameters for the runtime
780 // function call are prepaired in a0-a3 registers, but function we are
781 // calling is compiled with hard-float flag and expecting hard float ABI
782 // (parameters in f12/f14 registers). We need to copy parameters from
783 // a0-a3 registers to f12/f14 register pairs.
784 __ Move(f12, a0, a1);
785 __ Move(f14, a2, a3);
786 }
787 {
788 AllowExternalCallThatCantCauseGC scope(masm);
789 __ CallCFunction(
790 ExternalReference::double_fp_operation(op, masm->isolate()), 0, 2);
791 }
792 // Store answer in the overwritable heap number.
793 if (!IsMipsSoftFloatABI) {
794 // Double returned in register f0.
795 __ sdc1(f0, FieldMemOperand(heap_number_result, HeapNumber::kValueOffset));
796 } else {
797 // Double returned in registers v0 and v1.
798 __ sw(v1, FieldMemOperand(heap_number_result, HeapNumber::kExponentOffset));
799 __ sw(v0, FieldMemOperand(heap_number_result, HeapNumber::kMantissaOffset));
800 }
801 // Place heap_number_result in v0 and return to the pushed return address.
802 __ pop(ra);
803 __ Ret(USE_DELAY_SLOT);
804 __ mov(v0, heap_number_result);
805 }
806
807
808 bool WriteInt32ToHeapNumberStub::IsPregenerated() { 524 bool WriteInt32ToHeapNumberStub::IsPregenerated() {
809 // These variants are compiled ahead of time. See next method. 525 // These variants are compiled ahead of time. See next method.
810 if (the_int_.is(a1) && 526 if (the_int_.is(a1) &&
811 the_heap_number_.is(v0) && 527 the_heap_number_.is(v0) &&
812 scratch_.is(a2) && 528 scratch_.is(a2) &&
813 sign_.is(a3)) { 529 sign_.is(a3)) {
814 return true; 530 return true;
815 } 531 }
816 if (the_int_.is(a2) && 532 if (the_int_.is(a2) &&
817 the_heap_number_.is(v0) && 533 the_heap_number_.is(v0) &&
(...skipping 647 matching lines...) Expand 10 before | Expand all | Expand 10 after
1465 argument_count); 1181 argument_count);
1466 if (save_doubles_ == kSaveFPRegs) { 1182 if (save_doubles_ == kSaveFPRegs) {
1467 __ MultiPopFPU(kCallerSavedFPU); 1183 __ MultiPopFPU(kCallerSavedFPU);
1468 } 1184 }
1469 1185
1470 __ MultiPop(kJSCallerSaved | ra.bit()); 1186 __ MultiPop(kJSCallerSaved | ra.bit());
1471 __ Ret(); 1187 __ Ret();
1472 } 1188 }
1473 1189
1474 1190
1191 // Generates code to call a C function to do a double operation.
1192 // This code never falls through, but returns with a heap number containing
1193 // the result in v0.
1194 // Register heap_number_result must be a heap number in which the
1195 // result of the operation will be stored.
1196 // Requires the following layout on entry:
1197 // a0: Left value (least significant part of mantissa).
1198 // a1: Left value (sign, exponent, top of mantissa).
1199 // a2: Right value (least significant part of mantissa).
1200 // a3: Right value (sign, exponent, top of mantissa).
1201 static void CallCCodeForDoubleOperation(MacroAssembler* masm,
1202 Token::Value op,
1203 Register heap_number_result,
1204 Register scratch) {
1205 // Assert that heap_number_result is saved.
1206 // We currently always use s0 to pass it.
1207 ASSERT(heap_number_result.is(s0));
1208
1209 // Push the current return address before the C call.
1210 __ push(ra);
1211 __ PrepareCallCFunction(4, scratch); // Two doubles are 4 arguments.
1212 {
1213 AllowExternalCallThatCantCauseGC scope(masm);
1214 __ CallCFunction(
1215 ExternalReference::double_fp_operation(op, masm->isolate()), 0, 2);
1216 }
1217 // Store answer in the overwritable heap number.
1218 // Double returned in register f0.
1219 __ sdc1(f0, FieldMemOperand(heap_number_result, HeapNumber::kValueOffset));
1220 // Place heap_number_result in v0 and return to the pushed return address.
1221 __ pop(ra);
1222 __ Ret(USE_DELAY_SLOT);
1223 __ mov(v0, heap_number_result);
1224 }
1225
1226
1475 void BinaryOpStub::Initialize() { 1227 void BinaryOpStub::Initialize() {
1476 platform_specific_bit_ = true; // FPU is a base requirement for V8. 1228 platform_specific_bit_ = true; // FPU is a base requirement for V8.
1477 } 1229 }
1478 1230
1479 1231
1480 void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { 1232 void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
1481 Label get_result; 1233 Label get_result;
1482 1234
1483 __ Push(a1, a0); 1235 __ Push(a1, a0);
1484 1236
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
1692 1444
1693 Register heap_number_map = t2; 1445 Register heap_number_map = t2;
1694 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); 1446 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
1695 1447
1696 switch (op) { 1448 switch (op) {
1697 case Token::ADD: 1449 case Token::ADD:
1698 case Token::SUB: 1450 case Token::SUB:
1699 case Token::MUL: 1451 case Token::MUL:
1700 case Token::DIV: 1452 case Token::DIV:
1701 case Token::MOD: { 1453 case Token::MOD: {
1702 // Load left and right operands into f12 and f14 or a0/a1 and a2/a3
1703 // depending on operation.
1704 FloatingPointHelper::Destination destination =
1705 op != Token::MOD ?
1706 FloatingPointHelper::kFPURegisters :
1707 FloatingPointHelper::kCoreRegisters;
1708
1709 // Allocate new heap number for result. 1454 // Allocate new heap number for result.
1710 Register result = s0; 1455 Register result = s0;
1711 BinaryOpStub_GenerateHeapResultAllocation( 1456 BinaryOpStub_GenerateHeapResultAllocation(
1712 masm, result, heap_number_map, scratch1, scratch2, gc_required, mode); 1457 masm, result, heap_number_map, scratch1, scratch2, gc_required, mode);
1713 1458
1714 // Load the operands. 1459 // Load left and right operands into f12 and f14.
1715 if (smi_operands) { 1460 if (smi_operands) {
1716 FloatingPointHelper::LoadSmis(masm, destination, scratch1, scratch2); 1461 __ SmiUntag(scratch1, a0);
1462 __ mtc1(scratch1, f14);
1463 __ cvt_d_w(f14, f14);
1464 __ SmiUntag(scratch1, a1);
1465 __ mtc1(scratch1, f12);
1466 __ cvt_d_w(f12, f12);
1717 } else { 1467 } else {
1718 // Load right operand to f14 or a2/a3. 1468 // Load right operand to f14.
1719 if (right_type == BinaryOpIC::INT32) { 1469 if (right_type == BinaryOpIC::INT32) {
1720 FloatingPointHelper::LoadNumberAsInt32Double( 1470 __ LoadNumberAsInt32Double(
1721 masm, right, destination, f14, f16, a2, a3, heap_number_map, 1471 right, f14, heap_number_map, scratch1, scratch2, f2, miss);
1722 scratch1, scratch2, f2, miss);
1723 } else { 1472 } else {
1724 Label* fail = (right_type == BinaryOpIC::NUMBER) ? miss : not_numbers; 1473 Label* fail = (right_type == BinaryOpIC::NUMBER) ? miss : not_numbers;
1725 FloatingPointHelper::LoadNumber( 1474 __ LoadNumber(right, f14, heap_number_map, scratch1, fail);
1726 masm, destination, right, f14, a2, a3, heap_number_map,
1727 scratch1, scratch2, fail);
1728 } 1475 }
1729 // Load left operand to f12 or a0/a1. This keeps a0/a1 intact if it 1476 // Load left operand to f12 or a0/a1. This keeps a0/a1 intact if it
1730 // jumps to |miss|. 1477 // jumps to |miss|.
1731 if (left_type == BinaryOpIC::INT32) { 1478 if (left_type == BinaryOpIC::INT32) {
1732 FloatingPointHelper::LoadNumberAsInt32Double( 1479 __ LoadNumberAsInt32Double(
1733 masm, left, destination, f12, f16, a0, a1, heap_number_map, 1480 left, f12, heap_number_map, scratch1, scratch2, f2, miss);
1734 scratch1, scratch2, f2, miss);
1735 } else { 1481 } else {
1736 Label* fail = (left_type == BinaryOpIC::NUMBER) ? miss : not_numbers; 1482 Label* fail = (left_type == BinaryOpIC::NUMBER) ? miss : not_numbers;
1737 FloatingPointHelper::LoadNumber( 1483 __ LoadNumber(left, f12, heap_number_map, scratch1, fail);
1738 masm, destination, left, f12, a0, a1, heap_number_map,
1739 scratch1, scratch2, fail);
1740 } 1484 }
1741 } 1485 }
1742 1486
1743 // Calculate the result. 1487 // Calculate the result.
1744 if (destination == FloatingPointHelper::kFPURegisters) { 1488 if (op != Token::MOD) {
1745 // Using FPU registers: 1489 // Using FPU registers:
1746 // f12: Left value. 1490 // f12: Left value.
1747 // f14: Right value. 1491 // f14: Right value.
1748 switch (op) { 1492 switch (op) {
1749 case Token::ADD: 1493 case Token::ADD:
1750 __ add_d(f10, f12, f14); 1494 __ add_d(f10, f12, f14);
1751 break; 1495 break;
1752 case Token::SUB: 1496 case Token::SUB:
1753 __ sub_d(f10, f12, f14); 1497 __ sub_d(f10, f12, f14);
1754 break; 1498 break;
1755 case Token::MUL: 1499 case Token::MUL:
1756 __ mul_d(f10, f12, f14); 1500 __ mul_d(f10, f12, f14);
1757 break; 1501 break;
1758 case Token::DIV: 1502 case Token::DIV:
1759 __ div_d(f10, f12, f14); 1503 __ div_d(f10, f12, f14);
1760 break; 1504 break;
1761 default: 1505 default:
1762 UNREACHABLE(); 1506 UNREACHABLE();
1763 } 1507 }
1764 1508
1765 // ARM uses a workaround here because of the unaligned HeapNumber 1509 // ARM uses a workaround here because of the unaligned HeapNumber
1766 // kValueOffset. On MIPS this workaround is built into sdc1 so 1510 // kValueOffset. On MIPS this workaround is built into sdc1 so
1767 // there's no point in generating even more instructions. 1511 // there's no point in generating even more instructions.
1768 __ sdc1(f10, FieldMemOperand(result, HeapNumber::kValueOffset)); 1512 __ sdc1(f10, FieldMemOperand(result, HeapNumber::kValueOffset));
1769 __ Ret(USE_DELAY_SLOT); 1513 __ Ret(USE_DELAY_SLOT);
1770 __ mov(v0, result); 1514 __ mov(v0, result);
1771 } else { 1515 } else {
1772 // Call the C function to handle the double operation. 1516 // Call the C function to handle the double operation.
1773 FloatingPointHelper::CallCCodeForDoubleOperation(masm, 1517 CallCCodeForDoubleOperation(masm, op, result, scratch1);
1774 op,
1775 result,
1776 scratch1);
1777 if (FLAG_debug_code) { 1518 if (FLAG_debug_code) {
1778 __ stop("Unreachable code."); 1519 __ stop("Unreachable code.");
1779 } 1520 }
1780 } 1521 }
1781 break; 1522 break;
1782 } 1523 }
1783 case Token::BIT_OR: 1524 case Token::BIT_OR:
1784 case Token::BIT_XOR: 1525 case Token::BIT_XOR:
1785 case Token::BIT_AND: 1526 case Token::BIT_AND:
1786 case Token::SAR: 1527 case Token::SAR:
1787 case Token::SHR: 1528 case Token::SHR:
1788 case Token::SHL: { 1529 case Token::SHL: {
1789 if (smi_operands) { 1530 if (smi_operands) {
1790 __ SmiUntag(a3, left); 1531 __ SmiUntag(a3, left);
1791 __ SmiUntag(a2, right); 1532 __ SmiUntag(a2, right);
1792 } else { 1533 } else {
1793 // Convert operands to 32-bit integers. Right in a2 and left in a3. 1534 // Convert operands to 32-bit integers. Right in a2 and left in a3.
1794 FloatingPointHelper::ConvertNumberToInt32(masm, 1535 __ ConvertNumberToInt32(
1795 left, 1536 left, a3, heap_number_map,
1796 a3, 1537 scratch1, scratch2, scratch3, f0, not_numbers);
1797 heap_number_map, 1538 __ ConvertNumberToInt32(
1798 scratch1, 1539 right, a2, heap_number_map,
1799 scratch2, 1540 scratch1, scratch2, scratch3, f0, not_numbers);
1800 scratch3,
1801 f0,
1802 not_numbers);
1803 FloatingPointHelper::ConvertNumberToInt32(masm,
1804 right,
1805 a2,
1806 heap_number_map,
1807 scratch1,
1808 scratch2,
1809 scratch3,
1810 f0,
1811 not_numbers);
1812 } 1541 }
1813 Label result_not_a_smi; 1542 Label result_not_a_smi;
1814 switch (op) { 1543 switch (op) {
1815 case Token::BIT_OR: 1544 case Token::BIT_OR:
1816 __ Or(a2, a3, Operand(a2)); 1545 __ Or(a2, a3, Operand(a2));
1817 break; 1546 break;
1818 case Token::BIT_XOR: 1547 case Token::BIT_XOR:
1819 __ Xor(a2, a3, Operand(a2)); 1548 __ Xor(a2, a3, Operand(a2));
1820 break; 1549 break;
1821 case Token::BIT_AND: 1550 case Token::BIT_AND:
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
2035 // again if this changes. 1764 // again if this changes.
2036 if (left_type_ == BinaryOpIC::SMI) { 1765 if (left_type_ == BinaryOpIC::SMI) {
2037 __ JumpIfNotSmi(left, &transition); 1766 __ JumpIfNotSmi(left, &transition);
2038 } 1767 }
2039 if (right_type_ == BinaryOpIC::SMI) { 1768 if (right_type_ == BinaryOpIC::SMI) {
2040 __ JumpIfNotSmi(right, &transition); 1769 __ JumpIfNotSmi(right, &transition);
2041 } 1770 }
2042 // Load both operands and check that they are 32-bit integer. 1771 // Load both operands and check that they are 32-bit integer.
2043 // Jump to type transition if they are not. The registers a0 and a1 (right 1772 // Jump to type transition if they are not. The registers a0 and a1 (right
2044 // and left) are preserved for the runtime call. 1773 // and left) are preserved for the runtime call.
2045 FloatingPointHelper::Destination destination = (op_ != Token::MOD)
2046 ? FloatingPointHelper::kFPURegisters
2047 : FloatingPointHelper::kCoreRegisters;
2048 1774
2049 FloatingPointHelper::LoadNumberAsInt32Double(masm, 1775 __ LoadNumberAsInt32Double(
2050 right, 1776 right, f14, heap_number_map, scratch1, scratch2, f2, &transition);
2051 destination, 1777 __ LoadNumberAsInt32Double(
2052 f14, 1778 left, f12, heap_number_map, scratch1, scratch2, f2, &transition);
2053 f16,
2054 a2,
2055 a3,
2056 heap_number_map,
2057 scratch1,
2058 scratch2,
2059 f2,
2060 &transition);
2061 FloatingPointHelper::LoadNumberAsInt32Double(masm,
2062 left,
2063 destination,
2064 f12,
2065 f16,
2066 t0,
2067 t1,
2068 heap_number_map,
2069 scratch1,
2070 scratch2,
2071 f2,
2072 &transition);
2073 1779
2074 if (destination == FloatingPointHelper::kFPURegisters) { 1780 if (op_ != Token::MOD) {
2075 Label return_heap_number; 1781 Label return_heap_number;
2076 switch (op_) { 1782 switch (op_) {
2077 case Token::ADD: 1783 case Token::ADD:
2078 __ add_d(f10, f12, f14); 1784 __ add_d(f10, f12, f14);
2079 break; 1785 break;
2080 case Token::SUB: 1786 case Token::SUB:
2081 __ sub_d(f10, f12, f14); 1787 __ sub_d(f10, f12, f14);
2082 break; 1788 break;
2083 case Token::MUL: 1789 case Token::MUL:
2084 __ mul_d(f10, f12, f14); 1790 __ mul_d(f10, f12, f14);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
2141 1847
2142 // A DIV operation expecting an integer result falls through 1848 // A DIV operation expecting an integer result falls through
2143 // to type transition. 1849 // to type transition.
2144 1850
2145 } else { 1851 } else {
2146 if (encoded_right_arg_.has_value) { 1852 if (encoded_right_arg_.has_value) {
2147 __ Move(f16, fixed_right_arg_value()); 1853 __ Move(f16, fixed_right_arg_value());
2148 __ BranchF(&transition, NULL, ne, f14, f16); 1854 __ BranchF(&transition, NULL, ne, f14, f16);
2149 } 1855 }
2150 1856
2151 // We preserved a0 and a1 to be able to call runtime.
2152 // Save the left value on the stack.
2153 __ Push(t1, t0);
2154
2155 Label pop_and_call_runtime; 1857 Label pop_and_call_runtime;
2156 1858
2157 // Allocate a heap number to store the result. 1859 // Allocate a heap number to store the result.
2158 heap_number_result = s0; 1860 heap_number_result = s0;
2159 BinaryOpStub_GenerateHeapResultAllocation(masm, 1861 BinaryOpStub_GenerateHeapResultAllocation(masm,
2160 heap_number_result, 1862 heap_number_result,
2161 heap_number_map, 1863 heap_number_map,
2162 scratch1, 1864 scratch1,
2163 scratch2, 1865 scratch2,
2164 &pop_and_call_runtime, 1866 &pop_and_call_runtime,
2165 mode_); 1867 mode_);
2166 1868
2167 // Load the left value from the value saved on the stack.
2168 __ Pop(a1, a0);
2169
2170 // Call the C function to handle the double operation. 1869 // Call the C function to handle the double operation.
2171 FloatingPointHelper::CallCCodeForDoubleOperation( 1870 CallCCodeForDoubleOperation(masm, op_, heap_number_result, scratch1);
2172 masm, op_, heap_number_result, scratch1);
2173 if (FLAG_debug_code) { 1871 if (FLAG_debug_code) {
2174 __ stop("Unreachable code."); 1872 __ stop("Unreachable code.");
2175 } 1873 }
2176 1874
2177 __ bind(&pop_and_call_runtime); 1875 __ bind(&pop_and_call_runtime);
2178 __ Drop(2); 1876 __ Drop(2);
2179 __ Branch(&call_runtime); 1877 __ Branch(&call_runtime);
2180 } 1878 }
2181 1879
2182 break; 1880 break;
2183 } 1881 }
2184 1882
2185 case Token::BIT_OR: 1883 case Token::BIT_OR:
2186 case Token::BIT_XOR: 1884 case Token::BIT_XOR:
2187 case Token::BIT_AND: 1885 case Token::BIT_AND:
2188 case Token::SAR: 1886 case Token::SAR:
2189 case Token::SHR: 1887 case Token::SHR:
2190 case Token::SHL: { 1888 case Token::SHL: {
2191 Label return_heap_number; 1889 Label return_heap_number;
2192 Register scratch3 = t1;
2193 // Convert operands to 32-bit integers. Right in a2 and left in a3. The 1890 // Convert operands to 32-bit integers. Right in a2 and left in a3. The
2194 // registers a0 and a1 (right and left) are preserved for the runtime 1891 // registers a0 and a1 (right and left) are preserved for the runtime
2195 // call. 1892 // call.
2196 FloatingPointHelper::LoadNumberAsInt32(masm, 1893 __ LoadNumberAsInt32(
2197 left, 1894 left, a3, heap_number_map, scratch1, scratch2, f0, f2, &transition);
2198 a3, 1895 __ LoadNumberAsInt32(
2199 heap_number_map, 1896 right, a2, heap_number_map, scratch1, scratch2, f0, f2, &transition);
2200 scratch1,
2201 scratch2,
2202 scratch3,
2203 f0,
2204 f2,
2205 &transition);
2206 FloatingPointHelper::LoadNumberAsInt32(masm,
2207 right,
2208 a2,
2209 heap_number_map,
2210 scratch1,
2211 scratch2,
2212 scratch3,
2213 f0,
2214 f2,
2215 &transition);
2216 1897
2217 // The ECMA-262 standard specifies that, for shift operations, only the 1898 // The ECMA-262 standard specifies that, for shift operations, only the
2218 // 5 least significant bits of the shift value should be used. 1899 // 5 least significant bits of the shift value should be used.
2219 switch (op_) { 1900 switch (op_) {
2220 case Token::BIT_OR: 1901 case Token::BIT_OR:
2221 __ Or(a2, a3, Operand(a2)); 1902 __ Or(a2, a3, Operand(a2));
2222 break; 1903 break;
2223 case Token::BIT_XOR: 1904 case Token::BIT_XOR:
2224 __ Xor(a2, a3, Operand(a2)); 1905 __ Xor(a2, a3, Operand(a2));
2225 break; 1906 break;
(...skipping 4864 matching lines...) Expand 10 before | Expand all | Expand 10 after
7090 __ lw(t1, FieldMemOperand(a1, JSObject::kElementsOffset)); 6771 __ lw(t1, FieldMemOperand(a1, JSObject::kElementsOffset));
7091 __ sll(t2, a3, kPointerSizeLog2 - kSmiTagSize); 6772 __ sll(t2, a3, kPointerSizeLog2 - kSmiTagSize);
7092 __ Addu(t2, t1, t2); 6773 __ Addu(t2, t1, t2);
7093 __ sw(a0, FieldMemOperand(t2, FixedArray::kHeaderSize)); 6774 __ sw(a0, FieldMemOperand(t2, FixedArray::kHeaderSize));
7094 __ Ret(USE_DELAY_SLOT); 6775 __ Ret(USE_DELAY_SLOT);
7095 __ mov(v0, a0); 6776 __ mov(v0, a0);
7096 6777
7097 // Array literal has ElementsKind of FAST_*_DOUBLE_ELEMENTS. 6778 // Array literal has ElementsKind of FAST_*_DOUBLE_ELEMENTS.
7098 __ bind(&double_elements); 6779 __ bind(&double_elements);
7099 __ lw(t1, FieldMemOperand(a1, JSObject::kElementsOffset)); 6780 __ lw(t1, FieldMemOperand(a1, JSObject::kElementsOffset));
7100 __ StoreNumberToDoubleElements(a0, a3, 6781 __ StoreNumberToDoubleElements(a0, a3, t1, t3, t5, a2, &slow_elements);
7101 // Overwrites all regs after this.
7102 t1, t2, t3, t5, a2,
7103 &slow_elements);
7104 __ Ret(USE_DELAY_SLOT); 6782 __ Ret(USE_DELAY_SLOT);
7105 __ mov(v0, a0); 6783 __ mov(v0, a0);
7106 } 6784 }
7107 6785
7108 6786
7109 void StubFailureTrampolineStub::Generate(MacroAssembler* masm) { 6787 void StubFailureTrampolineStub::Generate(MacroAssembler* masm) {
7110 CEntryStub ces(1, fp_registers_ ? kSaveFPRegs : kDontSaveFPRegs); 6788 CEntryStub ces(1, fp_registers_ ? kSaveFPRegs : kDontSaveFPRegs);
7111 __ Call(ces.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); 6789 __ Call(ces.GetCode(masm->isolate()), RelocInfo::CODE_TARGET);
7112 int parameter_count_offset = 6790 int parameter_count_offset =
7113 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; 6791 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset;
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
7464 __ bind(&fast_elements_case); 7142 __ bind(&fast_elements_case);
7465 GenerateCase(masm, FAST_ELEMENTS); 7143 GenerateCase(masm, FAST_ELEMENTS);
7466 } 7144 }
7467 7145
7468 7146
7469 #undef __ 7147 #undef __
7470 7148
7471 } } // namespace v8::internal 7149 } } // namespace v8::internal
7472 7150
7473 #endif // V8_TARGET_ARCH_MIPS 7151 #endif // V8_TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « src/mips/code-stubs-mips.h ('k') | src/mips/ic-mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698