| 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 633 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 644 Operand(source_, LSR, 32 - HeapNumber::kMantissaBitsInTopWord)); | 644 Operand(source_, LSR, 32 - HeapNumber::kMantissaBitsInTopWord)); |
| 645 __ Ret(); | 645 __ Ret(); |
| 646 } | 646 } |
| 647 | 647 |
| 648 | 648 |
| 649 void FloatingPointHelper::LoadSmis(MacroAssembler* masm, | 649 void FloatingPointHelper::LoadSmis(MacroAssembler* masm, |
| 650 FloatingPointHelper::Destination destination, | 650 FloatingPointHelper::Destination destination, |
| 651 Register scratch1, | 651 Register scratch1, |
| 652 Register scratch2) { | 652 Register scratch2) { |
| 653 if (CpuFeatures::IsSupported(VFP2)) { | 653 if (CpuFeatures::IsSupported(VFP2)) { |
| 654 CpuFeatures::Scope scope(VFP2); | 654 CpuFeatureScope scope(masm, VFP2); |
| 655 __ mov(scratch1, Operand(r0, ASR, kSmiTagSize)); | 655 __ mov(scratch1, Operand(r0, ASR, kSmiTagSize)); |
| 656 __ vmov(d7.high(), scratch1); | 656 __ vmov(d7.high(), scratch1); |
| 657 __ vcvt_f64_s32(d7, d7.high()); | 657 __ vcvt_f64_s32(d7, d7.high()); |
| 658 __ mov(scratch1, Operand(r1, ASR, kSmiTagSize)); | 658 __ mov(scratch1, Operand(r1, ASR, kSmiTagSize)); |
| 659 __ vmov(d6.high(), scratch1); | 659 __ vmov(d6.high(), scratch1); |
| 660 __ vcvt_f64_s32(d6, d6.high()); | 660 __ vcvt_f64_s32(d6, d6.high()); |
| 661 if (destination == kCoreRegisters) { | 661 if (destination == kCoreRegisters) { |
| 662 __ vmov(r2, r3, d7); | 662 __ vmov(r2, r3, d7); |
| 663 __ vmov(r0, r1, d6); | 663 __ vmov(r0, r1, d6); |
| 664 } | 664 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 695 Label is_smi, done; | 695 Label is_smi, done; |
| 696 | 696 |
| 697 // Smi-check | 697 // Smi-check |
| 698 __ UntagAndJumpIfSmi(scratch1, object, &is_smi); | 698 __ UntagAndJumpIfSmi(scratch1, object, &is_smi); |
| 699 // Heap number check | 699 // Heap number check |
| 700 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number); | 700 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number); |
| 701 | 701 |
| 702 // Handle loading a double from a heap number. | 702 // Handle loading a double from a heap number. |
| 703 if (CpuFeatures::IsSupported(VFP2) && | 703 if (CpuFeatures::IsSupported(VFP2) && |
| 704 destination == kVFPRegisters) { | 704 destination == kVFPRegisters) { |
| 705 CpuFeatures::Scope scope(VFP2); | 705 CpuFeatureScope scope(masm, VFP2); |
| 706 // Load the double from tagged HeapNumber to double register. | 706 // Load the double from tagged HeapNumber to double register. |
| 707 __ sub(scratch1, object, Operand(kHeapObjectTag)); | 707 __ sub(scratch1, object, Operand(kHeapObjectTag)); |
| 708 __ vldr(dst, scratch1, HeapNumber::kValueOffset); | 708 __ vldr(dst, scratch1, HeapNumber::kValueOffset); |
| 709 } else { | 709 } else { |
| 710 ASSERT(destination == kCoreRegisters); | 710 ASSERT(destination == kCoreRegisters); |
| 711 // Load the double from heap number to dst1 and dst2 in double format. | 711 // Load the double from heap number to dst1 and dst2 in double format. |
| 712 __ Ldrd(dst1, dst2, FieldMemOperand(object, HeapNumber::kValueOffset)); | 712 __ Ldrd(dst1, dst2, FieldMemOperand(object, HeapNumber::kValueOffset)); |
| 713 } | 713 } |
| 714 __ jmp(&done); | 714 __ jmp(&done); |
| 715 | 715 |
| 716 // Handle loading a double from a smi. | 716 // Handle loading a double from a smi. |
| 717 __ bind(&is_smi); | 717 __ bind(&is_smi); |
| 718 if (CpuFeatures::IsSupported(VFP2)) { | 718 if (CpuFeatures::IsSupported(VFP2)) { |
| 719 CpuFeatures::Scope scope(VFP2); | 719 CpuFeatureScope scope(masm, VFP2); |
| 720 // Convert smi to double using VFP instructions. | 720 // Convert smi to double using VFP instructions. |
| 721 __ vmov(dst.high(), scratch1); | 721 __ vmov(dst.high(), scratch1); |
| 722 __ vcvt_f64_s32(dst, dst.high()); | 722 __ vcvt_f64_s32(dst, dst.high()); |
| 723 if (destination == kCoreRegisters) { | 723 if (destination == kCoreRegisters) { |
| 724 // Load the converted smi to dst1 and dst2 in double format. | 724 // Load the converted smi to dst1 and dst2 in double format. |
| 725 __ vmov(dst1, dst2, dst); | 725 __ vmov(dst1, dst2, dst); |
| 726 } | 726 } |
| 727 } else { | 727 } else { |
| 728 ASSERT(destination == kCoreRegisters); | 728 ASSERT(destination == kCoreRegisters); |
| 729 // Write smi to dst1 and dst2 double format. | 729 // Write smi to dst1 and dst2 double format. |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 785 Register dst_exponent, | 785 Register dst_exponent, |
| 786 Register scratch2, | 786 Register scratch2, |
| 787 SwVfpRegister single_scratch) { | 787 SwVfpRegister single_scratch) { |
| 788 ASSERT(!int_scratch.is(scratch2)); | 788 ASSERT(!int_scratch.is(scratch2)); |
| 789 ASSERT(!int_scratch.is(dst_mantissa)); | 789 ASSERT(!int_scratch.is(dst_mantissa)); |
| 790 ASSERT(!int_scratch.is(dst_exponent)); | 790 ASSERT(!int_scratch.is(dst_exponent)); |
| 791 | 791 |
| 792 Label done; | 792 Label done; |
| 793 | 793 |
| 794 if (CpuFeatures::IsSupported(VFP2)) { | 794 if (CpuFeatures::IsSupported(VFP2)) { |
| 795 CpuFeatures::Scope scope(VFP2); | 795 CpuFeatureScope scope(masm, VFP2); |
| 796 __ vmov(single_scratch, int_scratch); | 796 __ vmov(single_scratch, int_scratch); |
| 797 __ vcvt_f64_s32(double_dst, single_scratch); | 797 __ vcvt_f64_s32(double_dst, single_scratch); |
| 798 if (destination == kCoreRegisters) { | 798 if (destination == kCoreRegisters) { |
| 799 __ vmov(dst_mantissa, dst_exponent, double_dst); | 799 __ vmov(dst_mantissa, dst_exponent, double_dst); |
| 800 } | 800 } |
| 801 } else { | 801 } else { |
| 802 Label fewer_than_20_useful_bits; | 802 Label fewer_than_20_useful_bits; |
| 803 // Expected output: | 803 // Expected output: |
| 804 // | dst_exponent | dst_mantissa | | 804 // | dst_exponent | dst_mantissa | |
| 805 // | s | exp | mantissa | | 805 // | s | exp | mantissa | |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 879 __ b(&done); | 879 __ b(&done); |
| 880 | 880 |
| 881 __ bind(&obj_is_not_smi); | 881 __ bind(&obj_is_not_smi); |
| 882 __ AssertRootValue(heap_number_map, | 882 __ AssertRootValue(heap_number_map, |
| 883 Heap::kHeapNumberMapRootIndex, | 883 Heap::kHeapNumberMapRootIndex, |
| 884 "HeapNumberMap register clobbered."); | 884 "HeapNumberMap register clobbered."); |
| 885 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32); | 885 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32); |
| 886 | 886 |
| 887 // Load the number. | 887 // Load the number. |
| 888 if (CpuFeatures::IsSupported(VFP2)) { | 888 if (CpuFeatures::IsSupported(VFP2)) { |
| 889 CpuFeatures::Scope scope(VFP2); | 889 CpuFeatureScope scope(masm, VFP2); |
| 890 // Load the double value. | 890 // Load the double value. |
| 891 __ sub(scratch1, object, Operand(kHeapObjectTag)); | 891 __ sub(scratch1, object, Operand(kHeapObjectTag)); |
| 892 __ vldr(double_dst, scratch1, HeapNumber::kValueOffset); | 892 __ vldr(double_dst, scratch1, HeapNumber::kValueOffset); |
| 893 | 893 |
| 894 __ EmitVFPTruncate(kRoundToZero, | 894 __ EmitVFPTruncate(kRoundToZero, |
| 895 scratch1, | 895 scratch1, |
| 896 double_dst, | 896 double_dst, |
| 897 scratch2, | 897 scratch2, |
| 898 double_scratch, | 898 double_scratch, |
| 899 kCheckForInexactConversion); | 899 kCheckForInexactConversion); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 976 | 976 |
| 977 __ AssertRootValue(heap_number_map, | 977 __ AssertRootValue(heap_number_map, |
| 978 Heap::kHeapNumberMapRootIndex, | 978 Heap::kHeapNumberMapRootIndex, |
| 979 "HeapNumberMap register clobbered."); | 979 "HeapNumberMap register clobbered."); |
| 980 | 980 |
| 981 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, &maybe_undefined); | 981 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, &maybe_undefined); |
| 982 | 982 |
| 983 // Object is a heap number. | 983 // Object is a heap number. |
| 984 // Convert the floating point value to a 32-bit integer. | 984 // Convert the floating point value to a 32-bit integer. |
| 985 if (CpuFeatures::IsSupported(VFP2)) { | 985 if (CpuFeatures::IsSupported(VFP2)) { |
| 986 CpuFeatures::Scope scope(VFP2); | 986 CpuFeatureScope scope(masm, VFP2); |
| 987 | 987 |
| 988 // Load the double value. | 988 // Load the double value. |
| 989 __ sub(scratch1, object, Operand(kHeapObjectTag)); | 989 __ sub(scratch1, object, Operand(kHeapObjectTag)); |
| 990 __ vldr(double_scratch0, scratch1, HeapNumber::kValueOffset); | 990 __ vldr(double_scratch0, scratch1, HeapNumber::kValueOffset); |
| 991 | 991 |
| 992 __ EmitVFPTruncate(kRoundToZero, | 992 __ EmitVFPTruncate(kRoundToZero, |
| 993 dst, | 993 dst, |
| 994 double_scratch0, | 994 double_scratch0, |
| 995 scratch1, | 995 scratch1, |
| 996 double_scratch1, | 996 double_scratch1, |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1111 | 1111 |
| 1112 // Assert that heap_number_result is callee-saved. | 1112 // Assert that heap_number_result is callee-saved. |
| 1113 // We currently always use r5 to pass it. | 1113 // We currently always use r5 to pass it. |
| 1114 ASSERT(heap_number_result.is(r5)); | 1114 ASSERT(heap_number_result.is(r5)); |
| 1115 | 1115 |
| 1116 // Push the current return address before the C call. Return will be | 1116 // Push the current return address before the C call. Return will be |
| 1117 // through pop(pc) below. | 1117 // through pop(pc) below. |
| 1118 __ push(lr); | 1118 __ push(lr); |
| 1119 __ PrepareCallCFunction(0, 2, scratch); | 1119 __ PrepareCallCFunction(0, 2, scratch); |
| 1120 if (masm->use_eabi_hardfloat()) { | 1120 if (masm->use_eabi_hardfloat()) { |
| 1121 CpuFeatures::Scope scope(VFP2); | 1121 CpuFeatureScope scope(masm, VFP2); |
| 1122 __ vmov(d0, r0, r1); | 1122 __ vmov(d0, r0, r1); |
| 1123 __ vmov(d1, r2, r3); | 1123 __ vmov(d1, r2, r3); |
| 1124 } | 1124 } |
| 1125 { | 1125 { |
| 1126 AllowExternalCallThatCantCauseGC scope(masm); | 1126 AllowExternalCallThatCantCauseGC scope(masm); |
| 1127 __ CallCFunction( | 1127 __ CallCFunction( |
| 1128 ExternalReference::double_fp_operation(op, masm->isolate()), 0, 2); | 1128 ExternalReference::double_fp_operation(op, masm->isolate()), 0, 2); |
| 1129 } | 1129 } |
| 1130 // Store answer in the overwritable heap number. Double returned in | 1130 // Store answer in the overwritable heap number. Double returned in |
| 1131 // registers r0 and r1 or in d0. | 1131 // registers r0 and r1 or in d0. |
| 1132 if (masm->use_eabi_hardfloat()) { | 1132 if (masm->use_eabi_hardfloat()) { |
| 1133 CpuFeatures::Scope scope(VFP2); | 1133 CpuFeatureScope scope(masm, VFP2); |
| 1134 __ vstr(d0, | 1134 __ vstr(d0, |
| 1135 FieldMemOperand(heap_number_result, HeapNumber::kValueOffset)); | 1135 FieldMemOperand(heap_number_result, HeapNumber::kValueOffset)); |
| 1136 } else { | 1136 } else { |
| 1137 __ Strd(r0, r1, FieldMemOperand(heap_number_result, | 1137 __ Strd(r0, r1, FieldMemOperand(heap_number_result, |
| 1138 HeapNumber::kValueOffset)); | 1138 HeapNumber::kValueOffset)); |
| 1139 } | 1139 } |
| 1140 // Place heap_number_result in r0 and return to the pushed return address. | 1140 // Place heap_number_result in r0 and return to the pushed return address. |
| 1141 __ mov(r0, Operand(heap_number_result)); | 1141 __ mov(r0, Operand(heap_number_result)); |
| 1142 __ pop(pc); | 1142 __ pop(pc); |
| 1143 } | 1143 } |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1338 __ Ret(ne); | 1338 __ Ret(ne); |
| 1339 } else { | 1339 } else { |
| 1340 // Smi compared non-strictly with a non-Smi non-heap-number. Call | 1340 // Smi compared non-strictly with a non-Smi non-heap-number. Call |
| 1341 // the runtime. | 1341 // the runtime. |
| 1342 __ b(ne, slow); | 1342 __ b(ne, slow); |
| 1343 } | 1343 } |
| 1344 | 1344 |
| 1345 // Lhs is a smi, rhs is a number. | 1345 // Lhs is a smi, rhs is a number. |
| 1346 if (CpuFeatures::IsSupported(VFP2)) { | 1346 if (CpuFeatures::IsSupported(VFP2)) { |
| 1347 // Convert lhs to a double in d7. | 1347 // Convert lhs to a double in d7. |
| 1348 CpuFeatures::Scope scope(VFP2); | 1348 CpuFeatureScope scope(masm, VFP2); |
| 1349 __ SmiToDoubleVFPRegister(lhs, d7, r7, s15); | 1349 __ SmiToDoubleVFPRegister(lhs, d7, r7, s15); |
| 1350 // Load the double from rhs, tagged HeapNumber r0, to d6. | 1350 // Load the double from rhs, tagged HeapNumber r0, to d6. |
| 1351 __ sub(r7, rhs, Operand(kHeapObjectTag)); | 1351 __ sub(r7, rhs, Operand(kHeapObjectTag)); |
| 1352 __ vldr(d6, r7, HeapNumber::kValueOffset); | 1352 __ vldr(d6, r7, HeapNumber::kValueOffset); |
| 1353 } else { | 1353 } else { |
| 1354 __ push(lr); | 1354 __ push(lr); |
| 1355 // Convert lhs to a double in r2, r3. | 1355 // Convert lhs to a double in r2, r3. |
| 1356 __ mov(r7, Operand(lhs)); | 1356 __ mov(r7, Operand(lhs)); |
| 1357 ConvertToDoubleStub stub1(r3, r2, r7, r6); | 1357 ConvertToDoubleStub stub1(r3, r2, r7, r6); |
| 1358 __ Call(stub1.GetCode(masm->isolate())); | 1358 __ Call(stub1.GetCode(masm->isolate())); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1377 } | 1377 } |
| 1378 __ Ret(ne); | 1378 __ Ret(ne); |
| 1379 } else { | 1379 } else { |
| 1380 // Smi compared non-strictly with a non-smi non-heap-number. Call | 1380 // Smi compared non-strictly with a non-smi non-heap-number. Call |
| 1381 // the runtime. | 1381 // the runtime. |
| 1382 __ b(ne, slow); | 1382 __ b(ne, slow); |
| 1383 } | 1383 } |
| 1384 | 1384 |
| 1385 // Rhs is a smi, lhs is a heap number. | 1385 // Rhs is a smi, lhs is a heap number. |
| 1386 if (CpuFeatures::IsSupported(VFP2)) { | 1386 if (CpuFeatures::IsSupported(VFP2)) { |
| 1387 CpuFeatures::Scope scope(VFP2); | 1387 CpuFeatureScope scope(masm, VFP2); |
| 1388 // Load the double from lhs, tagged HeapNumber r1, to d7. | 1388 // Load the double from lhs, tagged HeapNumber r1, to d7. |
| 1389 __ sub(r7, lhs, Operand(kHeapObjectTag)); | 1389 __ sub(r7, lhs, Operand(kHeapObjectTag)); |
| 1390 __ vldr(d7, r7, HeapNumber::kValueOffset); | 1390 __ vldr(d7, r7, HeapNumber::kValueOffset); |
| 1391 // Convert rhs to a double in d6 . | 1391 // Convert rhs to a double in d6 . |
| 1392 __ SmiToDoubleVFPRegister(rhs, d6, r7, s13); | 1392 __ SmiToDoubleVFPRegister(rhs, d6, r7, s13); |
| 1393 } else { | 1393 } else { |
| 1394 __ push(lr); | 1394 __ push(lr); |
| 1395 // Load lhs to a double in r2, r3. | 1395 // Load lhs to a double in r2, r3. |
| 1396 __ Ldrd(r2, r3, FieldMemOperand(lhs, HeapNumber::kValueOffset)); | 1396 __ Ldrd(r2, r3, FieldMemOperand(lhs, HeapNumber::kValueOffset)); |
| 1397 // Convert rhs to a double in r0, r1. | 1397 // Convert rhs to a double in r0, r1. |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1489 // Now they are equal if and only if the lhs exponent is zero in its | 1489 // Now they are equal if and only if the lhs exponent is zero in its |
| 1490 // low 31 bits. | 1490 // low 31 bits. |
| 1491 __ mov(r0, Operand(rhs_exponent, LSL, kSmiTagSize)); | 1491 __ mov(r0, Operand(rhs_exponent, LSL, kSmiTagSize)); |
| 1492 __ Ret(); | 1492 __ Ret(); |
| 1493 } else { | 1493 } else { |
| 1494 // Call a native function to do a comparison between two non-NaNs. | 1494 // Call a native function to do a comparison between two non-NaNs. |
| 1495 // Call C routine that may not cause GC or other trouble. | 1495 // Call C routine that may not cause GC or other trouble. |
| 1496 __ push(lr); | 1496 __ push(lr); |
| 1497 __ PrepareCallCFunction(0, 2, r5); | 1497 __ PrepareCallCFunction(0, 2, r5); |
| 1498 if (masm->use_eabi_hardfloat()) { | 1498 if (masm->use_eabi_hardfloat()) { |
| 1499 CpuFeatures::Scope scope(VFP2); | 1499 CpuFeatureScope scope(masm, VFP2); |
| 1500 __ vmov(d0, r0, r1); | 1500 __ vmov(d0, r0, r1); |
| 1501 __ vmov(d1, r2, r3); | 1501 __ vmov(d1, r2, r3); |
| 1502 } | 1502 } |
| 1503 | 1503 |
| 1504 AllowExternalCallThatCantCauseGC scope(masm); | 1504 AllowExternalCallThatCantCauseGC scope(masm); |
| 1505 __ CallCFunction(ExternalReference::compare_doubles(masm->isolate()), | 1505 __ CallCFunction(ExternalReference::compare_doubles(masm->isolate()), |
| 1506 0, 2); | 1506 0, 2); |
| 1507 __ pop(pc); // Return. | 1507 __ pop(pc); // Return. |
| 1508 } | 1508 } |
| 1509 } | 1509 } |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1566 | 1566 |
| 1567 __ CompareObjectType(rhs, r3, r2, HEAP_NUMBER_TYPE); | 1567 __ CompareObjectType(rhs, r3, r2, HEAP_NUMBER_TYPE); |
| 1568 __ b(ne, not_heap_numbers); | 1568 __ b(ne, not_heap_numbers); |
| 1569 __ ldr(r2, FieldMemOperand(lhs, HeapObject::kMapOffset)); | 1569 __ ldr(r2, FieldMemOperand(lhs, HeapObject::kMapOffset)); |
| 1570 __ cmp(r2, r3); | 1570 __ cmp(r2, r3); |
| 1571 __ b(ne, slow); // First was a heap number, second wasn't. Go slow case. | 1571 __ b(ne, slow); // First was a heap number, second wasn't. Go slow case. |
| 1572 | 1572 |
| 1573 // Both are heap numbers. Load them up then jump to the code we have | 1573 // Both are heap numbers. Load them up then jump to the code we have |
| 1574 // for that. | 1574 // for that. |
| 1575 if (CpuFeatures::IsSupported(VFP2)) { | 1575 if (CpuFeatures::IsSupported(VFP2)) { |
| 1576 CpuFeatures::Scope scope(VFP2); | 1576 CpuFeatureScope scope(masm, VFP2); |
| 1577 __ sub(r7, rhs, Operand(kHeapObjectTag)); | 1577 __ sub(r7, rhs, Operand(kHeapObjectTag)); |
| 1578 __ vldr(d6, r7, HeapNumber::kValueOffset); | 1578 __ vldr(d6, r7, HeapNumber::kValueOffset); |
| 1579 __ sub(r7, lhs, Operand(kHeapObjectTag)); | 1579 __ sub(r7, lhs, Operand(kHeapObjectTag)); |
| 1580 __ vldr(d7, r7, HeapNumber::kValueOffset); | 1580 __ vldr(d7, r7, HeapNumber::kValueOffset); |
| 1581 } else { | 1581 } else { |
| 1582 __ Ldrd(r2, r3, FieldMemOperand(lhs, HeapNumber::kValueOffset)); | 1582 __ Ldrd(r2, r3, FieldMemOperand(lhs, HeapNumber::kValueOffset)); |
| 1583 __ Ldrd(r0, r1, FieldMemOperand(rhs, HeapNumber::kValueOffset)); | 1583 __ Ldrd(r0, r1, FieldMemOperand(rhs, HeapNumber::kValueOffset)); |
| 1584 } | 1584 } |
| 1585 __ jmp(both_loaded_as_doubles); | 1585 __ jmp(both_loaded_as_doubles); |
| 1586 } | 1586 } |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1656 // Calculate the entry in the number string cache. The hash value in the | 1656 // Calculate the entry in the number string cache. The hash value in the |
| 1657 // number string cache for smis is just the smi value, and the hash for | 1657 // number string cache for smis is just the smi value, and the hash for |
| 1658 // doubles is the xor of the upper and lower words. See | 1658 // doubles is the xor of the upper and lower words. See |
| 1659 // Heap::GetNumberStringCache. | 1659 // Heap::GetNumberStringCache. |
| 1660 Isolate* isolate = masm->isolate(); | 1660 Isolate* isolate = masm->isolate(); |
| 1661 Label is_smi; | 1661 Label is_smi; |
| 1662 Label load_result_from_cache; | 1662 Label load_result_from_cache; |
| 1663 if (!object_is_smi) { | 1663 if (!object_is_smi) { |
| 1664 __ JumpIfSmi(object, &is_smi); | 1664 __ JumpIfSmi(object, &is_smi); |
| 1665 if (CpuFeatures::IsSupported(VFP2)) { | 1665 if (CpuFeatures::IsSupported(VFP2)) { |
| 1666 CpuFeatures::Scope scope(VFP2); | 1666 CpuFeatureScope scope(masm, VFP2); |
| 1667 __ CheckMap(object, | 1667 __ CheckMap(object, |
| 1668 scratch1, | 1668 scratch1, |
| 1669 Heap::kHeapNumberMapRootIndex, | 1669 Heap::kHeapNumberMapRootIndex, |
| 1670 not_found, | 1670 not_found, |
| 1671 DONT_DO_SMI_CHECK); | 1671 DONT_DO_SMI_CHECK); |
| 1672 | 1672 |
| 1673 STATIC_ASSERT(8 == kDoubleSize); | 1673 STATIC_ASSERT(8 == kDoubleSize); |
| 1674 __ add(scratch1, | 1674 __ add(scratch1, |
| 1675 object, | 1675 object, |
| 1676 Operand(HeapNumber::kValueOffset - kHeapObjectTag)); | 1676 Operand(HeapNumber::kValueOffset - kHeapObjectTag)); |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1807 // been loaded into d7 and d6. Otherwise, the double values have been loaded | 1807 // been loaded into d7 and d6. Otherwise, the double values have been loaded |
| 1808 // into r0, r1, r2, and r3. | 1808 // into r0, r1, r2, and r3. |
| 1809 EmitSmiNonsmiComparison(masm, lhs, rhs, &lhs_not_nan, &slow, strict()); | 1809 EmitSmiNonsmiComparison(masm, lhs, rhs, &lhs_not_nan, &slow, strict()); |
| 1810 | 1810 |
| 1811 __ bind(&both_loaded_as_doubles); | 1811 __ bind(&both_loaded_as_doubles); |
| 1812 // The arguments have been converted to doubles and stored in d6 and d7, if | 1812 // The arguments have been converted to doubles and stored in d6 and d7, if |
| 1813 // VFP3 is supported, or in r0, r1, r2, and r3. | 1813 // VFP3 is supported, or in r0, r1, r2, and r3. |
| 1814 Isolate* isolate = masm->isolate(); | 1814 Isolate* isolate = masm->isolate(); |
| 1815 if (CpuFeatures::IsSupported(VFP2)) { | 1815 if (CpuFeatures::IsSupported(VFP2)) { |
| 1816 __ bind(&lhs_not_nan); | 1816 __ bind(&lhs_not_nan); |
| 1817 CpuFeatures::Scope scope(VFP2); | 1817 CpuFeatureScope scope(masm, VFP2); |
| 1818 Label no_nan; | 1818 Label no_nan; |
| 1819 // ARMv7 VFP3 instructions to implement double precision comparison. | 1819 // ARMv7 VFP3 instructions to implement double precision comparison. |
| 1820 __ VFPCompareAndSetFlags(d7, d6); | 1820 __ VFPCompareAndSetFlags(d7, d6); |
| 1821 Label nan; | 1821 Label nan; |
| 1822 __ b(vs, &nan); | 1822 __ b(vs, &nan); |
| 1823 __ mov(r0, Operand(EQUAL), LeaveCC, eq); | 1823 __ mov(r0, Operand(EQUAL), LeaveCC, eq); |
| 1824 __ mov(r0, Operand(LESS), LeaveCC, lt); | 1824 __ mov(r0, Operand(LESS), LeaveCC, lt); |
| 1825 __ mov(r0, Operand(GREATER), LeaveCC, gt); | 1825 __ mov(r0, Operand(GREATER), LeaveCC, gt); |
| 1826 __ Ret(); | 1826 __ Ret(); |
| 1827 | 1827 |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1987 __ Ret(lt); // the string length is OK as the return value | 1987 __ Ret(lt); // the string length is OK as the return value |
| 1988 } | 1988 } |
| 1989 | 1989 |
| 1990 if (types_.Contains(HEAP_NUMBER)) { | 1990 if (types_.Contains(HEAP_NUMBER)) { |
| 1991 // Heap number -> false iff +0, -0, or NaN. | 1991 // Heap number -> false iff +0, -0, or NaN. |
| 1992 Label not_heap_number; | 1992 Label not_heap_number; |
| 1993 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); | 1993 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); |
| 1994 __ b(ne, ¬_heap_number); | 1994 __ b(ne, ¬_heap_number); |
| 1995 | 1995 |
| 1996 if (CpuFeatures::IsSupported(VFP2)) { | 1996 if (CpuFeatures::IsSupported(VFP2)) { |
| 1997 CpuFeatures::Scope scope(VFP2); | 1997 CpuFeatureScope scope(masm, VFP2); |
| 1998 | 1998 |
| 1999 __ vldr(d1, FieldMemOperand(tos_, HeapNumber::kValueOffset)); | 1999 __ vldr(d1, FieldMemOperand(tos_, HeapNumber::kValueOffset)); |
| 2000 __ VFPCompareAndSetFlags(d1, 0.0); | 2000 __ VFPCompareAndSetFlags(d1, 0.0); |
| 2001 // "tos_" is a register, and contains a non zero value by default. | 2001 // "tos_" is a register, and contains a non zero value by default. |
| 2002 // Hence we only need to overwrite "tos_" with zero to return false for | 2002 // Hence we only need to overwrite "tos_" with zero to return false for |
| 2003 // FP_ZERO or FP_NAN cases. Otherwise, by default it returns true. | 2003 // FP_ZERO or FP_NAN cases. Otherwise, by default it returns true. |
| 2004 __ mov(tos_, Operand::Zero(), LeaveCC, eq); // for FP_ZERO | 2004 __ mov(tos_, Operand::Zero(), LeaveCC, eq); // for FP_ZERO |
| 2005 __ mov(tos_, Operand::Zero(), LeaveCC, vs); // for FP_NAN | 2005 __ mov(tos_, Operand::Zero(), LeaveCC, vs); // for FP_NAN |
| 2006 } else { | 2006 } else { |
| 2007 Label done, not_nan, not_zero; | 2007 Label done, not_nan, not_zero; |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2087 | 2087 |
| 2088 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { | 2088 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { |
| 2089 // We don't allow a GC during a store buffer overflow so there is no need to | 2089 // We don't allow a GC during a store buffer overflow so there is no need to |
| 2090 // store the registers in any particular way, but we do have to store and | 2090 // store the registers in any particular way, but we do have to store and |
| 2091 // restore them. | 2091 // restore them. |
| 2092 __ stm(db_w, sp, kCallerSaved | lr.bit()); | 2092 __ stm(db_w, sp, kCallerSaved | lr.bit()); |
| 2093 | 2093 |
| 2094 const Register scratch = r1; | 2094 const Register scratch = r1; |
| 2095 | 2095 |
| 2096 if (save_doubles_ == kSaveFPRegs) { | 2096 if (save_doubles_ == kSaveFPRegs) { |
| 2097 CpuFeatures::Scope scope(VFP2); | 2097 CpuFeatureScope scope(masm, VFP2); |
| 2098 // Check CPU flags for number of registers, setting the Z condition flag. | 2098 // Check CPU flags for number of registers, setting the Z condition flag. |
| 2099 __ CheckFor32DRegs(scratch); | 2099 __ CheckFor32DRegs(scratch); |
| 2100 | 2100 |
| 2101 __ sub(sp, sp, Operand(kDoubleSize * DwVfpRegister::kMaxNumRegisters)); | 2101 __ sub(sp, sp, Operand(kDoubleSize * DwVfpRegister::kMaxNumRegisters)); |
| 2102 for (int i = 0; i < DwVfpRegister::kMaxNumRegisters; i++) { | 2102 for (int i = 0; i < DwVfpRegister::kMaxNumRegisters; i++) { |
| 2103 DwVfpRegister reg = DwVfpRegister::from_code(i); | 2103 DwVfpRegister reg = DwVfpRegister::from_code(i); |
| 2104 __ vstr(reg, MemOperand(sp, i * kDoubleSize), i < 16 ? al : ne); | 2104 __ vstr(reg, MemOperand(sp, i * kDoubleSize), i < 16 ? al : ne); |
| 2105 } | 2105 } |
| 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 | 2109 |
| 2110 AllowExternalCallThatCantCauseGC scope(masm); | 2110 AllowExternalCallThatCantCauseGC scope(masm); |
| 2111 __ PrepareCallCFunction(argument_count, fp_argument_count, scratch); | 2111 __ PrepareCallCFunction(argument_count, fp_argument_count, scratch); |
| 2112 __ mov(r0, Operand(ExternalReference::isolate_address())); | 2112 __ mov(r0, Operand(ExternalReference::isolate_address())); |
| 2113 __ CallCFunction( | 2113 __ CallCFunction( |
| 2114 ExternalReference::store_buffer_overflow_function(masm->isolate()), | 2114 ExternalReference::store_buffer_overflow_function(masm->isolate()), |
| 2115 argument_count); | 2115 argument_count); |
| 2116 if (save_doubles_ == kSaveFPRegs) { | 2116 if (save_doubles_ == kSaveFPRegs) { |
| 2117 CpuFeatures::Scope scope(VFP2); | 2117 CpuFeatureScope scope(masm, VFP2); |
| 2118 | 2118 |
| 2119 // Check CPU flags for number of registers, setting the Z condition flag. | 2119 // Check CPU flags for number of registers, setting the Z condition flag. |
| 2120 __ CheckFor32DRegs(scratch); | 2120 __ CheckFor32DRegs(scratch); |
| 2121 | 2121 |
| 2122 for (int i = 0; i < DwVfpRegister::kMaxNumRegisters; i++) { | 2122 for (int i = 0; i < DwVfpRegister::kMaxNumRegisters; i++) { |
| 2123 DwVfpRegister reg = DwVfpRegister::from_code(i); | 2123 DwVfpRegister reg = DwVfpRegister::from_code(i); |
| 2124 __ vldr(reg, MemOperand(sp, i * kDoubleSize), i < 16 ? al : ne); | 2124 __ vldr(reg, MemOperand(sp, i * kDoubleSize), i < 16 ? al : ne); |
| 2125 } | 2125 } |
| 2126 __ add(sp, sp, Operand(kDoubleSize * DwVfpRegister::kMaxNumRegisters)); | 2126 __ add(sp, sp, Operand(kDoubleSize * DwVfpRegister::kMaxNumRegisters)); |
| 2127 } | 2127 } |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2343 // converted once again. | 2343 // converted once again. |
| 2344 __ ConvertToInt32(r0, r1, r3, r4, d0, &impossible); | 2344 __ ConvertToInt32(r0, r1, r3, r4, d0, &impossible); |
| 2345 __ mvn(r1, Operand(r1)); | 2345 __ mvn(r1, Operand(r1)); |
| 2346 | 2346 |
| 2347 __ bind(&heapnumber_allocated); | 2347 __ bind(&heapnumber_allocated); |
| 2348 __ mov(r0, r2); // Move newly allocated heap number to r0. | 2348 __ mov(r0, r2); // Move newly allocated heap number to r0. |
| 2349 } | 2349 } |
| 2350 | 2350 |
| 2351 if (CpuFeatures::IsSupported(VFP2)) { | 2351 if (CpuFeatures::IsSupported(VFP2)) { |
| 2352 // Convert the int32 in r1 to the heap number in r0. r2 is corrupted. | 2352 // Convert the int32 in r1 to the heap number in r0. r2 is corrupted. |
| 2353 CpuFeatures::Scope scope(VFP2); | 2353 CpuFeatureScope scope(masm, VFP2); |
| 2354 __ vmov(s0, r1); | 2354 __ vmov(s0, r1); |
| 2355 __ vcvt_f64_s32(d0, s0); | 2355 __ vcvt_f64_s32(d0, s0); |
| 2356 __ sub(r2, r0, Operand(kHeapObjectTag)); | 2356 __ sub(r2, r0, Operand(kHeapObjectTag)); |
| 2357 __ vstr(d0, r2, HeapNumber::kValueOffset); | 2357 __ vstr(d0, r2, HeapNumber::kValueOffset); |
| 2358 __ Ret(); | 2358 __ Ret(); |
| 2359 } else { | 2359 } else { |
| 2360 // WriteInt32ToHeapNumberStub does not trigger GC, so we do not | 2360 // WriteInt32ToHeapNumberStub does not trigger GC, so we do not |
| 2361 // have to set up a frame. | 2361 // have to set up a frame. |
| 2362 WriteInt32ToHeapNumberStub stub(r1, r0, r2); | 2362 WriteInt32ToHeapNumberStub stub(r1, r0, r2); |
| 2363 __ Jump(stub.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); | 2363 __ Jump(stub.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); |
| (...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2738 masm, destination, left, d6, r0, r1, heap_number_map, | 2738 masm, destination, left, d6, r0, r1, heap_number_map, |
| 2739 scratch1, scratch2, fail); | 2739 scratch1, scratch2, fail); |
| 2740 } | 2740 } |
| 2741 } | 2741 } |
| 2742 | 2742 |
| 2743 // Calculate the result. | 2743 // Calculate the result. |
| 2744 if (destination == FloatingPointHelper::kVFPRegisters) { | 2744 if (destination == FloatingPointHelper::kVFPRegisters) { |
| 2745 // Using VFP registers: | 2745 // Using VFP registers: |
| 2746 // d6: Left value | 2746 // d6: Left value |
| 2747 // d7: Right value | 2747 // d7: Right value |
| 2748 CpuFeatures::Scope scope(VFP2); | 2748 CpuFeatureScope scope(masm, VFP2); |
| 2749 switch (op) { | 2749 switch (op) { |
| 2750 case Token::ADD: | 2750 case Token::ADD: |
| 2751 __ vadd(d5, d6, d7); | 2751 __ vadd(d5, d6, d7); |
| 2752 break; | 2752 break; |
| 2753 case Token::SUB: | 2753 case Token::SUB: |
| 2754 __ vsub(d5, d6, d7); | 2754 __ vsub(d5, d6, d7); |
| 2755 break; | 2755 break; |
| 2756 case Token::MUL: | 2756 case Token::MUL: |
| 2757 __ vmul(d5, d6, d7); | 2757 __ vmul(d5, d6, d7); |
| 2758 break; | 2758 break; |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2870 // r2: Answer as signed int32. | 2870 // r2: Answer as signed int32. |
| 2871 // r5: Heap number to write answer into. | 2871 // r5: Heap number to write answer into. |
| 2872 | 2872 |
| 2873 // Nothing can go wrong now, so move the heap number to r0, which is the | 2873 // Nothing can go wrong now, so move the heap number to r0, which is the |
| 2874 // result. | 2874 // result. |
| 2875 __ mov(r0, Operand(r5)); | 2875 __ mov(r0, Operand(r5)); |
| 2876 | 2876 |
| 2877 if (CpuFeatures::IsSupported(VFP2)) { | 2877 if (CpuFeatures::IsSupported(VFP2)) { |
| 2878 // Convert the int32 in r2 to the heap number in r0. r3 is corrupted. As | 2878 // Convert the int32 in r2 to the heap number in r0. r3 is corrupted. As |
| 2879 // mentioned above SHR needs to always produce a positive result. | 2879 // mentioned above SHR needs to always produce a positive result. |
| 2880 CpuFeatures::Scope scope(VFP2); | 2880 CpuFeatureScope scope(masm, VFP2); |
| 2881 __ vmov(s0, r2); | 2881 __ vmov(s0, r2); |
| 2882 if (op == Token::SHR) { | 2882 if (op == Token::SHR) { |
| 2883 __ vcvt_f64_u32(d0, s0); | 2883 __ vcvt_f64_u32(d0, s0); |
| 2884 } else { | 2884 } else { |
| 2885 __ vcvt_f64_s32(d0, s0); | 2885 __ vcvt_f64_s32(d0, s0); |
| 2886 } | 2886 } |
| 2887 __ sub(r3, r0, Operand(kHeapObjectTag)); | 2887 __ sub(r3, r0, Operand(kHeapObjectTag)); |
| 2888 __ vstr(d0, r3, HeapNumber::kValueOffset); | 2888 __ vstr(d0, r3, HeapNumber::kValueOffset); |
| 2889 __ Ret(); | 2889 __ Ret(); |
| 2890 } else { | 2890 } else { |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3062 d8, | 3062 d8, |
| 3063 r4, | 3063 r4, |
| 3064 r5, | 3064 r5, |
| 3065 heap_number_map, | 3065 heap_number_map, |
| 3066 scratch1, | 3066 scratch1, |
| 3067 scratch2, | 3067 scratch2, |
| 3068 s0, | 3068 s0, |
| 3069 &transition); | 3069 &transition); |
| 3070 | 3070 |
| 3071 if (destination == FloatingPointHelper::kVFPRegisters) { | 3071 if (destination == FloatingPointHelper::kVFPRegisters) { |
| 3072 CpuFeatures::Scope scope(VFP2); | 3072 CpuFeatureScope scope(masm, VFP2); |
| 3073 Label return_heap_number; | 3073 Label return_heap_number; |
| 3074 switch (op_) { | 3074 switch (op_) { |
| 3075 case Token::ADD: | 3075 case Token::ADD: |
| 3076 __ vadd(d5, d6, d7); | 3076 __ vadd(d5, d6, d7); |
| 3077 break; | 3077 break; |
| 3078 case Token::SUB: | 3078 case Token::SUB: |
| 3079 __ vsub(d5, d6, d7); | 3079 __ vsub(d5, d6, d7); |
| 3080 break; | 3080 break; |
| 3081 case Token::MUL: | 3081 case Token::MUL: |
| 3082 __ vmul(d5, d6, d7); | 3082 __ vmul(d5, d6, d7); |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3271 heap_number_result = r5; | 3271 heap_number_result = r5; |
| 3272 BinaryOpStub_GenerateHeapResultAllocation(masm, | 3272 BinaryOpStub_GenerateHeapResultAllocation(masm, |
| 3273 heap_number_result, | 3273 heap_number_result, |
| 3274 heap_number_map, | 3274 heap_number_map, |
| 3275 scratch1, | 3275 scratch1, |
| 3276 scratch2, | 3276 scratch2, |
| 3277 &call_runtime, | 3277 &call_runtime, |
| 3278 mode_); | 3278 mode_); |
| 3279 | 3279 |
| 3280 if (CpuFeatures::IsSupported(VFP2)) { | 3280 if (CpuFeatures::IsSupported(VFP2)) { |
| 3281 CpuFeatures::Scope scope(VFP2); | 3281 CpuFeatureScope scope(masm, VFP2); |
| 3282 if (op_ != Token::SHR) { | 3282 if (op_ != Token::SHR) { |
| 3283 // Convert the result to a floating point value. | 3283 // Convert the result to a floating point value. |
| 3284 __ vmov(double_scratch.low(), r2); | 3284 __ vmov(double_scratch.low(), r2); |
| 3285 __ vcvt_f64_s32(double_scratch, double_scratch.low()); | 3285 __ vcvt_f64_s32(double_scratch, double_scratch.low()); |
| 3286 } else { | 3286 } else { |
| 3287 // The result must be interpreted as an unsigned 32-bit integer. | 3287 // The result must be interpreted as an unsigned 32-bit integer. |
| 3288 __ vmov(double_scratch.low(), r2); | 3288 __ vmov(double_scratch.low(), r2); |
| 3289 __ vcvt_f64_u32(double_scratch, double_scratch.low()); | 3289 __ vcvt_f64_u32(double_scratch, double_scratch.low()); |
| 3290 } | 3290 } |
| 3291 | 3291 |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3474 Label input_not_smi; | 3474 Label input_not_smi; |
| 3475 Label loaded; | 3475 Label loaded; |
| 3476 Label calculate; | 3476 Label calculate; |
| 3477 Label invalid_cache; | 3477 Label invalid_cache; |
| 3478 const Register scratch0 = r9; | 3478 const Register scratch0 = r9; |
| 3479 const Register scratch1 = r7; | 3479 const Register scratch1 = r7; |
| 3480 const Register cache_entry = r0; | 3480 const Register cache_entry = r0; |
| 3481 const bool tagged = (argument_type_ == TAGGED); | 3481 const bool tagged = (argument_type_ == TAGGED); |
| 3482 | 3482 |
| 3483 if (CpuFeatures::IsSupported(VFP2)) { | 3483 if (CpuFeatures::IsSupported(VFP2)) { |
| 3484 CpuFeatures::Scope scope(VFP2); | 3484 CpuFeatureScope scope(masm, VFP2); |
| 3485 if (tagged) { | 3485 if (tagged) { |
| 3486 // Argument is a number and is on stack and in r0. | 3486 // Argument is a number and is on stack and in r0. |
| 3487 // Load argument and check if it is a smi. | 3487 // Load argument and check if it is a smi. |
| 3488 __ JumpIfNotSmi(r0, &input_not_smi); | 3488 __ JumpIfNotSmi(r0, &input_not_smi); |
| 3489 | 3489 |
| 3490 // Input is a smi. Convert to double and load the low and high words | 3490 // Input is a smi. Convert to double and load the low and high words |
| 3491 // of the double into r2, r3. | 3491 // of the double into r2, r3. |
| 3492 __ IntegerToDoubleConversionWithVFP3(r0, r3, r2); | 3492 __ IntegerToDoubleConversionWithVFP3(r0, r3, r2); |
| 3493 __ b(&loaded); | 3493 __ b(&loaded); |
| 3494 | 3494 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3576 Counters* counters = masm->isolate()->counters(); | 3576 Counters* counters = masm->isolate()->counters(); |
| 3577 __ IncrementCounter( | 3577 __ IncrementCounter( |
| 3578 counters->transcendental_cache_miss(), 1, scratch0, scratch1); | 3578 counters->transcendental_cache_miss(), 1, scratch0, scratch1); |
| 3579 if (tagged) { | 3579 if (tagged) { |
| 3580 __ bind(&invalid_cache); | 3580 __ bind(&invalid_cache); |
| 3581 ExternalReference runtime_function = | 3581 ExternalReference runtime_function = |
| 3582 ExternalReference(RuntimeFunction(), masm->isolate()); | 3582 ExternalReference(RuntimeFunction(), masm->isolate()); |
| 3583 __ TailCallExternalReference(runtime_function, 1, 1); | 3583 __ TailCallExternalReference(runtime_function, 1, 1); |
| 3584 } else { | 3584 } else { |
| 3585 ASSERT(CpuFeatures::IsSupported(VFP2)); | 3585 ASSERT(CpuFeatures::IsSupported(VFP2)); |
| 3586 CpuFeatures::Scope scope(VFP2); | 3586 CpuFeatureScope scope(masm, VFP2); |
| 3587 | 3587 |
| 3588 Label no_update; | 3588 Label no_update; |
| 3589 Label skip_cache; | 3589 Label skip_cache; |
| 3590 | 3590 |
| 3591 // Call C function to calculate the result and update the cache. | 3591 // Call C function to calculate the result and update the cache. |
| 3592 // r0: precalculated cache entry address. | 3592 // r0: precalculated cache entry address. |
| 3593 // r2 and r3: parts of the double value. | 3593 // r2 and r3: parts of the double value. |
| 3594 // Store r0, r2 and r3 on stack for later before calling C function. | 3594 // Store r0, r2 and r3 on stack for later before calling C function. |
| 3595 __ Push(r3, r2, cache_entry); | 3595 __ Push(r3, r2, cache_entry); |
| 3596 GenerateCallCFunction(masm, scratch0); | 3596 GenerateCallCFunction(masm, scratch0); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3637 __ push(scratch0); | 3637 __ push(scratch0); |
| 3638 __ CallRuntimeSaveDoubles(Runtime::kAllocateInNewSpace); | 3638 __ CallRuntimeSaveDoubles(Runtime::kAllocateInNewSpace); |
| 3639 } | 3639 } |
| 3640 __ Ret(); | 3640 __ Ret(); |
| 3641 } | 3641 } |
| 3642 } | 3642 } |
| 3643 | 3643 |
| 3644 | 3644 |
| 3645 void TranscendentalCacheStub::GenerateCallCFunction(MacroAssembler* masm, | 3645 void TranscendentalCacheStub::GenerateCallCFunction(MacroAssembler* masm, |
| 3646 Register scratch) { | 3646 Register scratch) { |
| 3647 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 3647 ASSERT(masm->IsEnabled(VFP2)); |
| 3648 Isolate* isolate = masm->isolate(); | 3648 Isolate* isolate = masm->isolate(); |
| 3649 | 3649 |
| 3650 __ push(lr); | 3650 __ push(lr); |
| 3651 __ PrepareCallCFunction(0, 1, scratch); | 3651 __ PrepareCallCFunction(0, 1, scratch); |
| 3652 if (masm->use_eabi_hardfloat()) { | 3652 if (masm->use_eabi_hardfloat()) { |
| 3653 __ vmov(d0, d2); | 3653 __ vmov(d0, d2); |
| 3654 } else { | 3654 } else { |
| 3655 __ vmov(r0, r1, d2); | 3655 __ vmov(r0, r1, d2); |
| 3656 } | 3656 } |
| 3657 AllowExternalCallThatCantCauseGC scope(masm); | 3657 AllowExternalCallThatCantCauseGC scope(masm); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3698 __ TailCallRuntime(Runtime::kStackGuard, 0, 1); | 3698 __ TailCallRuntime(Runtime::kStackGuard, 0, 1); |
| 3699 } | 3699 } |
| 3700 | 3700 |
| 3701 | 3701 |
| 3702 void InterruptStub::Generate(MacroAssembler* masm) { | 3702 void InterruptStub::Generate(MacroAssembler* masm) { |
| 3703 __ TailCallRuntime(Runtime::kInterrupt, 0, 1); | 3703 __ TailCallRuntime(Runtime::kInterrupt, 0, 1); |
| 3704 } | 3704 } |
| 3705 | 3705 |
| 3706 | 3706 |
| 3707 void MathPowStub::Generate(MacroAssembler* masm) { | 3707 void MathPowStub::Generate(MacroAssembler* masm) { |
| 3708 CpuFeatures::Scope vfp2_scope(VFP2); | 3708 CpuFeatureScope vfp2_scope(masm, VFP2); |
| 3709 const Register base = r1; | 3709 const Register base = r1; |
| 3710 const Register exponent = r2; | 3710 const Register exponent = r2; |
| 3711 const Register heapnumbermap = r5; | 3711 const Register heapnumbermap = r5; |
| 3712 const Register heapnumber = r0; | 3712 const Register heapnumber = r0; |
| 3713 const DwVfpRegister double_base = d1; | 3713 const DwVfpRegister double_base = d1; |
| 3714 const DwVfpRegister double_exponent = d2; | 3714 const DwVfpRegister double_exponent = d2; |
| 3715 const DwVfpRegister double_result = d3; | 3715 const DwVfpRegister double_result = d3; |
| 3716 const DwVfpRegister double_scratch = d0; | 3716 const DwVfpRegister double_scratch = d0; |
| 3717 const SwVfpRegister single_scratch = s0; | 3717 const SwVfpRegister single_scratch = s0; |
| 3718 const Register scratch = r9; | 3718 const Register scratch = r9; |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3924 | 3924 |
| 3925 void CodeStub::GenerateFPStubs(Isolate* isolate) { | 3925 void CodeStub::GenerateFPStubs(Isolate* isolate) { |
| 3926 SaveFPRegsMode mode = CpuFeatures::IsSupported(VFP2) | 3926 SaveFPRegsMode mode = CpuFeatures::IsSupported(VFP2) |
| 3927 ? kSaveFPRegs | 3927 ? kSaveFPRegs |
| 3928 : kDontSaveFPRegs; | 3928 : kDontSaveFPRegs; |
| 3929 CEntryStub save_doubles(1, mode); | 3929 CEntryStub save_doubles(1, mode); |
| 3930 StoreBufferOverflowStub stub(mode); | 3930 StoreBufferOverflowStub stub(mode); |
| 3931 // These stubs might already be in the snapshot, detect that and don't | 3931 // These stubs might already be in the snapshot, detect that and don't |
| 3932 // regenerate, which would lead to code stub initialization state being messed | 3932 // regenerate, which would lead to code stub initialization state being messed |
| 3933 // up. | 3933 // up. |
| 3934 Code* save_doubles_code = NULL; | 3934 Code* save_doubles_code; |
| 3935 Code* store_buffer_overflow_code = NULL; | 3935 if (!save_doubles.FindCodeInCache(&save_doubles_code, isolate)) { |
| 3936 if (!save_doubles.FindCodeInCache(&save_doubles_code, ISOLATE)) { | 3936 save_doubles_code = *save_doubles.GetCode(isolate); |
| 3937 if (CpuFeatures::IsSupported(VFP2)) { | |
| 3938 CpuFeatures::Scope scope2(VFP2); | |
| 3939 save_doubles_code = *save_doubles.GetCode(isolate); | |
| 3940 store_buffer_overflow_code = *stub.GetCode(isolate); | |
| 3941 } else { | |
| 3942 save_doubles_code = *save_doubles.GetCode(isolate); | |
| 3943 store_buffer_overflow_code = *stub.GetCode(isolate); | |
| 3944 } | |
| 3945 save_doubles_code->set_is_pregenerated(true); | 3937 save_doubles_code->set_is_pregenerated(true); |
| 3938 |
| 3939 Code* store_buffer_overflow_code = *stub.GetCode(isolate); |
| 3946 store_buffer_overflow_code->set_is_pregenerated(true); | 3940 store_buffer_overflow_code->set_is_pregenerated(true); |
| 3947 } | 3941 } |
| 3948 ISOLATE->set_fp_stubs_generated(true); | 3942 isolate->set_fp_stubs_generated(true); |
| 3949 } | 3943 } |
| 3950 | 3944 |
| 3951 | 3945 |
| 3952 void CEntryStub::GenerateAheadOfTime(Isolate* isolate) { | 3946 void CEntryStub::GenerateAheadOfTime(Isolate* isolate) { |
| 3953 CEntryStub stub(1, kDontSaveFPRegs); | 3947 CEntryStub stub(1, kDontSaveFPRegs); |
| 3954 Handle<Code> code = stub.GetCode(isolate); | 3948 Handle<Code> code = stub.GetCode(isolate); |
| 3955 code->set_is_pregenerated(true); | 3949 code->set_is_pregenerated(true); |
| 3956 } | 3950 } |
| 3957 | 3951 |
| 3958 | 3952 |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4185 // [sp+0]: argv | 4179 // [sp+0]: argv |
| 4186 | 4180 |
| 4187 Label invoke, handler_entry, exit; | 4181 Label invoke, handler_entry, exit; |
| 4188 | 4182 |
| 4189 // Called from C, so do not pop argc and args on exit (preserve sp) | 4183 // Called from C, so do not pop argc and args on exit (preserve sp) |
| 4190 // No need to save register-passed args | 4184 // No need to save register-passed args |
| 4191 // Save callee-saved registers (incl. cp and fp), sp, and lr | 4185 // Save callee-saved registers (incl. cp and fp), sp, and lr |
| 4192 __ stm(db_w, sp, kCalleeSaved | lr.bit()); | 4186 __ stm(db_w, sp, kCalleeSaved | lr.bit()); |
| 4193 | 4187 |
| 4194 if (CpuFeatures::IsSupported(VFP2)) { | 4188 if (CpuFeatures::IsSupported(VFP2)) { |
| 4195 CpuFeatures::Scope scope(VFP2); | 4189 CpuFeatureScope scope(masm, VFP2); |
| 4196 // Save callee-saved vfp registers. | 4190 // Save callee-saved vfp registers. |
| 4197 __ vstm(db_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg); | 4191 __ vstm(db_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg); |
| 4198 // Set up the reserved register for 0.0. | 4192 // Set up the reserved register for 0.0. |
| 4199 __ vmov(kDoubleRegZero, 0.0); | 4193 __ vmov(kDoubleRegZero, 0.0); |
| 4200 } | 4194 } |
| 4201 | 4195 |
| 4202 // Get address of argv, see stm above. | 4196 // Get address of argv, see stm above. |
| 4203 // r0: code entry | 4197 // r0: code entry |
| 4204 // r1: function | 4198 // r1: function |
| 4205 // r2: receiver | 4199 // r2: receiver |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4339 __ add(sp, sp, Operand(-EntryFrameConstants::kCallerFPOffset)); | 4333 __ add(sp, sp, Operand(-EntryFrameConstants::kCallerFPOffset)); |
| 4340 | 4334 |
| 4341 // Restore callee-saved registers and return. | 4335 // Restore callee-saved registers and return. |
| 4342 #ifdef DEBUG | 4336 #ifdef DEBUG |
| 4343 if (FLAG_debug_code) { | 4337 if (FLAG_debug_code) { |
| 4344 __ mov(lr, Operand(pc)); | 4338 __ mov(lr, Operand(pc)); |
| 4345 } | 4339 } |
| 4346 #endif | 4340 #endif |
| 4347 | 4341 |
| 4348 if (CpuFeatures::IsSupported(VFP2)) { | 4342 if (CpuFeatures::IsSupported(VFP2)) { |
| 4349 CpuFeatures::Scope scope(VFP2); | 4343 CpuFeatureScope scope(masm, VFP2); |
| 4350 // Restore callee-saved vfp registers. | 4344 // Restore callee-saved vfp registers. |
| 4351 __ vldm(ia_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg); | 4345 __ vldm(ia_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg); |
| 4352 } | 4346 } |
| 4353 | 4347 |
| 4354 __ ldm(ia_w, sp, kCalleeSaved | pc.bit()); | 4348 __ ldm(ia_w, sp, kCalleeSaved | pc.bit()); |
| 4355 } | 4349 } |
| 4356 | 4350 |
| 4357 | 4351 |
| 4358 // Uses registers r0 to r4. | 4352 // Uses registers r0 to r4. |
| 4359 // Expected input (depending on whether args are in registers or on the stack): | 4353 // Expected input (depending on whether args are in registers or on the stack): |
| (...skipping 2723 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7083 if (left_ == CompareIC::SMI) { | 7077 if (left_ == CompareIC::SMI) { |
| 7084 __ JumpIfNotSmi(r1, &miss); | 7078 __ JumpIfNotSmi(r1, &miss); |
| 7085 } | 7079 } |
| 7086 if (right_ == CompareIC::SMI) { | 7080 if (right_ == CompareIC::SMI) { |
| 7087 __ JumpIfNotSmi(r0, &miss); | 7081 __ JumpIfNotSmi(r0, &miss); |
| 7088 } | 7082 } |
| 7089 | 7083 |
| 7090 // Inlining the double comparison and falling back to the general compare | 7084 // Inlining the double comparison and falling back to the general compare |
| 7091 // stub if NaN is involved or VFP2 is unsupported. | 7085 // stub if NaN is involved or VFP2 is unsupported. |
| 7092 if (CpuFeatures::IsSupported(VFP2)) { | 7086 if (CpuFeatures::IsSupported(VFP2)) { |
| 7093 CpuFeatures::Scope scope(VFP2); | 7087 CpuFeatureScope scope(masm, VFP2); |
| 7094 | 7088 |
| 7095 // Load left and right operand. | 7089 // Load left and right operand. |
| 7096 Label done, left, left_smi, right_smi; | 7090 Label done, left, left_smi, right_smi; |
| 7097 __ JumpIfSmi(r0, &right_smi); | 7091 __ JumpIfSmi(r0, &right_smi); |
| 7098 __ CheckMap(r0, r2, Heap::kHeapNumberMapRootIndex, &maybe_undefined1, | 7092 __ CheckMap(r0, r2, Heap::kHeapNumberMapRootIndex, &maybe_undefined1, |
| 7099 DONT_DO_SMI_CHECK); | 7093 DONT_DO_SMI_CHECK); |
| 7100 __ sub(r2, r0, Operand(kHeapObjectTag)); | 7094 __ sub(r2, r0, Operand(kHeapObjectTag)); |
| 7101 __ vldr(d1, r2, HeapNumber::kValueOffset); | 7095 __ vldr(d1, r2, HeapNumber::kValueOffset); |
| 7102 __ b(&left); | 7096 __ b(&left); |
| 7103 __ bind(&right_smi); | 7097 __ bind(&right_smi); |
| (...skipping 1003 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8107 | 8101 |
| 8108 __ Pop(lr, r5, r1); | 8102 __ Pop(lr, r5, r1); |
| 8109 __ Ret(); | 8103 __ Ret(); |
| 8110 } | 8104 } |
| 8111 | 8105 |
| 8112 #undef __ | 8106 #undef __ |
| 8113 | 8107 |
| 8114 } } // namespace v8::internal | 8108 } } // namespace v8::internal |
| 8115 | 8109 |
| 8116 #endif // V8_TARGET_ARCH_ARM | 8110 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |