| OLD | NEW |
| 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 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 607 __ Ret(USE_DELAY_SLOT); | 607 __ Ret(USE_DELAY_SLOT); |
| 608 __ or_(exponent, exponent, source_); | 608 __ or_(exponent, exponent, source_); |
| 609 } | 609 } |
| 610 | 610 |
| 611 | 611 |
| 612 void FloatingPointHelper::LoadSmis(MacroAssembler* masm, | 612 void FloatingPointHelper::LoadSmis(MacroAssembler* masm, |
| 613 FloatingPointHelper::Destination destination, | 613 FloatingPointHelper::Destination destination, |
| 614 Register scratch1, | 614 Register scratch1, |
| 615 Register scratch2) { | 615 Register scratch2) { |
| 616 if (CpuFeatures::IsSupported(FPU)) { | 616 if (CpuFeatures::IsSupported(FPU)) { |
| 617 CpuFeatures::Scope scope(FPU); | 617 CpuFeatureScope scope(masm, FPU); |
| 618 __ sra(scratch1, a0, kSmiTagSize); | 618 __ sra(scratch1, a0, kSmiTagSize); |
| 619 __ mtc1(scratch1, f14); | 619 __ mtc1(scratch1, f14); |
| 620 __ cvt_d_w(f14, f14); | 620 __ cvt_d_w(f14, f14); |
| 621 __ sra(scratch1, a1, kSmiTagSize); | 621 __ sra(scratch1, a1, kSmiTagSize); |
| 622 __ mtc1(scratch1, f12); | 622 __ mtc1(scratch1, f12); |
| 623 __ cvt_d_w(f12, f12); | 623 __ cvt_d_w(f12, f12); |
| 624 if (destination == kCoreRegisters) { | 624 if (destination == kCoreRegisters) { |
| 625 __ Move(a2, a3, f14); | 625 __ Move(a2, a3, f14); |
| 626 __ Move(a0, a1, f12); | 626 __ Move(a0, a1, f12); |
| 627 } | 627 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 658 Label is_smi, done; | 658 Label is_smi, done; |
| 659 | 659 |
| 660 // Smi-check | 660 // Smi-check |
| 661 __ UntagAndJumpIfSmi(scratch1, object, &is_smi); | 661 __ UntagAndJumpIfSmi(scratch1, object, &is_smi); |
| 662 // Heap number check | 662 // Heap number check |
| 663 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number); | 663 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number); |
| 664 | 664 |
| 665 // Handle loading a double from a heap number. | 665 // Handle loading a double from a heap number. |
| 666 if (CpuFeatures::IsSupported(FPU) && | 666 if (CpuFeatures::IsSupported(FPU) && |
| 667 destination == kFPURegisters) { | 667 destination == kFPURegisters) { |
| 668 CpuFeatures::Scope scope(FPU); | 668 CpuFeatureScope scope(masm, FPU); |
| 669 // Load the double from tagged HeapNumber to double register. | 669 // Load the double from tagged HeapNumber to double register. |
| 670 | 670 |
| 671 // ARM uses a workaround here because of the unaligned HeapNumber | 671 // ARM uses a workaround here because of the unaligned HeapNumber |
| 672 // kValueOffset. On MIPS this workaround is built into ldc1 so there's no | 672 // kValueOffset. On MIPS this workaround is built into ldc1 so there's no |
| 673 // point in generating even more instructions. | 673 // point in generating even more instructions. |
| 674 __ ldc1(dst, FieldMemOperand(object, HeapNumber::kValueOffset)); | 674 __ ldc1(dst, FieldMemOperand(object, HeapNumber::kValueOffset)); |
| 675 } else { | 675 } else { |
| 676 ASSERT(destination == kCoreRegisters); | 676 ASSERT(destination == kCoreRegisters); |
| 677 // Load the double from heap number to dst1 and dst2 in double format. | 677 // Load the double from heap number to dst1 and dst2 in double format. |
| 678 __ lw(dst1, FieldMemOperand(object, HeapNumber::kValueOffset)); | 678 __ lw(dst1, FieldMemOperand(object, HeapNumber::kValueOffset)); |
| 679 __ lw(dst2, FieldMemOperand(object, | 679 __ lw(dst2, FieldMemOperand(object, |
| 680 HeapNumber::kValueOffset + kPointerSize)); | 680 HeapNumber::kValueOffset + kPointerSize)); |
| 681 } | 681 } |
| 682 __ Branch(&done); | 682 __ Branch(&done); |
| 683 | 683 |
| 684 // Handle loading a double from a smi. | 684 // Handle loading a double from a smi. |
| 685 __ bind(&is_smi); | 685 __ bind(&is_smi); |
| 686 if (CpuFeatures::IsSupported(FPU)) { | 686 if (CpuFeatures::IsSupported(FPU)) { |
| 687 CpuFeatures::Scope scope(FPU); | 687 CpuFeatureScope scope(masm, FPU); |
| 688 // Convert smi to double using FPU instructions. | 688 // Convert smi to double using FPU instructions. |
| 689 __ mtc1(scratch1, dst); | 689 __ mtc1(scratch1, dst); |
| 690 __ cvt_d_w(dst, dst); | 690 __ cvt_d_w(dst, dst); |
| 691 if (destination == kCoreRegisters) { | 691 if (destination == kCoreRegisters) { |
| 692 // Load the converted smi to dst1 and dst2 in double format. | 692 // Load the converted smi to dst1 and dst2 in double format. |
| 693 __ Move(dst1, dst2, dst); | 693 __ Move(dst1, dst2, dst); |
| 694 } | 694 } |
| 695 } else { | 695 } else { |
| 696 ASSERT(destination == kCoreRegisters); | 696 ASSERT(destination == kCoreRegisters); |
| 697 // Write smi to dst1 and dst2 double format. | 697 // Write smi to dst1 and dst2 double format. |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 753 Register dst_exponent, | 753 Register dst_exponent, |
| 754 Register scratch2, | 754 Register scratch2, |
| 755 FPURegister single_scratch) { | 755 FPURegister single_scratch) { |
| 756 ASSERT(!int_scratch.is(scratch2)); | 756 ASSERT(!int_scratch.is(scratch2)); |
| 757 ASSERT(!int_scratch.is(dst_mantissa)); | 757 ASSERT(!int_scratch.is(dst_mantissa)); |
| 758 ASSERT(!int_scratch.is(dst_exponent)); | 758 ASSERT(!int_scratch.is(dst_exponent)); |
| 759 | 759 |
| 760 Label done; | 760 Label done; |
| 761 | 761 |
| 762 if (CpuFeatures::IsSupported(FPU)) { | 762 if (CpuFeatures::IsSupported(FPU)) { |
| 763 CpuFeatures::Scope scope(FPU); | 763 CpuFeatureScope scope(masm, FPU); |
| 764 __ mtc1(int_scratch, single_scratch); | 764 __ mtc1(int_scratch, single_scratch); |
| 765 __ cvt_d_w(double_dst, single_scratch); | 765 __ cvt_d_w(double_dst, single_scratch); |
| 766 if (destination == kCoreRegisters) { | 766 if (destination == kCoreRegisters) { |
| 767 __ Move(dst_mantissa, dst_exponent, double_dst); | 767 __ Move(dst_mantissa, dst_exponent, double_dst); |
| 768 } | 768 } |
| 769 } else { | 769 } else { |
| 770 Label fewer_than_20_useful_bits; | 770 Label fewer_than_20_useful_bits; |
| 771 // Expected output: | 771 // Expected output: |
| 772 // | dst_exponent | dst_mantissa | | 772 // | dst_exponent | dst_mantissa | |
| 773 // | s | exp | mantissa | | 773 // | s | exp | mantissa | |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 855 __ Branch(&done); | 855 __ Branch(&done); |
| 856 | 856 |
| 857 __ bind(&obj_is_not_smi); | 857 __ bind(&obj_is_not_smi); |
| 858 __ AssertRootValue(heap_number_map, | 858 __ AssertRootValue(heap_number_map, |
| 859 Heap::kHeapNumberMapRootIndex, | 859 Heap::kHeapNumberMapRootIndex, |
| 860 "HeapNumberMap register clobbered."); | 860 "HeapNumberMap register clobbered."); |
| 861 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32); | 861 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32); |
| 862 | 862 |
| 863 // Load the number. | 863 // Load the number. |
| 864 if (CpuFeatures::IsSupported(FPU)) { | 864 if (CpuFeatures::IsSupported(FPU)) { |
| 865 CpuFeatures::Scope scope(FPU); | 865 CpuFeatureScope scope(masm, FPU); |
| 866 // Load the double value. | 866 // Load the double value. |
| 867 __ ldc1(double_dst, FieldMemOperand(object, HeapNumber::kValueOffset)); | 867 __ ldc1(double_dst, FieldMemOperand(object, HeapNumber::kValueOffset)); |
| 868 | 868 |
| 869 Register except_flag = scratch2; | 869 Register except_flag = scratch2; |
| 870 __ EmitFPUTruncate(kRoundToZero, | 870 __ EmitFPUTruncate(kRoundToZero, |
| 871 scratch1, | 871 scratch1, |
| 872 double_dst, | 872 double_dst, |
| 873 at, | 873 at, |
| 874 double_scratch, | 874 double_scratch, |
| 875 except_flag, | 875 except_flag, |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 952 | 952 |
| 953 __ AssertRootValue(heap_number_map, | 953 __ AssertRootValue(heap_number_map, |
| 954 Heap::kHeapNumberMapRootIndex, | 954 Heap::kHeapNumberMapRootIndex, |
| 955 "HeapNumberMap register clobbered."); | 955 "HeapNumberMap register clobbered."); |
| 956 | 956 |
| 957 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, &maybe_undefined); | 957 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, &maybe_undefined); |
| 958 | 958 |
| 959 // Object is a heap number. | 959 // Object is a heap number. |
| 960 // Convert the floating point value to a 32-bit integer. | 960 // Convert the floating point value to a 32-bit integer. |
| 961 if (CpuFeatures::IsSupported(FPU)) { | 961 if (CpuFeatures::IsSupported(FPU)) { |
| 962 CpuFeatures::Scope scope(FPU); | 962 CpuFeatureScope scope(masm, FPU); |
| 963 // Load the double value. | 963 // Load the double value. |
| 964 __ ldc1(double_scratch0, FieldMemOperand(object, HeapNumber::kValueOffset)); | 964 __ ldc1(double_scratch0, FieldMemOperand(object, HeapNumber::kValueOffset)); |
| 965 | 965 |
| 966 Register except_flag = scratch2; | 966 Register except_flag = scratch2; |
| 967 __ EmitFPUTruncate(kRoundToZero, | 967 __ EmitFPUTruncate(kRoundToZero, |
| 968 dst, | 968 dst, |
| 969 double_scratch0, | 969 double_scratch0, |
| 970 scratch1, | 970 scratch1, |
| 971 double_scratch1, | 971 double_scratch1, |
| 972 except_flag, | 972 except_flag, |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1090 // a3: Right value (sign, exponent, top of mantissa). | 1090 // a3: Right value (sign, exponent, top of mantissa). |
| 1091 | 1091 |
| 1092 // Assert that heap_number_result is saved. | 1092 // Assert that heap_number_result is saved. |
| 1093 // We currently always use s0 to pass it. | 1093 // We currently always use s0 to pass it. |
| 1094 ASSERT(heap_number_result.is(s0)); | 1094 ASSERT(heap_number_result.is(s0)); |
| 1095 | 1095 |
| 1096 // Push the current return address before the C call. | 1096 // Push the current return address before the C call. |
| 1097 __ push(ra); | 1097 __ push(ra); |
| 1098 __ PrepareCallCFunction(4, scratch); // Two doubles are 4 arguments. | 1098 __ PrepareCallCFunction(4, scratch); // Two doubles are 4 arguments. |
| 1099 if (!IsMipsSoftFloatABI) { | 1099 if (!IsMipsSoftFloatABI) { |
| 1100 CpuFeatures::Scope scope(FPU); | 1100 CpuFeatureScope scope(masm, FPU); |
| 1101 // We are not using MIPS FPU instructions, and parameters for the runtime | 1101 // We are not using MIPS FPU instructions, and parameters for the runtime |
| 1102 // function call are prepaired in a0-a3 registers, but function we are | 1102 // function call are prepaired in a0-a3 registers, but function we are |
| 1103 // calling is compiled with hard-float flag and expecting hard float ABI | 1103 // calling is compiled with hard-float flag and expecting hard float ABI |
| 1104 // (parameters in f12/f14 registers). We need to copy parameters from | 1104 // (parameters in f12/f14 registers). We need to copy parameters from |
| 1105 // a0-a3 registers to f12/f14 register pairs. | 1105 // a0-a3 registers to f12/f14 register pairs. |
| 1106 __ Move(f12, a0, a1); | 1106 __ Move(f12, a0, a1); |
| 1107 __ Move(f14, a2, a3); | 1107 __ Move(f14, a2, a3); |
| 1108 } | 1108 } |
| 1109 { | 1109 { |
| 1110 AllowExternalCallThatCantCauseGC scope(masm); | 1110 AllowExternalCallThatCantCauseGC scope(masm); |
| 1111 __ CallCFunction( | 1111 __ CallCFunction( |
| 1112 ExternalReference::double_fp_operation(op, masm->isolate()), 0, 2); | 1112 ExternalReference::double_fp_operation(op, masm->isolate()), 0, 2); |
| 1113 } | 1113 } |
| 1114 // Store answer in the overwritable heap number. | 1114 // Store answer in the overwritable heap number. |
| 1115 if (!IsMipsSoftFloatABI) { | 1115 if (!IsMipsSoftFloatABI) { |
| 1116 CpuFeatures::Scope scope(FPU); | 1116 CpuFeatureScope scope(masm, FPU); |
| 1117 // Double returned in register f0. | 1117 // Double returned in register f0. |
| 1118 __ sdc1(f0, FieldMemOperand(heap_number_result, HeapNumber::kValueOffset)); | 1118 __ sdc1(f0, FieldMemOperand(heap_number_result, HeapNumber::kValueOffset)); |
| 1119 } else { | 1119 } else { |
| 1120 // Double returned in registers v0 and v1. | 1120 // Double returned in registers v0 and v1. |
| 1121 __ sw(v1, FieldMemOperand(heap_number_result, HeapNumber::kExponentOffset)); | 1121 __ sw(v1, FieldMemOperand(heap_number_result, HeapNumber::kExponentOffset)); |
| 1122 __ sw(v0, FieldMemOperand(heap_number_result, HeapNumber::kMantissaOffset)); | 1122 __ sw(v0, FieldMemOperand(heap_number_result, HeapNumber::kMantissaOffset)); |
| 1123 } | 1123 } |
| 1124 // Place heap_number_result in v0 and return to the pushed return address. | 1124 // Place heap_number_result in v0 and return to the pushed return address. |
| 1125 __ pop(ra); | 1125 __ pop(ra); |
| 1126 __ Ret(USE_DELAY_SLOT); | 1126 __ Ret(USE_DELAY_SLOT); |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1330 __ mov(v0, lhs); | 1330 __ mov(v0, lhs); |
| 1331 } else { | 1331 } else { |
| 1332 // Smi compared non-strictly with a non-Smi non-heap-number. Call | 1332 // Smi compared non-strictly with a non-Smi non-heap-number. Call |
| 1333 // the runtime. | 1333 // the runtime. |
| 1334 __ Branch(slow, ne, t4, Operand(HEAP_NUMBER_TYPE)); | 1334 __ Branch(slow, ne, t4, Operand(HEAP_NUMBER_TYPE)); |
| 1335 } | 1335 } |
| 1336 | 1336 |
| 1337 // Rhs is a smi, lhs is a number. | 1337 // Rhs is a smi, lhs is a number. |
| 1338 // Convert smi rhs to double. | 1338 // Convert smi rhs to double. |
| 1339 if (CpuFeatures::IsSupported(FPU)) { | 1339 if (CpuFeatures::IsSupported(FPU)) { |
| 1340 CpuFeatures::Scope scope(FPU); | 1340 CpuFeatureScope scope(masm, FPU); |
| 1341 __ sra(at, rhs, kSmiTagSize); | 1341 __ sra(at, rhs, kSmiTagSize); |
| 1342 __ mtc1(at, f14); | 1342 __ mtc1(at, f14); |
| 1343 __ cvt_d_w(f14, f14); | 1343 __ cvt_d_w(f14, f14); |
| 1344 __ ldc1(f12, FieldMemOperand(lhs, HeapNumber::kValueOffset)); | 1344 __ ldc1(f12, FieldMemOperand(lhs, HeapNumber::kValueOffset)); |
| 1345 } else { | 1345 } else { |
| 1346 // Load lhs to a double in a2, a3. | 1346 // Load lhs to a double in a2, a3. |
| 1347 __ lw(a3, FieldMemOperand(lhs, HeapNumber::kValueOffset + 4)); | 1347 __ lw(a3, FieldMemOperand(lhs, HeapNumber::kValueOffset + 4)); |
| 1348 __ lw(a2, FieldMemOperand(lhs, HeapNumber::kValueOffset)); | 1348 __ lw(a2, FieldMemOperand(lhs, HeapNumber::kValueOffset)); |
| 1349 | 1349 |
| 1350 // Write Smi from rhs to a1 and a0 in double format. t5 is scratch. | 1350 // Write Smi from rhs to a1 and a0 in double format. t5 is scratch. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1369 __ li(v0, Operand(1)); | 1369 __ li(v0, Operand(1)); |
| 1370 } else { | 1370 } else { |
| 1371 // Smi compared non-strictly with a non-Smi non-heap-number. Call | 1371 // Smi compared non-strictly with a non-Smi non-heap-number. Call |
| 1372 // the runtime. | 1372 // the runtime. |
| 1373 __ Branch(slow, ne, t4, Operand(HEAP_NUMBER_TYPE)); | 1373 __ Branch(slow, ne, t4, Operand(HEAP_NUMBER_TYPE)); |
| 1374 } | 1374 } |
| 1375 | 1375 |
| 1376 // Lhs is a smi, rhs is a number. | 1376 // Lhs is a smi, rhs is a number. |
| 1377 // Convert smi lhs to double. | 1377 // Convert smi lhs to double. |
| 1378 if (CpuFeatures::IsSupported(FPU)) { | 1378 if (CpuFeatures::IsSupported(FPU)) { |
| 1379 CpuFeatures::Scope scope(FPU); | 1379 CpuFeatureScope scope(masm, FPU); |
| 1380 __ sra(at, lhs, kSmiTagSize); | 1380 __ sra(at, lhs, kSmiTagSize); |
| 1381 __ mtc1(at, f12); | 1381 __ mtc1(at, f12); |
| 1382 __ cvt_d_w(f12, f12); | 1382 __ cvt_d_w(f12, f12); |
| 1383 __ ldc1(f14, FieldMemOperand(rhs, HeapNumber::kValueOffset)); | 1383 __ ldc1(f14, FieldMemOperand(rhs, HeapNumber::kValueOffset)); |
| 1384 } else { | 1384 } else { |
| 1385 // Convert lhs to a double format. t5 is scratch. | 1385 // Convert lhs to a double format. t5 is scratch. |
| 1386 __ mov(t6, lhs); | 1386 __ mov(t6, lhs); |
| 1387 ConvertToDoubleStub stub2(a3, a2, t6, t5); | 1387 ConvertToDoubleStub stub2(a3, a2, t6, t5); |
| 1388 __ push(ra); | 1388 __ push(ra); |
| 1389 __ Call(stub2.GetCode(masm->isolate())); | 1389 __ Call(stub2.GetCode(masm->isolate())); |
| 1390 __ pop(ra); | 1390 __ pop(ra); |
| 1391 // Load rhs to a double in a1, a0. | 1391 // Load rhs to a double in a1, a0. |
| 1392 if (rhs.is(a0)) { | 1392 if (rhs.is(a0)) { |
| 1393 __ lw(a1, FieldMemOperand(rhs, HeapNumber::kValueOffset + 4)); | 1393 __ lw(a1, FieldMemOperand(rhs, HeapNumber::kValueOffset + 4)); |
| 1394 __ lw(a0, FieldMemOperand(rhs, HeapNumber::kValueOffset)); | 1394 __ lw(a0, FieldMemOperand(rhs, HeapNumber::kValueOffset)); |
| 1395 } else { | 1395 } else { |
| 1396 __ lw(a0, FieldMemOperand(rhs, HeapNumber::kValueOffset)); | 1396 __ lw(a0, FieldMemOperand(rhs, HeapNumber::kValueOffset)); |
| 1397 __ lw(a1, FieldMemOperand(rhs, HeapNumber::kValueOffset + 4)); | 1397 __ lw(a1, FieldMemOperand(rhs, HeapNumber::kValueOffset + 4)); |
| 1398 } | 1398 } |
| 1399 } | 1399 } |
| 1400 // Fall through to both_loaded_as_doubles. | 1400 // Fall through to both_loaded_as_doubles. |
| 1401 } | 1401 } |
| 1402 | 1402 |
| 1403 | 1403 |
| 1404 void EmitNanCheck(MacroAssembler* masm, Condition cc) { | 1404 void EmitNanCheck(MacroAssembler* masm, Condition cc) { |
| 1405 bool exp_first = (HeapNumber::kExponentOffset == HeapNumber::kValueOffset); | 1405 bool exp_first = (HeapNumber::kExponentOffset == HeapNumber::kValueOffset); |
| 1406 if (CpuFeatures::IsSupported(FPU)) { | 1406 if (CpuFeatures::IsSupported(FPU)) { |
| 1407 CpuFeatures::Scope scope(FPU); | 1407 CpuFeatureScope scope(masm, FPU); |
| 1408 // Lhs and rhs are already loaded to f12 and f14 register pairs. | 1408 // Lhs and rhs are already loaded to f12 and f14 register pairs. |
| 1409 __ Move(t0, t1, f14); | 1409 __ Move(t0, t1, f14); |
| 1410 __ Move(t2, t3, f12); | 1410 __ Move(t2, t3, f12); |
| 1411 } else { | 1411 } else { |
| 1412 // Lhs and rhs are already loaded to GP registers. | 1412 // Lhs and rhs are already loaded to GP registers. |
| 1413 __ mov(t0, a0); // a0 has LS 32 bits of rhs. | 1413 __ mov(t0, a0); // a0 has LS 32 bits of rhs. |
| 1414 __ mov(t1, a1); // a1 has MS 32 bits of rhs. | 1414 __ mov(t1, a1); // a1 has MS 32 bits of rhs. |
| 1415 __ mov(t2, a2); // a2 has LS 32 bits of lhs. | 1415 __ mov(t2, a2); // a2 has LS 32 bits of lhs. |
| 1416 __ mov(t3, a3); // a3 has MS 32 bits of lhs. | 1416 __ mov(t3, a3); // a3 has MS 32 bits of lhs. |
| 1417 } | 1417 } |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1464 // Call C routine that may not cause GC or other trouble. | 1464 // Call C routine that may not cause GC or other trouble. |
| 1465 // We use a call_was and return manually because we need arguments slots to | 1465 // We use a call_was and return manually because we need arguments slots to |
| 1466 // be freed. | 1466 // be freed. |
| 1467 | 1467 |
| 1468 Label return_result_not_equal, return_result_equal; | 1468 Label return_result_not_equal, return_result_equal; |
| 1469 if (cc == eq) { | 1469 if (cc == eq) { |
| 1470 // Doubles are not equal unless they have the same bit pattern. | 1470 // Doubles are not equal unless they have the same bit pattern. |
| 1471 // Exception: 0 and -0. | 1471 // Exception: 0 and -0. |
| 1472 bool exp_first = (HeapNumber::kExponentOffset == HeapNumber::kValueOffset); | 1472 bool exp_first = (HeapNumber::kExponentOffset == HeapNumber::kValueOffset); |
| 1473 if (CpuFeatures::IsSupported(FPU)) { | 1473 if (CpuFeatures::IsSupported(FPU)) { |
| 1474 CpuFeatures::Scope scope(FPU); | 1474 CpuFeatureScope scope(masm, FPU); |
| 1475 // Lhs and rhs are already loaded to f12 and f14 register pairs. | 1475 // Lhs and rhs are already loaded to f12 and f14 register pairs. |
| 1476 __ Move(t0, t1, f14); | 1476 __ Move(t0, t1, f14); |
| 1477 __ Move(t2, t3, f12); | 1477 __ Move(t2, t3, f12); |
| 1478 } else { | 1478 } else { |
| 1479 // Lhs and rhs are already loaded to GP registers. | 1479 // Lhs and rhs are already loaded to GP registers. |
| 1480 __ mov(t0, a0); // a0 has LS 32 bits of rhs. | 1480 __ mov(t0, a0); // a0 has LS 32 bits of rhs. |
| 1481 __ mov(t1, a1); // a1 has MS 32 bits of rhs. | 1481 __ mov(t1, a1); // a1 has MS 32 bits of rhs. |
| 1482 __ mov(t2, a2); // a2 has LS 32 bits of lhs. | 1482 __ mov(t2, a2); // a2 has LS 32 bits of lhs. |
| 1483 __ mov(t3, a3); // a3 has MS 32 bits of lhs. | 1483 __ mov(t3, a3); // a3 has MS 32 bits of lhs. |
| 1484 } | 1484 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1520 __ Move(f12, a0, a1); | 1520 __ Move(f12, a0, a1); |
| 1521 __ Move(f14, a2, a3); | 1521 __ Move(f14, a2, a3); |
| 1522 } | 1522 } |
| 1523 | 1523 |
| 1524 AllowExternalCallThatCantCauseGC scope(masm); | 1524 AllowExternalCallThatCantCauseGC scope(masm); |
| 1525 __ CallCFunction(ExternalReference::compare_doubles(masm->isolate()), | 1525 __ CallCFunction(ExternalReference::compare_doubles(masm->isolate()), |
| 1526 0, 2); | 1526 0, 2); |
| 1527 __ pop(ra); // Because this function returns int, result is in v0. | 1527 __ pop(ra); // Because this function returns int, result is in v0. |
| 1528 __ Ret(); | 1528 __ Ret(); |
| 1529 } else { | 1529 } else { |
| 1530 CpuFeatures::Scope scope(FPU); | 1530 CpuFeatureScope scope(masm, FPU); |
| 1531 Label equal, less_than; | 1531 Label equal, less_than; |
| 1532 __ BranchF(&equal, NULL, eq, f12, f14); | 1532 __ BranchF(&equal, NULL, eq, f12, f14); |
| 1533 __ BranchF(&less_than, NULL, lt, f12, f14); | 1533 __ BranchF(&less_than, NULL, lt, f12, f14); |
| 1534 | 1534 |
| 1535 // Not equal, not less, not NaN, must be greater. | 1535 // Not equal, not less, not NaN, must be greater. |
| 1536 | 1536 |
| 1537 __ li(v0, Operand(GREATER)); | 1537 __ li(v0, Operand(GREATER)); |
| 1538 __ Ret(); | 1538 __ Ret(); |
| 1539 | 1539 |
| 1540 __ bind(&equal); | 1540 __ bind(&equal); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1596 Label* slow) { | 1596 Label* slow) { |
| 1597 __ GetObjectType(lhs, a3, a2); | 1597 __ GetObjectType(lhs, a3, a2); |
| 1598 __ Branch(not_heap_numbers, ne, a2, Operand(HEAP_NUMBER_TYPE)); | 1598 __ Branch(not_heap_numbers, ne, a2, Operand(HEAP_NUMBER_TYPE)); |
| 1599 __ lw(a2, FieldMemOperand(rhs, HeapObject::kMapOffset)); | 1599 __ lw(a2, FieldMemOperand(rhs, HeapObject::kMapOffset)); |
| 1600 // If first was a heap number & second wasn't, go to slow case. | 1600 // If first was a heap number & second wasn't, go to slow case. |
| 1601 __ Branch(slow, ne, a3, Operand(a2)); | 1601 __ Branch(slow, ne, a3, Operand(a2)); |
| 1602 | 1602 |
| 1603 // Both are heap numbers. Load them up then jump to the code we have | 1603 // Both are heap numbers. Load them up then jump to the code we have |
| 1604 // for that. | 1604 // for that. |
| 1605 if (CpuFeatures::IsSupported(FPU)) { | 1605 if (CpuFeatures::IsSupported(FPU)) { |
| 1606 CpuFeatures::Scope scope(FPU); | 1606 CpuFeatureScope scope(masm, FPU); |
| 1607 __ ldc1(f12, FieldMemOperand(lhs, HeapNumber::kValueOffset)); | 1607 __ ldc1(f12, FieldMemOperand(lhs, HeapNumber::kValueOffset)); |
| 1608 __ ldc1(f14, FieldMemOperand(rhs, HeapNumber::kValueOffset)); | 1608 __ ldc1(f14, FieldMemOperand(rhs, HeapNumber::kValueOffset)); |
| 1609 } else { | 1609 } else { |
| 1610 __ lw(a2, FieldMemOperand(lhs, HeapNumber::kValueOffset)); | 1610 __ lw(a2, FieldMemOperand(lhs, HeapNumber::kValueOffset)); |
| 1611 __ lw(a3, FieldMemOperand(lhs, HeapNumber::kValueOffset + 4)); | 1611 __ lw(a3, FieldMemOperand(lhs, HeapNumber::kValueOffset + 4)); |
| 1612 if (rhs.is(a0)) { | 1612 if (rhs.is(a0)) { |
| 1613 __ lw(a1, FieldMemOperand(rhs, HeapNumber::kValueOffset + 4)); | 1613 __ lw(a1, FieldMemOperand(rhs, HeapNumber::kValueOffset + 4)); |
| 1614 __ lw(a0, FieldMemOperand(rhs, HeapNumber::kValueOffset)); | 1614 __ lw(a0, FieldMemOperand(rhs, HeapNumber::kValueOffset)); |
| 1615 } else { | 1615 } else { |
| 1616 __ lw(a0, FieldMemOperand(rhs, HeapNumber::kValueOffset)); | 1616 __ lw(a0, FieldMemOperand(rhs, HeapNumber::kValueOffset)); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1691 // Calculate the entry in the number string cache. The hash value in the | 1691 // Calculate the entry in the number string cache. The hash value in the |
| 1692 // number string cache for smis is just the smi value, and the hash for | 1692 // number string cache for smis is just the smi value, and the hash for |
| 1693 // doubles is the xor of the upper and lower words. See | 1693 // doubles is the xor of the upper and lower words. See |
| 1694 // Heap::GetNumberStringCache. | 1694 // Heap::GetNumberStringCache. |
| 1695 Isolate* isolate = masm->isolate(); | 1695 Isolate* isolate = masm->isolate(); |
| 1696 Label is_smi; | 1696 Label is_smi; |
| 1697 Label load_result_from_cache; | 1697 Label load_result_from_cache; |
| 1698 if (!object_is_smi) { | 1698 if (!object_is_smi) { |
| 1699 __ JumpIfSmi(object, &is_smi); | 1699 __ JumpIfSmi(object, &is_smi); |
| 1700 if (CpuFeatures::IsSupported(FPU)) { | 1700 if (CpuFeatures::IsSupported(FPU)) { |
| 1701 CpuFeatures::Scope scope(FPU); | 1701 CpuFeatureScope scope(masm, FPU); |
| 1702 __ CheckMap(object, | 1702 __ CheckMap(object, |
| 1703 scratch1, | 1703 scratch1, |
| 1704 Heap::kHeapNumberMapRootIndex, | 1704 Heap::kHeapNumberMapRootIndex, |
| 1705 not_found, | 1705 not_found, |
| 1706 DONT_DO_SMI_CHECK); | 1706 DONT_DO_SMI_CHECK); |
| 1707 | 1707 |
| 1708 STATIC_ASSERT(8 == kDoubleSize); | 1708 STATIC_ASSERT(8 == kDoubleSize); |
| 1709 __ Addu(scratch1, | 1709 __ Addu(scratch1, |
| 1710 object, | 1710 object, |
| 1711 Operand(HeapNumber::kValueOffset - kHeapObjectTag)); | 1711 Operand(HeapNumber::kValueOffset - kHeapObjectTag)); |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1844 EmitSmiNonsmiComparison(masm, lhs, rhs, | 1844 EmitSmiNonsmiComparison(masm, lhs, rhs, |
| 1845 &both_loaded_as_doubles, &slow, strict()); | 1845 &both_loaded_as_doubles, &slow, strict()); |
| 1846 | 1846 |
| 1847 __ bind(&both_loaded_as_doubles); | 1847 __ bind(&both_loaded_as_doubles); |
| 1848 // f12, f14 are the double representations of the left hand side | 1848 // f12, f14 are the double representations of the left hand side |
| 1849 // and the right hand side if we have FPU. Otherwise a2, a3 represent | 1849 // and the right hand side if we have FPU. Otherwise a2, a3 represent |
| 1850 // left hand side and a0, a1 represent right hand side. | 1850 // left hand side and a0, a1 represent right hand side. |
| 1851 | 1851 |
| 1852 Isolate* isolate = masm->isolate(); | 1852 Isolate* isolate = masm->isolate(); |
| 1853 if (CpuFeatures::IsSupported(FPU)) { | 1853 if (CpuFeatures::IsSupported(FPU)) { |
| 1854 CpuFeatures::Scope scope(FPU); | 1854 CpuFeatureScope scope(masm, FPU); |
| 1855 Label nan; | 1855 Label nan; |
| 1856 __ li(t0, Operand(LESS)); | 1856 __ li(t0, Operand(LESS)); |
| 1857 __ li(t1, Operand(GREATER)); | 1857 __ li(t1, Operand(GREATER)); |
| 1858 __ li(t2, Operand(EQUAL)); | 1858 __ li(t2, Operand(EQUAL)); |
| 1859 | 1859 |
| 1860 // Check if either rhs or lhs is NaN. | 1860 // Check if either rhs or lhs is NaN. |
| 1861 __ BranchF(NULL, &nan, eq, f12, f14); | 1861 __ BranchF(NULL, &nan, eq, f12, f14); |
| 1862 | 1862 |
| 1863 // Check if LESS condition is satisfied. If true, move conditionally | 1863 // Check if LESS condition is satisfied. If true, move conditionally |
| 1864 // result to v0. | 1864 // result to v0. |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1979 | 1979 |
| 1980 __ bind(&miss); | 1980 __ bind(&miss); |
| 1981 GenerateMiss(masm); | 1981 GenerateMiss(masm); |
| 1982 } | 1982 } |
| 1983 | 1983 |
| 1984 | 1984 |
| 1985 // The stub expects its argument in the tos_ register and returns its result in | 1985 // The stub expects its argument in the tos_ register and returns its result in |
| 1986 // it, too: zero for false, and a non-zero value for true. | 1986 // it, too: zero for false, and a non-zero value for true. |
| 1987 void ToBooleanStub::Generate(MacroAssembler* masm) { | 1987 void ToBooleanStub::Generate(MacroAssembler* masm) { |
| 1988 // This stub uses FPU instructions. | 1988 // This stub uses FPU instructions. |
| 1989 CpuFeatures::Scope scope(FPU); | 1989 CpuFeatureScope scope(masm, FPU); |
| 1990 | 1990 |
| 1991 Label patch; | 1991 Label patch; |
| 1992 const Register map = t5.is(tos_) ? t3 : t5; | 1992 const Register map = t5.is(tos_) ? t3 : t5; |
| 1993 | 1993 |
| 1994 // undefined -> false. | 1994 // undefined -> false. |
| 1995 CheckOddball(masm, UNDEFINED, Heap::kUndefinedValueRootIndex, false); | 1995 CheckOddball(masm, UNDEFINED, Heap::kUndefinedValueRootIndex, false); |
| 1996 | 1996 |
| 1997 // Boolean -> its value. | 1997 // Boolean -> its value. |
| 1998 CheckOddball(masm, BOOLEAN, Heap::kFalseValueRootIndex, false); | 1998 CheckOddball(masm, BOOLEAN, Heap::kFalseValueRootIndex, false); |
| 1999 CheckOddball(masm, BOOLEAN, Heap::kTrueValueRootIndex, true); | 1999 CheckOddball(masm, BOOLEAN, Heap::kTrueValueRootIndex, true); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2094 1); | 2094 1); |
| 2095 } | 2095 } |
| 2096 | 2096 |
| 2097 | 2097 |
| 2098 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { | 2098 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { |
| 2099 // We don't allow a GC during a store buffer overflow so there is no need to | 2099 // We don't allow a GC during a store buffer overflow so there is no need to |
| 2100 // store the registers in any particular way, but we do have to store and | 2100 // store the registers in any particular way, but we do have to store and |
| 2101 // restore them. | 2101 // restore them. |
| 2102 __ MultiPush(kJSCallerSaved | ra.bit()); | 2102 __ MultiPush(kJSCallerSaved | ra.bit()); |
| 2103 if (save_doubles_ == kSaveFPRegs) { | 2103 if (save_doubles_ == kSaveFPRegs) { |
| 2104 CpuFeatures::Scope scope(FPU); | 2104 CpuFeatureScope scope(masm, FPU); |
| 2105 __ MultiPushFPU(kCallerSavedFPU); | 2105 __ MultiPushFPU(kCallerSavedFPU); |
| 2106 } | 2106 } |
| 2107 const int argument_count = 1; | 2107 const int argument_count = 1; |
| 2108 const int fp_argument_count = 0; | 2108 const int fp_argument_count = 0; |
| 2109 const Register scratch = a1; | 2109 const Register scratch = a1; |
| 2110 | 2110 |
| 2111 AllowExternalCallThatCantCauseGC scope(masm); | 2111 AllowExternalCallThatCantCauseGC scope(masm); |
| 2112 __ PrepareCallCFunction(argument_count, fp_argument_count, scratch); | 2112 __ PrepareCallCFunction(argument_count, fp_argument_count, scratch); |
| 2113 __ li(a0, Operand(ExternalReference::isolate_address())); | 2113 __ li(a0, Operand(ExternalReference::isolate_address())); |
| 2114 __ CallCFunction( | 2114 __ CallCFunction( |
| 2115 ExternalReference::store_buffer_overflow_function(masm->isolate()), | 2115 ExternalReference::store_buffer_overflow_function(masm->isolate()), |
| 2116 argument_count); | 2116 argument_count); |
| 2117 if (save_doubles_ == kSaveFPRegs) { | 2117 if (save_doubles_ == kSaveFPRegs) { |
| 2118 CpuFeatures::Scope scope(FPU); | 2118 CpuFeatureScope scope(masm, FPU); |
| 2119 __ MultiPopFPU(kCallerSavedFPU); | 2119 __ MultiPopFPU(kCallerSavedFPU); |
| 2120 } | 2120 } |
| 2121 | 2121 |
| 2122 __ MultiPop(kJSCallerSaved | ra.bit()); | 2122 __ MultiPop(kJSCallerSaved | ra.bit()); |
| 2123 __ Ret(); | 2123 __ Ret(); |
| 2124 } | 2124 } |
| 2125 | 2125 |
| 2126 | 2126 |
| 2127 void UnaryOpStub::PrintName(StringStream* stream) { | 2127 void UnaryOpStub::PrintName(StringStream* stream) { |
| 2128 const char* op_name = Token::Name(op_); | 2128 const char* op_name = Token::Name(op_); |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2341 __ ConvertToInt32(v0, a1, a3, t0, f0, &impossible); | 2341 __ ConvertToInt32(v0, a1, a3, t0, f0, &impossible); |
| 2342 // Negate the result. | 2342 // Negate the result. |
| 2343 __ Xor(a1, a1, -1); | 2343 __ Xor(a1, a1, -1); |
| 2344 | 2344 |
| 2345 __ bind(&heapnumber_allocated); | 2345 __ bind(&heapnumber_allocated); |
| 2346 __ mov(v0, a2); // Move newly allocated heap number to v0. | 2346 __ mov(v0, a2); // Move newly allocated heap number to v0. |
| 2347 } | 2347 } |
| 2348 | 2348 |
| 2349 if (CpuFeatures::IsSupported(FPU)) { | 2349 if (CpuFeatures::IsSupported(FPU)) { |
| 2350 // Convert the int32 in a1 to the heap number in v0. a2 is corrupted. | 2350 // Convert the int32 in a1 to the heap number in v0. a2 is corrupted. |
| 2351 CpuFeatures::Scope scope(FPU); | 2351 CpuFeatureScope scope(masm, FPU); |
| 2352 __ mtc1(a1, f0); | 2352 __ mtc1(a1, f0); |
| 2353 __ cvt_d_w(f0, f0); | 2353 __ cvt_d_w(f0, f0); |
| 2354 __ sdc1(f0, FieldMemOperand(v0, HeapNumber::kValueOffset)); | 2354 __ sdc1(f0, FieldMemOperand(v0, HeapNumber::kValueOffset)); |
| 2355 __ Ret(); | 2355 __ Ret(); |
| 2356 } else { | 2356 } else { |
| 2357 // WriteInt32ToHeapNumberStub does not trigger GC, so we do not | 2357 // WriteInt32ToHeapNumberStub does not trigger GC, so we do not |
| 2358 // have to set up a frame. | 2358 // have to set up a frame. |
| 2359 WriteInt32ToHeapNumberStub stub(a1, v0, a2, a3); | 2359 WriteInt32ToHeapNumberStub stub(a1, v0, a2, a3); |
| 2360 __ Jump(stub.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); | 2360 __ Jump(stub.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); |
| 2361 } | 2361 } |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2686 masm, destination, left, f12, a0, a1, heap_number_map, | 2686 masm, destination, left, f12, a0, a1, heap_number_map, |
| 2687 scratch1, scratch2, fail); | 2687 scratch1, scratch2, fail); |
| 2688 } | 2688 } |
| 2689 } | 2689 } |
| 2690 | 2690 |
| 2691 // Calculate the result. | 2691 // Calculate the result. |
| 2692 if (destination == FloatingPointHelper::kFPURegisters) { | 2692 if (destination == FloatingPointHelper::kFPURegisters) { |
| 2693 // Using FPU registers: | 2693 // Using FPU registers: |
| 2694 // f12: Left value. | 2694 // f12: Left value. |
| 2695 // f14: Right value. | 2695 // f14: Right value. |
| 2696 CpuFeatures::Scope scope(FPU); | 2696 CpuFeatureScope scope(masm, FPU); |
| 2697 switch (op) { | 2697 switch (op) { |
| 2698 case Token::ADD: | 2698 case Token::ADD: |
| 2699 __ add_d(f10, f12, f14); | 2699 __ add_d(f10, f12, f14); |
| 2700 break; | 2700 break; |
| 2701 case Token::SUB: | 2701 case Token::SUB: |
| 2702 __ sub_d(f10, f12, f14); | 2702 __ sub_d(f10, f12, f14); |
| 2703 break; | 2703 break; |
| 2704 case Token::MUL: | 2704 case Token::MUL: |
| 2705 __ mul_d(f10, f12, f14); | 2705 __ mul_d(f10, f12, f14); |
| 2706 break; | 2706 break; |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2818 // a2: Answer as signed int32. | 2818 // a2: Answer as signed int32. |
| 2819 // t1: Heap number to write answer into. | 2819 // t1: Heap number to write answer into. |
| 2820 | 2820 |
| 2821 // Nothing can go wrong now, so move the heap number to v0, which is the | 2821 // Nothing can go wrong now, so move the heap number to v0, which is the |
| 2822 // result. | 2822 // result. |
| 2823 __ mov(v0, t1); | 2823 __ mov(v0, t1); |
| 2824 | 2824 |
| 2825 if (CpuFeatures::IsSupported(FPU)) { | 2825 if (CpuFeatures::IsSupported(FPU)) { |
| 2826 // Convert the int32 in a2 to the heap number in a0. As | 2826 // Convert the int32 in a2 to the heap number in a0. As |
| 2827 // mentioned above SHR needs to always produce a positive result. | 2827 // mentioned above SHR needs to always produce a positive result. |
| 2828 CpuFeatures::Scope scope(FPU); | 2828 CpuFeatureScope scope(masm, FPU); |
| 2829 __ mtc1(a2, f0); | 2829 __ mtc1(a2, f0); |
| 2830 if (op == Token::SHR) { | 2830 if (op == Token::SHR) { |
| 2831 __ Cvt_d_uw(f0, f0, f22); | 2831 __ Cvt_d_uw(f0, f0, f22); |
| 2832 } else { | 2832 } else { |
| 2833 __ cvt_d_w(f0, f0); | 2833 __ cvt_d_w(f0, f0); |
| 2834 } | 2834 } |
| 2835 // ARM uses a workaround here because of the unaligned HeapNumber | 2835 // ARM uses a workaround here because of the unaligned HeapNumber |
| 2836 // kValueOffset. On MIPS this workaround is built into sdc1 so | 2836 // kValueOffset. On MIPS this workaround is built into sdc1 so |
| 2837 // there's no point in generating even more instructions. | 2837 // there's no point in generating even more instructions. |
| 2838 __ sdc1(f0, FieldMemOperand(v0, HeapNumber::kValueOffset)); | 2838 __ sdc1(f0, FieldMemOperand(v0, HeapNumber::kValueOffset)); |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3013 f16, | 3013 f16, |
| 3014 t0, | 3014 t0, |
| 3015 t1, | 3015 t1, |
| 3016 heap_number_map, | 3016 heap_number_map, |
| 3017 scratch1, | 3017 scratch1, |
| 3018 scratch2, | 3018 scratch2, |
| 3019 f2, | 3019 f2, |
| 3020 &transition); | 3020 &transition); |
| 3021 | 3021 |
| 3022 if (destination == FloatingPointHelper::kFPURegisters) { | 3022 if (destination == FloatingPointHelper::kFPURegisters) { |
| 3023 CpuFeatures::Scope scope(FPU); | 3023 CpuFeatureScope scope(masm, FPU); |
| 3024 Label return_heap_number; | 3024 Label return_heap_number; |
| 3025 switch (op_) { | 3025 switch (op_) { |
| 3026 case Token::ADD: | 3026 case Token::ADD: |
| 3027 __ add_d(f10, f12, f14); | 3027 __ add_d(f10, f12, f14); |
| 3028 break; | 3028 break; |
| 3029 case Token::SUB: | 3029 case Token::SUB: |
| 3030 __ sub_d(f10, f12, f14); | 3030 __ sub_d(f10, f12, f14); |
| 3031 break; | 3031 break; |
| 3032 case Token::MUL: | 3032 case Token::MUL: |
| 3033 __ mul_d(f10, f12, f14); | 3033 __ mul_d(f10, f12, f14); |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3227 heap_number_result = t1; | 3227 heap_number_result = t1; |
| 3228 BinaryOpStub_GenerateHeapResultAllocation(masm, | 3228 BinaryOpStub_GenerateHeapResultAllocation(masm, |
| 3229 heap_number_result, | 3229 heap_number_result, |
| 3230 heap_number_map, | 3230 heap_number_map, |
| 3231 scratch1, | 3231 scratch1, |
| 3232 scratch2, | 3232 scratch2, |
| 3233 &call_runtime, | 3233 &call_runtime, |
| 3234 mode_); | 3234 mode_); |
| 3235 | 3235 |
| 3236 if (CpuFeatures::IsSupported(FPU)) { | 3236 if (CpuFeatures::IsSupported(FPU)) { |
| 3237 CpuFeatures::Scope scope(FPU); | 3237 CpuFeatureScope scope(masm, FPU); |
| 3238 | 3238 |
| 3239 if (op_ != Token::SHR) { | 3239 if (op_ != Token::SHR) { |
| 3240 // Convert the result to a floating point value. | 3240 // Convert the result to a floating point value. |
| 3241 __ mtc1(a2, double_scratch); | 3241 __ mtc1(a2, double_scratch); |
| 3242 __ cvt_d_w(double_scratch, double_scratch); | 3242 __ cvt_d_w(double_scratch, double_scratch); |
| 3243 } else { | 3243 } else { |
| 3244 // The result must be interpreted as an unsigned 32-bit integer. | 3244 // The result must be interpreted as an unsigned 32-bit integer. |
| 3245 __ mtc1(a2, double_scratch); | 3245 __ mtc1(a2, double_scratch); |
| 3246 __ Cvt_d_uw(double_scratch, double_scratch, single_scratch); | 3246 __ Cvt_d_uw(double_scratch, double_scratch, single_scratch); |
| 3247 } | 3247 } |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3431 Label input_not_smi; | 3431 Label input_not_smi; |
| 3432 Label loaded; | 3432 Label loaded; |
| 3433 Label calculate; | 3433 Label calculate; |
| 3434 Label invalid_cache; | 3434 Label invalid_cache; |
| 3435 const Register scratch0 = t5; | 3435 const Register scratch0 = t5; |
| 3436 const Register scratch1 = t3; | 3436 const Register scratch1 = t3; |
| 3437 const Register cache_entry = a0; | 3437 const Register cache_entry = a0; |
| 3438 const bool tagged = (argument_type_ == TAGGED); | 3438 const bool tagged = (argument_type_ == TAGGED); |
| 3439 | 3439 |
| 3440 if (CpuFeatures::IsSupported(FPU)) { | 3440 if (CpuFeatures::IsSupported(FPU)) { |
| 3441 CpuFeatures::Scope scope(FPU); | 3441 CpuFeatureScope scope(masm, FPU); |
| 3442 | 3442 |
| 3443 if (tagged) { | 3443 if (tagged) { |
| 3444 // Argument is a number and is on stack and in a0. | 3444 // Argument is a number and is on stack and in a0. |
| 3445 // Load argument and check if it is a smi. | 3445 // Load argument and check if it is a smi. |
| 3446 __ JumpIfNotSmi(a0, &input_not_smi); | 3446 __ JumpIfNotSmi(a0, &input_not_smi); |
| 3447 | 3447 |
| 3448 // Input is a smi. Convert to double and load the low and high words | 3448 // Input is a smi. Convert to double and load the low and high words |
| 3449 // of the double into a2, a3. | 3449 // of the double into a2, a3. |
| 3450 __ sra(t0, a0, kSmiTagSize); | 3450 __ sra(t0, a0, kSmiTagSize); |
| 3451 __ mtc1(t0, f4); | 3451 __ mtc1(t0, f4); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3541 __ IncrementCounter( | 3541 __ IncrementCounter( |
| 3542 counters->transcendental_cache_miss(), 1, scratch0, scratch1); | 3542 counters->transcendental_cache_miss(), 1, scratch0, scratch1); |
| 3543 if (tagged) { | 3543 if (tagged) { |
| 3544 __ bind(&invalid_cache); | 3544 __ bind(&invalid_cache); |
| 3545 __ TailCallExternalReference(ExternalReference(RuntimeFunction(), | 3545 __ TailCallExternalReference(ExternalReference(RuntimeFunction(), |
| 3546 masm->isolate()), | 3546 masm->isolate()), |
| 3547 1, | 3547 1, |
| 3548 1); | 3548 1); |
| 3549 } else { | 3549 } else { |
| 3550 ASSERT(CpuFeatures::IsSupported(FPU)); | 3550 ASSERT(CpuFeatures::IsSupported(FPU)); |
| 3551 CpuFeatures::Scope scope(FPU); | 3551 CpuFeatureScope scope(masm, FPU); |
| 3552 | 3552 |
| 3553 Label no_update; | 3553 Label no_update; |
| 3554 Label skip_cache; | 3554 Label skip_cache; |
| 3555 | 3555 |
| 3556 // Call C function to calculate the result and update the cache. | 3556 // Call C function to calculate the result and update the cache. |
| 3557 // a0: precalculated cache entry address. | 3557 // a0: precalculated cache entry address. |
| 3558 // a2 and a3: parts of the double value. | 3558 // a2 and a3: parts of the double value. |
| 3559 // Store a0, a2 and a3 on stack for later before calling C function. | 3559 // Store a0, a2 and a3 on stack for later before calling C function. |
| 3560 __ Push(a3, a2, cache_entry); | 3560 __ Push(a3, a2, cache_entry); |
| 3561 GenerateCallCFunction(masm, scratch0); | 3561 GenerateCallCFunction(masm, scratch0); |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3669 __ TailCallRuntime(Runtime::kStackGuard, 0, 1); | 3669 __ TailCallRuntime(Runtime::kStackGuard, 0, 1); |
| 3670 } | 3670 } |
| 3671 | 3671 |
| 3672 | 3672 |
| 3673 void InterruptStub::Generate(MacroAssembler* masm) { | 3673 void InterruptStub::Generate(MacroAssembler* masm) { |
| 3674 __ TailCallRuntime(Runtime::kInterrupt, 0, 1); | 3674 __ TailCallRuntime(Runtime::kInterrupt, 0, 1); |
| 3675 } | 3675 } |
| 3676 | 3676 |
| 3677 | 3677 |
| 3678 void MathPowStub::Generate(MacroAssembler* masm) { | 3678 void MathPowStub::Generate(MacroAssembler* masm) { |
| 3679 CpuFeatures::Scope fpu_scope(FPU); | 3679 CpuFeatureScope fpu_scope(masm, FPU); |
| 3680 const Register base = a1; | 3680 const Register base = a1; |
| 3681 const Register exponent = a2; | 3681 const Register exponent = a2; |
| 3682 const Register heapnumbermap = t1; | 3682 const Register heapnumbermap = t1; |
| 3683 const Register heapnumber = v0; | 3683 const Register heapnumber = v0; |
| 3684 const DoubleRegister double_base = f2; | 3684 const DoubleRegister double_base = f2; |
| 3685 const DoubleRegister double_exponent = f4; | 3685 const DoubleRegister double_exponent = f4; |
| 3686 const DoubleRegister double_result = f0; | 3686 const DoubleRegister double_result = f0; |
| 3687 const DoubleRegister double_scratch = f6; | 3687 const DoubleRegister double_scratch = f6; |
| 3688 const FPURegister single_scratch = f8; | 3688 const FPURegister single_scratch = f8; |
| 3689 const Register scratch = t5; | 3689 const Register scratch = t5; |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3912 | 3912 |
| 3913 void CodeStub::GenerateFPStubs(Isolate* isolate) { | 3913 void CodeStub::GenerateFPStubs(Isolate* isolate) { |
| 3914 SaveFPRegsMode mode = CpuFeatures::IsSupported(FPU) | 3914 SaveFPRegsMode mode = CpuFeatures::IsSupported(FPU) |
| 3915 ? kSaveFPRegs | 3915 ? kSaveFPRegs |
| 3916 : kDontSaveFPRegs; | 3916 : kDontSaveFPRegs; |
| 3917 CEntryStub save_doubles(1, mode); | 3917 CEntryStub save_doubles(1, mode); |
| 3918 StoreBufferOverflowStub stub(mode); | 3918 StoreBufferOverflowStub stub(mode); |
| 3919 // These stubs might already be in the snapshot, detect that and don't | 3919 // These stubs might already be in the snapshot, detect that and don't |
| 3920 // regenerate, which would lead to code stub initialization state being messed | 3920 // regenerate, which would lead to code stub initialization state being messed |
| 3921 // up. | 3921 // up. |
| 3922 Code* save_doubles_code = NULL; | 3922 Code* save_doubles_code; |
| 3923 Code* store_buffer_overflow_code = NULL; | 3923 if (!save_doubles.FindCodeInCache(&save_doubles_code, isolate)) { |
| 3924 if (!save_doubles.FindCodeInCache(&save_doubles_code, ISOLATE)) { | 3924 save_doubles_code = *save_doubles.GetCode(isolate); |
| 3925 if (CpuFeatures::IsSupported(FPU)) { | |
| 3926 CpuFeatures::Scope scope2(FPU); | |
| 3927 save_doubles_code = *save_doubles.GetCode(isolate); | |
| 3928 store_buffer_overflow_code = *stub.GetCode(isolate); | |
| 3929 } else { | |
| 3930 save_doubles_code = *save_doubles.GetCode(isolate); | |
| 3931 store_buffer_overflow_code = *stub.GetCode(isolate); | |
| 3932 } | |
| 3933 save_doubles_code->set_is_pregenerated(true); | 3925 save_doubles_code->set_is_pregenerated(true); |
| 3926 |
| 3927 Code* store_buffer_overflow_code = *stub.GetCode(isolate); |
| 3934 store_buffer_overflow_code->set_is_pregenerated(true); | 3928 store_buffer_overflow_code->set_is_pregenerated(true); |
| 3935 } | 3929 } |
| 3936 ISOLATE->set_fp_stubs_generated(true); | 3930 isolate->set_fp_stubs_generated(true); |
| 3937 } | 3931 } |
| 3938 | 3932 |
| 3939 | 3933 |
| 3940 void CEntryStub::GenerateAheadOfTime(Isolate* isolate) { | 3934 void CEntryStub::GenerateAheadOfTime(Isolate* isolate) { |
| 3941 CEntryStub stub(1, kDontSaveFPRegs); | 3935 CEntryStub stub(1, kDontSaveFPRegs); |
| 3942 Handle<Code> code = stub.GetCode(isolate); | 3936 Handle<Code> code = stub.GetCode(isolate); |
| 3943 code->set_is_pregenerated(true); | 3937 code->set_is_pregenerated(true); |
| 3944 } | 3938 } |
| 3945 | 3939 |
| 3946 | 3940 |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4182 // a3: argc | 4176 // a3: argc |
| 4183 // | 4177 // |
| 4184 // Stack: | 4178 // Stack: |
| 4185 // 4 args slots | 4179 // 4 args slots |
| 4186 // args | 4180 // args |
| 4187 | 4181 |
| 4188 // Save callee saved registers on the stack. | 4182 // Save callee saved registers on the stack. |
| 4189 __ MultiPush(kCalleeSaved | ra.bit()); | 4183 __ MultiPush(kCalleeSaved | ra.bit()); |
| 4190 | 4184 |
| 4191 if (CpuFeatures::IsSupported(FPU)) { | 4185 if (CpuFeatures::IsSupported(FPU)) { |
| 4192 CpuFeatures::Scope scope(FPU); | 4186 CpuFeatureScope scope(masm, FPU); |
| 4193 // Save callee-saved FPU registers. | 4187 // Save callee-saved FPU registers. |
| 4194 __ MultiPushFPU(kCalleeSavedFPU); | 4188 __ MultiPushFPU(kCalleeSavedFPU); |
| 4195 // Set up the reserved register for 0.0. | 4189 // Set up the reserved register for 0.0. |
| 4196 __ Move(kDoubleRegZero, 0.0); | 4190 __ Move(kDoubleRegZero, 0.0); |
| 4197 } | 4191 } |
| 4198 | 4192 |
| 4199 | 4193 |
| 4200 // Load argv in s0 register. | 4194 // Load argv in s0 register. |
| 4201 int offset_to_argv = (kNumCalleeSaved + 1) * kPointerSize; | 4195 int offset_to_argv = (kNumCalleeSaved + 1) * kPointerSize; |
| 4202 if (CpuFeatures::IsSupported(FPU)) { | 4196 if (CpuFeatures::IsSupported(FPU)) { |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4331 // Restore the top frame descriptors from the stack. | 4325 // Restore the top frame descriptors from the stack. |
| 4332 __ pop(t1); | 4326 __ pop(t1); |
| 4333 __ li(t0, Operand(ExternalReference(Isolate::kCEntryFPAddress, | 4327 __ li(t0, Operand(ExternalReference(Isolate::kCEntryFPAddress, |
| 4334 isolate))); | 4328 isolate))); |
| 4335 __ sw(t1, MemOperand(t0)); | 4329 __ sw(t1, MemOperand(t0)); |
| 4336 | 4330 |
| 4337 // Reset the stack to the callee saved registers. | 4331 // Reset the stack to the callee saved registers. |
| 4338 __ addiu(sp, sp, -EntryFrameConstants::kCallerFPOffset); | 4332 __ addiu(sp, sp, -EntryFrameConstants::kCallerFPOffset); |
| 4339 | 4333 |
| 4340 if (CpuFeatures::IsSupported(FPU)) { | 4334 if (CpuFeatures::IsSupported(FPU)) { |
| 4341 CpuFeatures::Scope scope(FPU); | 4335 CpuFeatureScope scope(masm, FPU); |
| 4342 // Restore callee-saved fpu registers. | 4336 // Restore callee-saved fpu registers. |
| 4343 __ MultiPopFPU(kCalleeSavedFPU); | 4337 __ MultiPopFPU(kCalleeSavedFPU); |
| 4344 } | 4338 } |
| 4345 | 4339 |
| 4346 // Restore callee saved registers from the stack. | 4340 // Restore callee saved registers from the stack. |
| 4347 __ MultiPop(kCalleeSaved | ra.bit()); | 4341 __ MultiPop(kCalleeSaved | ra.bit()); |
| 4348 // Return. | 4342 // Return. |
| 4349 __ Jump(ra); | 4343 __ Jump(ra); |
| 4350 } | 4344 } |
| 4351 | 4345 |
| (...skipping 2668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7020 if (left_ == CompareIC::SMI) { | 7014 if (left_ == CompareIC::SMI) { |
| 7021 __ JumpIfNotSmi(a1, &miss); | 7015 __ JumpIfNotSmi(a1, &miss); |
| 7022 } | 7016 } |
| 7023 if (right_ == CompareIC::SMI) { | 7017 if (right_ == CompareIC::SMI) { |
| 7024 __ JumpIfNotSmi(a0, &miss); | 7018 __ JumpIfNotSmi(a0, &miss); |
| 7025 } | 7019 } |
| 7026 | 7020 |
| 7027 // Inlining the double comparison and falling back to the general compare | 7021 // Inlining the double comparison and falling back to the general compare |
| 7028 // stub if NaN is involved or FPU is unsupported. | 7022 // stub if NaN is involved or FPU is unsupported. |
| 7029 if (CpuFeatures::IsSupported(FPU)) { | 7023 if (CpuFeatures::IsSupported(FPU)) { |
| 7030 CpuFeatures::Scope scope(FPU); | 7024 CpuFeatureScope scope(masm, FPU); |
| 7031 | 7025 |
| 7032 // Load left and right operand. | 7026 // Load left and right operand. |
| 7033 Label done, left, left_smi, right_smi; | 7027 Label done, left, left_smi, right_smi; |
| 7034 __ JumpIfSmi(a0, &right_smi); | 7028 __ JumpIfSmi(a0, &right_smi); |
| 7035 __ CheckMap(a0, a2, Heap::kHeapNumberMapRootIndex, &maybe_undefined1, | 7029 __ CheckMap(a0, a2, Heap::kHeapNumberMapRootIndex, &maybe_undefined1, |
| 7036 DONT_DO_SMI_CHECK); | 7030 DONT_DO_SMI_CHECK); |
| 7037 __ Subu(a2, a0, Operand(kHeapObjectTag)); | 7031 __ Subu(a2, a0, Operand(kHeapObjectTag)); |
| 7038 __ ldc1(f2, MemOperand(a2, HeapNumber::kValueOffset)); | 7032 __ ldc1(f2, MemOperand(a2, HeapNumber::kValueOffset)); |
| 7039 __ Branch(&left); | 7033 __ Branch(&left); |
| 7040 __ bind(&right_smi); | 7034 __ bind(&right_smi); |
| (...skipping 987 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8028 __ Pop(ra, t1, a1); | 8022 __ Pop(ra, t1, a1); |
| 8029 __ Ret(); | 8023 __ Ret(); |
| 8030 } | 8024 } |
| 8031 | 8025 |
| 8032 | 8026 |
| 8033 #undef __ | 8027 #undef __ |
| 8034 | 8028 |
| 8035 } } // namespace v8::internal | 8029 } } // namespace v8::internal |
| 8036 | 8030 |
| 8037 #endif // V8_TARGET_ARCH_MIPS | 8031 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |