Chromium Code Reviews| 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 581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 592 exponent, | 592 exponent, |
| 593 Operand(source_, LSR, 32 - HeapNumber::kMantissaBitsInTopWord)); | 593 Operand(source_, LSR, 32 - HeapNumber::kMantissaBitsInTopWord)); |
| 594 __ Ret(); | 594 __ Ret(); |
| 595 } | 595 } |
| 596 | 596 |
| 597 | 597 |
| 598 void FloatingPointHelper::LoadSmis(MacroAssembler* masm, | 598 void FloatingPointHelper::LoadSmis(MacroAssembler* masm, |
| 599 FloatingPointHelper::Destination destination, | 599 FloatingPointHelper::Destination destination, |
| 600 Register scratch1, | 600 Register scratch1, |
| 601 Register scratch2) { | 601 Register scratch2) { |
| 602 if (CpuFeatures::IsSupported(VFP3)) { | 602 if (CpuFeatures::IsSupported(VFP2)) { |
| 603 CpuFeatures::Scope scope(VFP3); | 603 CpuFeatures::Scope scope(VFP2); |
| 604 __ mov(scratch1, Operand(r0, ASR, kSmiTagSize)); | 604 __ mov(scratch1, Operand(r0, ASR, kSmiTagSize)); |
| 605 __ vmov(d7.high(), scratch1); | 605 __ vmov(d7.high(), scratch1); |
| 606 __ vcvt_f64_s32(d7, d7.high()); | 606 __ vcvt_f64_s32(d7, d7.high()); |
| 607 __ mov(scratch1, Operand(r1, ASR, kSmiTagSize)); | 607 __ mov(scratch1, Operand(r1, ASR, kSmiTagSize)); |
| 608 __ vmov(d6.high(), scratch1); | 608 __ vmov(d6.high(), scratch1); |
| 609 __ vcvt_f64_s32(d6, d6.high()); | 609 __ vcvt_f64_s32(d6, d6.high()); |
| 610 if (destination == kCoreRegisters) { | 610 if (destination == kCoreRegisters) { |
| 611 __ vmov(r2, r3, d7); | 611 __ vmov(r2, r3, d7); |
| 612 __ vmov(r0, r1, d6); | 612 __ vmov(r0, r1, d6); |
| 613 } | 613 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 662 } | 662 } |
| 663 | 663 |
| 664 Label is_smi, done; | 664 Label is_smi, done; |
| 665 | 665 |
| 666 // Smi-check | 666 // Smi-check |
| 667 __ UntagAndJumpIfSmi(scratch1, object, &is_smi); | 667 __ UntagAndJumpIfSmi(scratch1, object, &is_smi); |
| 668 // Heap number check | 668 // Heap number check |
| 669 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number); | 669 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number); |
| 670 | 670 |
| 671 // Handle loading a double from a heap number. | 671 // Handle loading a double from a heap number. |
| 672 if (CpuFeatures::IsSupported(VFP3) && | 672 if (CpuFeatures::IsSupported(VFP2) && |
| 673 destination == kVFPRegisters) { | 673 destination == kVFPRegisters) { |
| 674 CpuFeatures::Scope scope(VFP3); | 674 CpuFeatures::Scope scope(VFP2); |
| 675 // Load the double from tagged HeapNumber to double register. | 675 // Load the double from tagged HeapNumber to double register. |
| 676 __ sub(scratch1, object, Operand(kHeapObjectTag)); | 676 __ sub(scratch1, object, Operand(kHeapObjectTag)); |
| 677 __ vldr(dst, scratch1, HeapNumber::kValueOffset); | 677 __ vldr(dst, scratch1, HeapNumber::kValueOffset); |
| 678 } else { | 678 } else { |
| 679 ASSERT(destination == kCoreRegisters); | 679 ASSERT(destination == kCoreRegisters); |
| 680 // Load the double from heap number to dst1 and dst2 in double format. | 680 // Load the double from heap number to dst1 and dst2 in double format. |
| 681 __ Ldrd(dst1, dst2, FieldMemOperand(object, HeapNumber::kValueOffset)); | 681 __ Ldrd(dst1, dst2, FieldMemOperand(object, HeapNumber::kValueOffset)); |
| 682 } | 682 } |
| 683 __ jmp(&done); | 683 __ jmp(&done); |
| 684 | 684 |
| 685 // Handle loading a double from a smi. | 685 // Handle loading a double from a smi. |
| 686 __ bind(&is_smi); | 686 __ bind(&is_smi); |
| 687 if (CpuFeatures::IsSupported(VFP3)) { | 687 if (CpuFeatures::IsSupported(VFP2)) { |
| 688 CpuFeatures::Scope scope(VFP3); | 688 CpuFeatures::Scope scope(VFP2); |
| 689 // Convert smi to double using VFP instructions. | 689 // Convert smi to double using VFP instructions. |
| 690 __ vmov(dst.high(), scratch1); | 690 __ vmov(dst.high(), scratch1); |
| 691 __ vcvt_f64_s32(dst, dst.high()); | 691 __ vcvt_f64_s32(dst, dst.high()); |
| 692 if (destination == kCoreRegisters) { | 692 if (destination == kCoreRegisters) { |
| 693 // Load the converted smi to dst1 and dst2 in double format. | 693 // Load the converted smi to dst1 and dst2 in double format. |
| 694 __ vmov(dst1, dst2, dst); | 694 __ vmov(dst1, dst2, dst); |
| 695 } | 695 } |
| 696 } else { | 696 } else { |
| 697 ASSERT(destination == kCoreRegisters); | 697 ASSERT(destination == kCoreRegisters); |
| 698 // Write smi to dst1 and dst2 double format. | 698 // Write smi to dst1 and dst2 double format. |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 755 Register dst1, | 755 Register dst1, |
| 756 Register dst2, | 756 Register dst2, |
| 757 Register scratch2, | 757 Register scratch2, |
| 758 SwVfpRegister single_scratch) { | 758 SwVfpRegister single_scratch) { |
| 759 ASSERT(!int_scratch.is(scratch2)); | 759 ASSERT(!int_scratch.is(scratch2)); |
| 760 ASSERT(!int_scratch.is(dst1)); | 760 ASSERT(!int_scratch.is(dst1)); |
| 761 ASSERT(!int_scratch.is(dst2)); | 761 ASSERT(!int_scratch.is(dst2)); |
| 762 | 762 |
| 763 Label done; | 763 Label done; |
| 764 | 764 |
| 765 if (CpuFeatures::IsSupported(VFP3)) { | 765 if (CpuFeatures::IsSupported(VFP2)) { |
| 766 CpuFeatures::Scope scope(VFP3); | 766 CpuFeatures::Scope scope(VFP2); |
| 767 __ vmov(single_scratch, int_scratch); | 767 __ vmov(single_scratch, int_scratch); |
| 768 __ vcvt_f64_s32(double_dst, single_scratch); | 768 __ vcvt_f64_s32(double_dst, single_scratch); |
| 769 if (destination == kCoreRegisters) { | 769 if (destination == kCoreRegisters) { |
| 770 __ vmov(dst1, dst2, double_dst); | 770 __ vmov(dst1, dst2, double_dst); |
| 771 } | 771 } |
| 772 } else { | 772 } else { |
| 773 Label fewer_than_20_useful_bits; | 773 Label fewer_than_20_useful_bits; |
| 774 // Expected output: | 774 // Expected output: |
| 775 // | dst2 | dst1 | | 775 // | dst2 | dst1 | |
| 776 // | s | exp | mantissa | | 776 // | s | exp | mantissa | |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 849 | 849 |
| 850 __ bind(&obj_is_not_smi); | 850 __ bind(&obj_is_not_smi); |
| 851 if (FLAG_debug_code) { | 851 if (FLAG_debug_code) { |
| 852 __ AbortIfNotRootValue(heap_number_map, | 852 __ AbortIfNotRootValue(heap_number_map, |
| 853 Heap::kHeapNumberMapRootIndex, | 853 Heap::kHeapNumberMapRootIndex, |
| 854 "HeapNumberMap register clobbered."); | 854 "HeapNumberMap register clobbered."); |
| 855 } | 855 } |
| 856 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32); | 856 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32); |
| 857 | 857 |
| 858 // Load the number. | 858 // Load the number. |
| 859 if (CpuFeatures::IsSupported(VFP3)) { | 859 if (CpuFeatures::IsSupported(VFP2)) { |
| 860 CpuFeatures::Scope scope(VFP3); | 860 CpuFeatures::Scope scope(VFP2); |
| 861 // Load the double value. | 861 // Load the double value. |
| 862 __ sub(scratch1, object, Operand(kHeapObjectTag)); | 862 __ sub(scratch1, object, Operand(kHeapObjectTag)); |
| 863 __ vldr(double_dst, scratch1, HeapNumber::kValueOffset); | 863 __ vldr(double_dst, scratch1, HeapNumber::kValueOffset); |
| 864 | 864 |
| 865 __ EmitVFPTruncate(kRoundToZero, | 865 __ EmitVFPTruncate(kRoundToZero, |
| 866 single_scratch, | 866 single_scratch, |
| 867 double_dst, | 867 double_dst, |
| 868 scratch1, | 868 scratch1, |
| 869 scratch2, | 869 scratch2, |
| 870 kCheckForInexactConversion); | 870 kCheckForInexactConversion); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 920 | 920 |
| 921 if (FLAG_debug_code) { | 921 if (FLAG_debug_code) { |
| 922 __ AbortIfNotRootValue(heap_number_map, | 922 __ AbortIfNotRootValue(heap_number_map, |
| 923 Heap::kHeapNumberMapRootIndex, | 923 Heap::kHeapNumberMapRootIndex, |
| 924 "HeapNumberMap register clobbered."); | 924 "HeapNumberMap register clobbered."); |
| 925 } | 925 } |
| 926 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32); | 926 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32); |
| 927 | 927 |
| 928 // Object is a heap number. | 928 // Object is a heap number. |
| 929 // Convert the floating point value to a 32-bit integer. | 929 // Convert the floating point value to a 32-bit integer. |
| 930 if (CpuFeatures::IsSupported(VFP3)) { | 930 if (CpuFeatures::IsSupported(VFP2)) { |
| 931 CpuFeatures::Scope scope(VFP3); | 931 CpuFeatures::Scope scope(VFP2); |
| 932 SwVfpRegister single_scratch = double_scratch.low(); | 932 SwVfpRegister single_scratch = double_scratch.low(); |
| 933 // Load the double value. | 933 // Load the double value. |
| 934 __ sub(scratch1, object, Operand(kHeapObjectTag)); | 934 __ sub(scratch1, object, Operand(kHeapObjectTag)); |
| 935 __ vldr(double_scratch, scratch1, HeapNumber::kValueOffset); | 935 __ vldr(double_scratch, scratch1, HeapNumber::kValueOffset); |
| 936 | 936 |
| 937 __ EmitVFPTruncate(kRoundToZero, | 937 __ EmitVFPTruncate(kRoundToZero, |
| 938 single_scratch, | 938 single_scratch, |
| 939 double_scratch, | 939 double_scratch, |
| 940 scratch1, | 940 scratch1, |
| 941 scratch2, | 941 scratch2, |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1051 | 1051 |
| 1052 // Assert that heap_number_result is callee-saved. | 1052 // Assert that heap_number_result is callee-saved. |
| 1053 // We currently always use r5 to pass it. | 1053 // We currently always use r5 to pass it. |
| 1054 ASSERT(heap_number_result.is(r5)); | 1054 ASSERT(heap_number_result.is(r5)); |
| 1055 | 1055 |
| 1056 // Push the current return address before the C call. Return will be | 1056 // Push the current return address before the C call. Return will be |
| 1057 // through pop(pc) below. | 1057 // through pop(pc) below. |
| 1058 __ push(lr); | 1058 __ push(lr); |
| 1059 __ PrepareCallCFunction(0, 2, scratch); | 1059 __ PrepareCallCFunction(0, 2, scratch); |
| 1060 if (masm->use_eabi_hardfloat()) { | 1060 if (masm->use_eabi_hardfloat()) { |
| 1061 CpuFeatures::Scope scope(VFP3); | 1061 CpuFeatures::Scope scope(VFP2); |
| 1062 __ vmov(d0, r0, r1); | 1062 __ vmov(d0, r0, r1); |
| 1063 __ vmov(d1, r2, r3); | 1063 __ vmov(d1, r2, r3); |
| 1064 } | 1064 } |
| 1065 { | 1065 { |
| 1066 AllowExternalCallThatCantCauseGC scope(masm); | 1066 AllowExternalCallThatCantCauseGC scope(masm); |
| 1067 __ CallCFunction( | 1067 __ CallCFunction( |
| 1068 ExternalReference::double_fp_operation(op, masm->isolate()), 0, 2); | 1068 ExternalReference::double_fp_operation(op, masm->isolate()), 0, 2); |
| 1069 } | 1069 } |
| 1070 // Store answer in the overwritable heap number. Double returned in | 1070 // Store answer in the overwritable heap number. Double returned in |
| 1071 // registers r0 and r1 or in d0. | 1071 // registers r0 and r1 or in d0. |
| 1072 if (masm->use_eabi_hardfloat()) { | 1072 if (masm->use_eabi_hardfloat()) { |
| 1073 CpuFeatures::Scope scope(VFP3); | 1073 CpuFeatures::Scope scope(VFP2); |
| 1074 __ vstr(d0, | 1074 __ vstr(d0, |
| 1075 FieldMemOperand(heap_number_result, HeapNumber::kValueOffset)); | 1075 FieldMemOperand(heap_number_result, HeapNumber::kValueOffset)); |
| 1076 } else { | 1076 } else { |
| 1077 __ Strd(r0, r1, FieldMemOperand(heap_number_result, | 1077 __ Strd(r0, r1, FieldMemOperand(heap_number_result, |
| 1078 HeapNumber::kValueOffset)); | 1078 HeapNumber::kValueOffset)); |
| 1079 } | 1079 } |
| 1080 // Place heap_number_result in r0 and return to the pushed return address. | 1080 // Place heap_number_result in r0 and return to the pushed return address. |
| 1081 __ mov(r0, Operand(heap_number_result)); | 1081 __ mov(r0, Operand(heap_number_result)); |
| 1082 __ pop(pc); | 1082 __ pop(pc); |
| 1083 } | 1083 } |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1282 __ mov(r0, Operand(NOT_EQUAL), LeaveCC, ne); | 1282 __ mov(r0, Operand(NOT_EQUAL), LeaveCC, ne); |
| 1283 } | 1283 } |
| 1284 __ Ret(ne); | 1284 __ Ret(ne); |
| 1285 } else { | 1285 } else { |
| 1286 // Smi compared non-strictly with a non-Smi non-heap-number. Call | 1286 // Smi compared non-strictly with a non-Smi non-heap-number. Call |
| 1287 // the runtime. | 1287 // the runtime. |
| 1288 __ b(ne, slow); | 1288 __ b(ne, slow); |
| 1289 } | 1289 } |
| 1290 | 1290 |
| 1291 // Lhs is a smi, rhs is a number. | 1291 // Lhs is a smi, rhs is a number. |
| 1292 if (CpuFeatures::IsSupported(VFP3)) { | 1292 if (CpuFeatures::IsSupported(VFP2)) { |
| 1293 // Convert lhs to a double in d7. | 1293 // Convert lhs to a double in d7. |
| 1294 CpuFeatures::Scope scope(VFP3); | 1294 CpuFeatures::Scope scope(VFP2); |
| 1295 __ SmiToDoubleVFPRegister(lhs, d7, r7, s15); | 1295 __ SmiToDoubleVFPRegister(lhs, d7, r7, s15); |
| 1296 // Load the double from rhs, tagged HeapNumber r0, to d6. | 1296 // Load the double from rhs, tagged HeapNumber r0, to d6. |
| 1297 __ sub(r7, rhs, Operand(kHeapObjectTag)); | 1297 __ sub(r7, rhs, Operand(kHeapObjectTag)); |
| 1298 __ vldr(d6, r7, HeapNumber::kValueOffset); | 1298 __ vldr(d6, r7, HeapNumber::kValueOffset); |
| 1299 } else { | 1299 } else { |
| 1300 __ push(lr); | 1300 __ push(lr); |
| 1301 // Convert lhs to a double in r2, r3. | 1301 // Convert lhs to a double in r2, r3. |
| 1302 __ mov(r7, Operand(lhs)); | 1302 __ mov(r7, Operand(lhs)); |
| 1303 ConvertToDoubleStub stub1(r3, r2, r7, r6); | 1303 ConvertToDoubleStub stub1(r3, r2, r7, r6); |
| 1304 __ Call(stub1.GetCode()); | 1304 __ Call(stub1.GetCode()); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 1322 __ mov(r0, Operand(NOT_EQUAL), LeaveCC, ne); | 1322 __ mov(r0, Operand(NOT_EQUAL), LeaveCC, ne); |
| 1323 } | 1323 } |
| 1324 __ Ret(ne); | 1324 __ Ret(ne); |
| 1325 } else { | 1325 } else { |
| 1326 // Smi compared non-strictly with a non-smi non-heap-number. Call | 1326 // Smi compared non-strictly with a non-smi non-heap-number. Call |
| 1327 // the runtime. | 1327 // the runtime. |
| 1328 __ b(ne, slow); | 1328 __ b(ne, slow); |
| 1329 } | 1329 } |
| 1330 | 1330 |
| 1331 // Rhs is a smi, lhs is a heap number. | 1331 // Rhs is a smi, lhs is a heap number. |
| 1332 if (CpuFeatures::IsSupported(VFP3)) { | 1332 if (CpuFeatures::IsSupported(VFP2)) { |
| 1333 CpuFeatures::Scope scope(VFP3); | 1333 CpuFeatures::Scope scope(VFP2); |
| 1334 // Load the double from lhs, tagged HeapNumber r1, to d7. | 1334 // Load the double from lhs, tagged HeapNumber r1, to d7. |
| 1335 __ sub(r7, lhs, Operand(kHeapObjectTag)); | 1335 __ sub(r7, lhs, Operand(kHeapObjectTag)); |
| 1336 __ vldr(d7, r7, HeapNumber::kValueOffset); | 1336 __ vldr(d7, r7, HeapNumber::kValueOffset); |
| 1337 // Convert rhs to a double in d6 . | 1337 // Convert rhs to a double in d6 . |
| 1338 __ SmiToDoubleVFPRegister(rhs, d6, r7, s13); | 1338 __ SmiToDoubleVFPRegister(rhs, d6, r7, s13); |
| 1339 } else { | 1339 } else { |
| 1340 __ push(lr); | 1340 __ push(lr); |
| 1341 // Load lhs to a double in r2, r3. | 1341 // Load lhs to a double in r2, r3. |
| 1342 __ Ldrd(r2, r3, FieldMemOperand(lhs, HeapNumber::kValueOffset)); | 1342 __ Ldrd(r2, r3, FieldMemOperand(lhs, HeapNumber::kValueOffset)); |
| 1343 // Convert rhs to a double in r0, r1. | 1343 // Convert rhs to a double in r0, r1. |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1435 // Now they are equal if and only if the lhs exponent is zero in its | 1435 // Now they are equal if and only if the lhs exponent is zero in its |
| 1436 // low 31 bits. | 1436 // low 31 bits. |
| 1437 __ mov(r0, Operand(rhs_exponent, LSL, kSmiTagSize)); | 1437 __ mov(r0, Operand(rhs_exponent, LSL, kSmiTagSize)); |
| 1438 __ Ret(); | 1438 __ Ret(); |
| 1439 } else { | 1439 } else { |
| 1440 // Call a native function to do a comparison between two non-NaNs. | 1440 // Call a native function to do a comparison between two non-NaNs. |
| 1441 // Call C routine that may not cause GC or other trouble. | 1441 // Call C routine that may not cause GC or other trouble. |
| 1442 __ push(lr); | 1442 __ push(lr); |
| 1443 __ PrepareCallCFunction(0, 2, r5); | 1443 __ PrepareCallCFunction(0, 2, r5); |
| 1444 if (masm->use_eabi_hardfloat()) { | 1444 if (masm->use_eabi_hardfloat()) { |
| 1445 CpuFeatures::Scope scope(VFP3); | 1445 CpuFeatures::Scope scope(VFP2); |
| 1446 __ vmov(d0, r0, r1); | 1446 __ vmov(d0, r0, r1); |
| 1447 __ vmov(d1, r2, r3); | 1447 __ vmov(d1, r2, r3); |
| 1448 } | 1448 } |
| 1449 | 1449 |
| 1450 AllowExternalCallThatCantCauseGC scope(masm); | 1450 AllowExternalCallThatCantCauseGC scope(masm); |
| 1451 __ CallCFunction(ExternalReference::compare_doubles(masm->isolate()), | 1451 __ CallCFunction(ExternalReference::compare_doubles(masm->isolate()), |
| 1452 0, 2); | 1452 0, 2); |
| 1453 __ pop(pc); // Return. | 1453 __ pop(pc); // Return. |
| 1454 } | 1454 } |
| 1455 } | 1455 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1510 (lhs.is(r1) && rhs.is(r0))); | 1510 (lhs.is(r1) && rhs.is(r0))); |
| 1511 | 1511 |
| 1512 __ CompareObjectType(rhs, r3, r2, HEAP_NUMBER_TYPE); | 1512 __ CompareObjectType(rhs, r3, r2, HEAP_NUMBER_TYPE); |
| 1513 __ b(ne, not_heap_numbers); | 1513 __ b(ne, not_heap_numbers); |
| 1514 __ ldr(r2, FieldMemOperand(lhs, HeapObject::kMapOffset)); | 1514 __ ldr(r2, FieldMemOperand(lhs, HeapObject::kMapOffset)); |
| 1515 __ cmp(r2, r3); | 1515 __ cmp(r2, r3); |
| 1516 __ b(ne, slow); // First was a heap number, second wasn't. Go slow case. | 1516 __ b(ne, slow); // First was a heap number, second wasn't. Go slow case. |
| 1517 | 1517 |
| 1518 // Both are heap numbers. Load them up then jump to the code we have | 1518 // Both are heap numbers. Load them up then jump to the code we have |
| 1519 // for that. | 1519 // for that. |
| 1520 if (CpuFeatures::IsSupported(VFP3)) { | 1520 if (CpuFeatures::IsSupported(VFP2)) { |
| 1521 CpuFeatures::Scope scope(VFP3); | 1521 CpuFeatures::Scope scope(VFP2); |
| 1522 __ sub(r7, rhs, Operand(kHeapObjectTag)); | 1522 __ sub(r7, rhs, Operand(kHeapObjectTag)); |
| 1523 __ vldr(d6, r7, HeapNumber::kValueOffset); | 1523 __ vldr(d6, r7, HeapNumber::kValueOffset); |
| 1524 __ sub(r7, lhs, Operand(kHeapObjectTag)); | 1524 __ sub(r7, lhs, Operand(kHeapObjectTag)); |
| 1525 __ vldr(d7, r7, HeapNumber::kValueOffset); | 1525 __ vldr(d7, r7, HeapNumber::kValueOffset); |
| 1526 } else { | 1526 } else { |
| 1527 __ Ldrd(r2, r3, FieldMemOperand(lhs, HeapNumber::kValueOffset)); | 1527 __ Ldrd(r2, r3, FieldMemOperand(lhs, HeapNumber::kValueOffset)); |
| 1528 __ Ldrd(r0, r1, FieldMemOperand(rhs, HeapNumber::kValueOffset)); | 1528 __ Ldrd(r0, r1, FieldMemOperand(rhs, HeapNumber::kValueOffset)); |
| 1529 } | 1529 } |
| 1530 __ jmp(both_loaded_as_doubles); | 1530 __ jmp(both_loaded_as_doubles); |
| 1531 } | 1531 } |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1600 | 1600 |
| 1601 // Calculate the entry in the number string cache. The hash value in the | 1601 // Calculate the entry in the number string cache. The hash value in the |
| 1602 // number string cache for smis is just the smi value, and the hash for | 1602 // number string cache for smis is just the smi value, and the hash for |
| 1603 // doubles is the xor of the upper and lower words. See | 1603 // doubles is the xor of the upper and lower words. See |
| 1604 // Heap::GetNumberStringCache. | 1604 // Heap::GetNumberStringCache. |
| 1605 Isolate* isolate = masm->isolate(); | 1605 Isolate* isolate = masm->isolate(); |
| 1606 Label is_smi; | 1606 Label is_smi; |
| 1607 Label load_result_from_cache; | 1607 Label load_result_from_cache; |
| 1608 if (!object_is_smi) { | 1608 if (!object_is_smi) { |
| 1609 __ JumpIfSmi(object, &is_smi); | 1609 __ JumpIfSmi(object, &is_smi); |
| 1610 if (CpuFeatures::IsSupported(VFP3)) { | 1610 if (CpuFeatures::IsSupported(VFP2)) { |
| 1611 CpuFeatures::Scope scope(VFP3); | 1611 CpuFeatures::Scope scope(VFP2); |
| 1612 __ CheckMap(object, | 1612 __ CheckMap(object, |
| 1613 scratch1, | 1613 scratch1, |
| 1614 Heap::kHeapNumberMapRootIndex, | 1614 Heap::kHeapNumberMapRootIndex, |
| 1615 not_found, | 1615 not_found, |
| 1616 DONT_DO_SMI_CHECK); | 1616 DONT_DO_SMI_CHECK); |
| 1617 | 1617 |
| 1618 STATIC_ASSERT(8 == kDoubleSize); | 1618 STATIC_ASSERT(8 == kDoubleSize); |
| 1619 __ add(scratch1, | 1619 __ add(scratch1, |
| 1620 object, | 1620 object, |
| 1621 Operand(HeapNumber::kValueOffset - kHeapObjectTag)); | 1621 Operand(HeapNumber::kValueOffset - kHeapObjectTag)); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1732 // In cases 3 and 4 we have found out we were dealing with a number-number | 1732 // In cases 3 and 4 we have found out we were dealing with a number-number |
| 1733 // comparison. If VFP3 is supported the double values of the numbers have | 1733 // comparison. If VFP3 is supported the double values of the numbers have |
| 1734 // been loaded into d7 and d6. Otherwise, the double values have been loaded | 1734 // been loaded into d7 and d6. Otherwise, the double values have been loaded |
| 1735 // into r0, r1, r2, and r3. | 1735 // into r0, r1, r2, and r3. |
| 1736 EmitSmiNonsmiComparison(masm, lhs_, rhs_, &lhs_not_nan, &slow, strict_); | 1736 EmitSmiNonsmiComparison(masm, lhs_, rhs_, &lhs_not_nan, &slow, strict_); |
| 1737 | 1737 |
| 1738 __ bind(&both_loaded_as_doubles); | 1738 __ bind(&both_loaded_as_doubles); |
| 1739 // The arguments have been converted to doubles and stored in d6 and d7, if | 1739 // The arguments have been converted to doubles and stored in d6 and d7, if |
| 1740 // VFP3 is supported, or in r0, r1, r2, and r3. | 1740 // VFP3 is supported, or in r0, r1, r2, and r3. |
| 1741 Isolate* isolate = masm->isolate(); | 1741 Isolate* isolate = masm->isolate(); |
| 1742 if (CpuFeatures::IsSupported(VFP3)) { | 1742 if (CpuFeatures::IsSupported(VFP2)) { |
| 1743 __ bind(&lhs_not_nan); | 1743 __ bind(&lhs_not_nan); |
| 1744 CpuFeatures::Scope scope(VFP3); | 1744 CpuFeatures::Scope scope(VFP2); |
| 1745 Label no_nan; | 1745 Label no_nan; |
| 1746 // ARMv7 VFP3 instructions to implement double precision comparison. | 1746 // ARMv7 VFP3 instructions to implement double precision comparison. |
| 1747 __ VFPCompareAndSetFlags(d7, d6); | 1747 __ VFPCompareAndSetFlags(d7, d6); |
| 1748 Label nan; | 1748 Label nan; |
| 1749 __ b(vs, &nan); | 1749 __ b(vs, &nan); |
| 1750 __ mov(r0, Operand(EQUAL), LeaveCC, eq); | 1750 __ mov(r0, Operand(EQUAL), LeaveCC, eq); |
| 1751 __ mov(r0, Operand(LESS), LeaveCC, lt); | 1751 __ mov(r0, Operand(LESS), LeaveCC, lt); |
| 1752 __ mov(r0, Operand(GREATER), LeaveCC, gt); | 1752 __ mov(r0, Operand(GREATER), LeaveCC, gt); |
| 1753 __ Ret(); | 1753 __ Ret(); |
| 1754 | 1754 |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1853 __ InvokeBuiltin(native, JUMP_FUNCTION); | 1853 __ InvokeBuiltin(native, JUMP_FUNCTION); |
| 1854 } | 1854 } |
| 1855 | 1855 |
| 1856 | 1856 |
| 1857 // The stub expects its argument in the tos_ register and returns its result in | 1857 // The stub expects its argument in the tos_ register and returns its result in |
| 1858 // it, too: zero for false, and a non-zero value for true. | 1858 // it, too: zero for false, and a non-zero value for true. |
| 1859 void ToBooleanStub::Generate(MacroAssembler* masm) { | 1859 void ToBooleanStub::Generate(MacroAssembler* masm) { |
| 1860 // This stub overrides SometimesSetsUpAFrame() to return false. That means | 1860 // This stub overrides SometimesSetsUpAFrame() to return false. That means |
| 1861 // we cannot call anything that could cause a GC from this stub. | 1861 // we cannot call anything that could cause a GC from this stub. |
| 1862 // This stub uses VFP3 instructions. | 1862 // This stub uses VFP3 instructions. |
| 1863 CpuFeatures::Scope scope(VFP3); | 1863 CpuFeatures::Scope scope(VFP2); |
| 1864 | 1864 |
| 1865 Label patch; | 1865 Label patch; |
| 1866 const Register map = r9.is(tos_) ? r7 : r9; | 1866 const Register map = r9.is(tos_) ? r7 : r9; |
| 1867 | 1867 |
| 1868 // undefined -> false. | 1868 // undefined -> false. |
| 1869 CheckOddball(masm, UNDEFINED, Heap::kUndefinedValueRootIndex, false); | 1869 CheckOddball(masm, UNDEFINED, Heap::kUndefinedValueRootIndex, false); |
| 1870 | 1870 |
| 1871 // Boolean -> its value. | 1871 // Boolean -> its value. |
| 1872 CheckOddball(masm, BOOLEAN, Heap::kFalseValueRootIndex, false); | 1872 CheckOddball(masm, BOOLEAN, Heap::kFalseValueRootIndex, false); |
| 1873 CheckOddball(masm, BOOLEAN, Heap::kTrueValueRootIndex, true); | 1873 CheckOddball(masm, BOOLEAN, Heap::kTrueValueRootIndex, true); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1965 1); | 1965 1); |
| 1966 } | 1966 } |
| 1967 | 1967 |
| 1968 | 1968 |
| 1969 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { | 1969 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { |
| 1970 // We don't allow a GC during a store buffer overflow so there is no need to | 1970 // We don't allow a GC during a store buffer overflow so there is no need to |
| 1971 // store the registers in any particular way, but we do have to store and | 1971 // store the registers in any particular way, but we do have to store and |
| 1972 // restore them. | 1972 // restore them. |
| 1973 __ stm(db_w, sp, kCallerSaved | lr.bit()); | 1973 __ stm(db_w, sp, kCallerSaved | lr.bit()); |
| 1974 if (save_doubles_ == kSaveFPRegs) { | 1974 if (save_doubles_ == kSaveFPRegs) { |
| 1975 CpuFeatures::Scope scope(VFP3); | 1975 CpuFeatures::Scope scope(VFP2); |
| 1976 __ sub(sp, sp, Operand(kDoubleSize * DwVfpRegister::kNumRegisters)); | 1976 __ sub(sp, sp, Operand(kDoubleSize * DwVfpRegister::kNumRegisters)); |
| 1977 for (int i = 0; i < DwVfpRegister::kNumRegisters; i++) { | 1977 for (int i = 0; i < DwVfpRegister::kNumRegisters; i++) { |
| 1978 DwVfpRegister reg = DwVfpRegister::from_code(i); | 1978 DwVfpRegister reg = DwVfpRegister::from_code(i); |
| 1979 __ vstr(reg, MemOperand(sp, i * kDoubleSize)); | 1979 __ vstr(reg, MemOperand(sp, i * kDoubleSize)); |
| 1980 } | 1980 } |
| 1981 } | 1981 } |
| 1982 const int argument_count = 1; | 1982 const int argument_count = 1; |
| 1983 const int fp_argument_count = 0; | 1983 const int fp_argument_count = 0; |
| 1984 const Register scratch = r1; | 1984 const Register scratch = r1; |
| 1985 | 1985 |
| 1986 AllowExternalCallThatCantCauseGC scope(masm); | 1986 AllowExternalCallThatCantCauseGC scope(masm); |
| 1987 __ PrepareCallCFunction(argument_count, fp_argument_count, scratch); | 1987 __ PrepareCallCFunction(argument_count, fp_argument_count, scratch); |
| 1988 __ mov(r0, Operand(ExternalReference::isolate_address())); | 1988 __ mov(r0, Operand(ExternalReference::isolate_address())); |
| 1989 __ CallCFunction( | 1989 __ CallCFunction( |
| 1990 ExternalReference::store_buffer_overflow_function(masm->isolate()), | 1990 ExternalReference::store_buffer_overflow_function(masm->isolate()), |
| 1991 argument_count); | 1991 argument_count); |
| 1992 if (save_doubles_ == kSaveFPRegs) { | 1992 if (save_doubles_ == kSaveFPRegs) { |
| 1993 CpuFeatures::Scope scope(VFP3); | 1993 CpuFeatures::Scope scope(VFP2); |
| 1994 for (int i = 0; i < DwVfpRegister::kNumRegisters; i++) { | 1994 for (int i = 0; i < DwVfpRegister::kNumRegisters; i++) { |
| 1995 DwVfpRegister reg = DwVfpRegister::from_code(i); | 1995 DwVfpRegister reg = DwVfpRegister::from_code(i); |
| 1996 __ vldr(reg, MemOperand(sp, i * kDoubleSize)); | 1996 __ vldr(reg, MemOperand(sp, i * kDoubleSize)); |
| 1997 } | 1997 } |
| 1998 __ add(sp, sp, Operand(kDoubleSize * DwVfpRegister::kNumRegisters)); | 1998 __ add(sp, sp, Operand(kDoubleSize * DwVfpRegister::kNumRegisters)); |
| 1999 } | 1999 } |
| 2000 __ ldm(ia_w, sp, kCallerSaved | pc.bit()); // Also pop pc to get Ret(0). | 2000 __ ldm(ia_w, sp, kCallerSaved | pc.bit()); // Also pop pc to get Ret(0). |
| 2001 } | 2001 } |
| 2002 | 2002 |
| 2003 | 2003 |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2213 // Convert the heap number in r0 to an untagged integer in r1. | 2213 // Convert the heap number in r0 to an untagged integer in r1. |
| 2214 // This can't go slow-case because it's the same number we already | 2214 // This can't go slow-case because it's the same number we already |
| 2215 // converted once again. | 2215 // converted once again. |
| 2216 __ ConvertToInt32(r0, r1, r3, r4, d0, &impossible); | 2216 __ ConvertToInt32(r0, r1, r3, r4, d0, &impossible); |
| 2217 __ mvn(r1, Operand(r1)); | 2217 __ mvn(r1, Operand(r1)); |
| 2218 | 2218 |
| 2219 __ bind(&heapnumber_allocated); | 2219 __ bind(&heapnumber_allocated); |
| 2220 __ mov(r0, r2); // Move newly allocated heap number to r0. | 2220 __ mov(r0, r2); // Move newly allocated heap number to r0. |
| 2221 } | 2221 } |
| 2222 | 2222 |
| 2223 if (CpuFeatures::IsSupported(VFP3)) { | 2223 if (CpuFeatures::IsSupported(VFP2)) { |
| 2224 // Convert the int32 in r1 to the heap number in r0. r2 is corrupted. | 2224 // Convert the int32 in r1 to the heap number in r0. r2 is corrupted. |
| 2225 CpuFeatures::Scope scope(VFP3); | 2225 CpuFeatures::Scope scope(VFP2); |
| 2226 __ vmov(s0, r1); | 2226 __ vmov(s0, r1); |
| 2227 __ vcvt_f64_s32(d0, s0); | 2227 __ vcvt_f64_s32(d0, s0); |
| 2228 __ sub(r2, r0, Operand(kHeapObjectTag)); | 2228 __ sub(r2, r0, Operand(kHeapObjectTag)); |
| 2229 __ vstr(d0, r2, HeapNumber::kValueOffset); | 2229 __ vstr(d0, r2, HeapNumber::kValueOffset); |
| 2230 __ Ret(); | 2230 __ Ret(); |
| 2231 } else { | 2231 } else { |
| 2232 // WriteInt32ToHeapNumberStub does not trigger GC, so we do not | 2232 // WriteInt32ToHeapNumberStub does not trigger GC, so we do not |
| 2233 // have to set up a frame. | 2233 // have to set up a frame. |
| 2234 WriteInt32ToHeapNumberStub stub(r1, r0, r2); | 2234 WriteInt32ToHeapNumberStub stub(r1, r0, r2); |
| 2235 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); | 2235 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2515 | 2515 |
| 2516 switch (op_) { | 2516 switch (op_) { |
| 2517 case Token::ADD: | 2517 case Token::ADD: |
| 2518 case Token::SUB: | 2518 case Token::SUB: |
| 2519 case Token::MUL: | 2519 case Token::MUL: |
| 2520 case Token::DIV: | 2520 case Token::DIV: |
| 2521 case Token::MOD: { | 2521 case Token::MOD: { |
| 2522 // Load left and right operands into d6 and d7 or r0/r1 and r2/r3 | 2522 // Load left and right operands into d6 and d7 or r0/r1 and r2/r3 |
| 2523 // depending on whether VFP3 is available or not. | 2523 // depending on whether VFP3 is available or not. |
| 2524 FloatingPointHelper::Destination destination = | 2524 FloatingPointHelper::Destination destination = |
| 2525 CpuFeatures::IsSupported(VFP3) && | 2525 CpuFeatures::IsSupported(VFP2) && |
| 2526 op_ != Token::MOD ? | 2526 op_ != Token::MOD ? |
| 2527 FloatingPointHelper::kVFPRegisters : | 2527 FloatingPointHelper::kVFPRegisters : |
| 2528 FloatingPointHelper::kCoreRegisters; | 2528 FloatingPointHelper::kCoreRegisters; |
| 2529 | 2529 |
| 2530 // Allocate new heap number for result. | 2530 // Allocate new heap number for result. |
| 2531 Register result = r5; | 2531 Register result = r5; |
| 2532 GenerateHeapResultAllocation( | 2532 GenerateHeapResultAllocation( |
| 2533 masm, result, heap_number_map, scratch1, scratch2, gc_required); | 2533 masm, result, heap_number_map, scratch1, scratch2, gc_required); |
| 2534 | 2534 |
| 2535 // Load the operands. | 2535 // Load the operands. |
| 2536 if (smi_operands) { | 2536 if (smi_operands) { |
| 2537 FloatingPointHelper::LoadSmis(masm, destination, scratch1, scratch2); | 2537 FloatingPointHelper::LoadSmis(masm, destination, scratch1, scratch2); |
| 2538 } else { | 2538 } else { |
| 2539 FloatingPointHelper::LoadOperands(masm, | 2539 FloatingPointHelper::LoadOperands(masm, |
| 2540 destination, | 2540 destination, |
| 2541 heap_number_map, | 2541 heap_number_map, |
| 2542 scratch1, | 2542 scratch1, |
| 2543 scratch2, | 2543 scratch2, |
| 2544 not_numbers); | 2544 not_numbers); |
| 2545 } | 2545 } |
| 2546 | 2546 |
| 2547 // Calculate the result. | 2547 // Calculate the result. |
| 2548 if (destination == FloatingPointHelper::kVFPRegisters) { | 2548 if (destination == FloatingPointHelper::kVFPRegisters) { |
| 2549 // Using VFP registers: | 2549 // Using VFP registers: |
| 2550 // d6: Left value | 2550 // d6: Left value |
| 2551 // d7: Right value | 2551 // d7: Right value |
| 2552 CpuFeatures::Scope scope(VFP3); | 2552 CpuFeatures::Scope scope(VFP2); |
| 2553 switch (op_) { | 2553 switch (op_) { |
| 2554 case Token::ADD: | 2554 case Token::ADD: |
| 2555 __ vadd(d5, d6, d7); | 2555 __ vadd(d5, d6, d7); |
| 2556 break; | 2556 break; |
| 2557 case Token::SUB: | 2557 case Token::SUB: |
| 2558 __ vsub(d5, d6, d7); | 2558 __ vsub(d5, d6, d7); |
| 2559 break; | 2559 break; |
| 2560 case Token::MUL: | 2560 case Token::MUL: |
| 2561 __ vmul(d5, d6, d7); | 2561 __ vmul(d5, d6, d7); |
| 2562 break; | 2562 break; |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2631 __ mov(r2, Operand(r3, ASR, r2)); | 2631 __ mov(r2, Operand(r3, ASR, r2)); |
| 2632 break; | 2632 break; |
| 2633 case Token::SHR: | 2633 case Token::SHR: |
| 2634 // Use only the 5 least significant bits of the shift count. | 2634 // Use only the 5 least significant bits of the shift count. |
| 2635 __ GetLeastBitsFromInt32(r2, r2, 5); | 2635 __ GetLeastBitsFromInt32(r2, r2, 5); |
| 2636 __ mov(r2, Operand(r3, LSR, r2), SetCC); | 2636 __ mov(r2, Operand(r3, LSR, r2), SetCC); |
| 2637 // SHR is special because it is required to produce a positive answer. | 2637 // SHR is special because it is required to produce a positive answer. |
| 2638 // The code below for writing into heap numbers isn't capable of | 2638 // The code below for writing into heap numbers isn't capable of |
| 2639 // writing the register as an unsigned int so we go to slow case if we | 2639 // writing the register as an unsigned int so we go to slow case if we |
| 2640 // hit this case. | 2640 // hit this case. |
| 2641 if (CpuFeatures::IsSupported(VFP3)) { | 2641 if (CpuFeatures::IsSupported(VFP2)) { |
| 2642 __ b(mi, &result_not_a_smi); | 2642 __ b(mi, &result_not_a_smi); |
| 2643 } else { | 2643 } else { |
| 2644 __ b(mi, not_numbers); | 2644 __ b(mi, not_numbers); |
| 2645 } | 2645 } |
| 2646 break; | 2646 break; |
| 2647 case Token::SHL: | 2647 case Token::SHL: |
| 2648 // Use only the 5 least significant bits of the shift count. | 2648 // Use only the 5 least significant bits of the shift count. |
| 2649 __ GetLeastBitsFromInt32(r2, r2, 5); | 2649 __ GetLeastBitsFromInt32(r2, r2, 5); |
| 2650 __ mov(r2, Operand(r3, LSL, r2)); | 2650 __ mov(r2, Operand(r3, LSL, r2)); |
| 2651 break; | 2651 break; |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 2670 masm, result, heap_number_map, scratch1, scratch2, gc_required); | 2670 masm, result, heap_number_map, scratch1, scratch2, gc_required); |
| 2671 } | 2671 } |
| 2672 | 2672 |
| 2673 // r2: Answer as signed int32. | 2673 // r2: Answer as signed int32. |
| 2674 // r5: Heap number to write answer into. | 2674 // r5: Heap number to write answer into. |
| 2675 | 2675 |
| 2676 // Nothing can go wrong now, so move the heap number to r0, which is the | 2676 // Nothing can go wrong now, so move the heap number to r0, which is the |
| 2677 // result. | 2677 // result. |
| 2678 __ mov(r0, Operand(r5)); | 2678 __ mov(r0, Operand(r5)); |
| 2679 | 2679 |
| 2680 if (CpuFeatures::IsSupported(VFP3)) { | 2680 if (CpuFeatures::IsSupported(VFP2)) { |
| 2681 // Convert the int32 in r2 to the heap number in r0. r3 is corrupted. As | 2681 // Convert the int32 in r2 to the heap number in r0. r3 is corrupted. As |
| 2682 // mentioned above SHR needs to always produce a positive result. | 2682 // mentioned above SHR needs to always produce a positive result. |
| 2683 CpuFeatures::Scope scope(VFP3); | 2683 CpuFeatures::Scope scope(VFP2); |
| 2684 __ vmov(s0, r2); | 2684 __ vmov(s0, r2); |
| 2685 if (op_ == Token::SHR) { | 2685 if (op_ == Token::SHR) { |
| 2686 __ vcvt_f64_u32(d0, s0); | 2686 __ vcvt_f64_u32(d0, s0); |
| 2687 } else { | 2687 } else { |
| 2688 __ vcvt_f64_s32(d0, s0); | 2688 __ vcvt_f64_s32(d0, s0); |
| 2689 } | 2689 } |
| 2690 __ sub(r3, r0, Operand(kHeapObjectTag)); | 2690 __ sub(r3, r0, Operand(kHeapObjectTag)); |
| 2691 __ vstr(d0, r3, HeapNumber::kValueOffset); | 2691 __ vstr(d0, r3, HeapNumber::kValueOffset); |
| 2692 __ Ret(); | 2692 __ Ret(); |
| 2693 } else { | 2693 } else { |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2832 switch (op_) { | 2832 switch (op_) { |
| 2833 case Token::ADD: | 2833 case Token::ADD: |
| 2834 case Token::SUB: | 2834 case Token::SUB: |
| 2835 case Token::MUL: | 2835 case Token::MUL: |
| 2836 case Token::DIV: | 2836 case Token::DIV: |
| 2837 case Token::MOD: { | 2837 case Token::MOD: { |
| 2838 // Load both operands and check that they are 32-bit integer. | 2838 // Load both operands and check that they are 32-bit integer. |
| 2839 // Jump to type transition if they are not. The registers r0 and r1 (right | 2839 // Jump to type transition if they are not. The registers r0 and r1 (right |
| 2840 // and left) are preserved for the runtime call. | 2840 // and left) are preserved for the runtime call. |
| 2841 FloatingPointHelper::Destination destination = | 2841 FloatingPointHelper::Destination destination = |
| 2842 (CpuFeatures::IsSupported(VFP3) && op_ != Token::MOD) | 2842 (CpuFeatures::IsSupported(VFP2) && op_ != Token::MOD) |
| 2843 ? FloatingPointHelper::kVFPRegisters | 2843 ? FloatingPointHelper::kVFPRegisters |
| 2844 : FloatingPointHelper::kCoreRegisters; | 2844 : FloatingPointHelper::kCoreRegisters; |
| 2845 | 2845 |
| 2846 FloatingPointHelper::LoadNumberAsInt32Double(masm, | 2846 FloatingPointHelper::LoadNumberAsInt32Double(masm, |
| 2847 right, | 2847 right, |
| 2848 destination, | 2848 destination, |
| 2849 d7, | 2849 d7, |
| 2850 r2, | 2850 r2, |
| 2851 r3, | 2851 r3, |
| 2852 heap_number_map, | 2852 heap_number_map, |
| 2853 scratch1, | 2853 scratch1, |
| 2854 scratch2, | 2854 scratch2, |
| 2855 s0, | 2855 s0, |
| 2856 &transition); | 2856 &transition); |
| 2857 FloatingPointHelper::LoadNumberAsInt32Double(masm, | 2857 FloatingPointHelper::LoadNumberAsInt32Double(masm, |
| 2858 left, | 2858 left, |
| 2859 destination, | 2859 destination, |
| 2860 d6, | 2860 d6, |
| 2861 r4, | 2861 r4, |
| 2862 r5, | 2862 r5, |
| 2863 heap_number_map, | 2863 heap_number_map, |
| 2864 scratch1, | 2864 scratch1, |
| 2865 scratch2, | 2865 scratch2, |
| 2866 s0, | 2866 s0, |
| 2867 &transition); | 2867 &transition); |
| 2868 | 2868 |
| 2869 if (destination == FloatingPointHelper::kVFPRegisters) { | 2869 if (destination == FloatingPointHelper::kVFPRegisters) { |
| 2870 CpuFeatures::Scope scope(VFP3); | 2870 CpuFeatures::Scope scope(VFP2); |
| 2871 Label return_heap_number; | 2871 Label return_heap_number; |
| 2872 switch (op_) { | 2872 switch (op_) { |
| 2873 case Token::ADD: | 2873 case Token::ADD: |
| 2874 __ vadd(d5, d6, d7); | 2874 __ vadd(d5, d6, d7); |
| 2875 break; | 2875 break; |
| 2876 case Token::SUB: | 2876 case Token::SUB: |
| 2877 __ vsub(d5, d6, d7); | 2877 __ vsub(d5, d6, d7); |
| 2878 break; | 2878 break; |
| 2879 case Token::MUL: | 2879 case Token::MUL: |
| 2880 __ vmul(d5, d6, d7); | 2880 __ vmul(d5, d6, d7); |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3027 __ and_(r2, r2, Operand(0x1f)); | 3027 __ and_(r2, r2, Operand(0x1f)); |
| 3028 __ mov(r2, Operand(r3, ASR, r2)); | 3028 __ mov(r2, Operand(r3, ASR, r2)); |
| 3029 break; | 3029 break; |
| 3030 case Token::SHR: | 3030 case Token::SHR: |
| 3031 __ and_(r2, r2, Operand(0x1f)); | 3031 __ and_(r2, r2, Operand(0x1f)); |
| 3032 __ mov(r2, Operand(r3, LSR, r2), SetCC); | 3032 __ mov(r2, Operand(r3, LSR, r2), SetCC); |
| 3033 // SHR is special because it is required to produce a positive answer. | 3033 // SHR is special because it is required to produce a positive answer. |
| 3034 // We only get a negative result if the shift value (r2) is 0. | 3034 // We only get a negative result if the shift value (r2) is 0. |
| 3035 // This result cannot be respresented as a signed 32-bit integer, try | 3035 // This result cannot be respresented as a signed 32-bit integer, try |
| 3036 // to return a heap number if we can. | 3036 // to return a heap number if we can. |
| 3037 // The non vfp3 code does not support this special case, so jump to | 3037 // The non vfp2 code does not support this special case, so jump to |
| 3038 // runtime if we don't support it. | 3038 // runtime if we don't support it. |
| 3039 if (CpuFeatures::IsSupported(VFP3)) { | 3039 if (CpuFeatures::IsSupported(VFP2)) { |
| 3040 __ b(mi, (result_type_ <= BinaryOpIC::INT32) | 3040 __ b(mi, (result_type_ <= BinaryOpIC::INT32) |
| 3041 ? &transition | 3041 ? &transition |
| 3042 : &return_heap_number); | 3042 : &return_heap_number); |
| 3043 } else { | 3043 } else { |
| 3044 __ b(mi, (result_type_ <= BinaryOpIC::INT32) | 3044 __ b(mi, (result_type_ <= BinaryOpIC::INT32) |
| 3045 ? &transition | 3045 ? &transition |
| 3046 : &call_runtime); | 3046 : &call_runtime); |
| 3047 } | 3047 } |
| 3048 break; | 3048 break; |
| 3049 case Token::SHL: | 3049 case Token::SHL: |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 3064 | 3064 |
| 3065 __ bind(&return_heap_number); | 3065 __ bind(&return_heap_number); |
| 3066 heap_number_result = r5; | 3066 heap_number_result = r5; |
| 3067 GenerateHeapResultAllocation(masm, | 3067 GenerateHeapResultAllocation(masm, |
| 3068 heap_number_result, | 3068 heap_number_result, |
| 3069 heap_number_map, | 3069 heap_number_map, |
| 3070 scratch1, | 3070 scratch1, |
| 3071 scratch2, | 3071 scratch2, |
| 3072 &call_runtime); | 3072 &call_runtime); |
| 3073 | 3073 |
| 3074 if (CpuFeatures::IsSupported(VFP3)) { | 3074 if (CpuFeatures::IsSupported(VFP2)) { |
| 3075 CpuFeatures::Scope scope(VFP3); | 3075 CpuFeatures::Scope scope(VFP2); |
| 3076 if (op_ != Token::SHR) { | 3076 if (op_ != Token::SHR) { |
| 3077 // Convert the result to a floating point value. | 3077 // Convert the result to a floating point value. |
| 3078 __ vmov(double_scratch.low(), r2); | 3078 __ vmov(double_scratch.low(), r2); |
| 3079 __ vcvt_f64_s32(double_scratch, double_scratch.low()); | 3079 __ vcvt_f64_s32(double_scratch, double_scratch.low()); |
| 3080 } else { | 3080 } else { |
| 3081 // The result must be interpreted as an unsigned 32-bit integer. | 3081 // The result must be interpreted as an unsigned 32-bit integer. |
| 3082 __ vmov(double_scratch.low(), r2); | 3082 __ vmov(double_scratch.low(), r2); |
| 3083 __ vcvt_f64_u32(double_scratch, double_scratch.low()); | 3083 __ vcvt_f64_u32(double_scratch, double_scratch.low()); |
| 3084 } | 3084 } |
| 3085 | 3085 |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3294 | 3294 |
| 3295 Label input_not_smi; | 3295 Label input_not_smi; |
| 3296 Label loaded; | 3296 Label loaded; |
| 3297 Label calculate; | 3297 Label calculate; |
| 3298 Label invalid_cache; | 3298 Label invalid_cache; |
| 3299 const Register scratch0 = r9; | 3299 const Register scratch0 = r9; |
| 3300 const Register scratch1 = r7; | 3300 const Register scratch1 = r7; |
| 3301 const Register cache_entry = r0; | 3301 const Register cache_entry = r0; |
| 3302 const bool tagged = (argument_type_ == TAGGED); | 3302 const bool tagged = (argument_type_ == TAGGED); |
| 3303 | 3303 |
| 3304 if (CpuFeatures::IsSupported(VFP3)) { | 3304 if (CpuFeatures::IsSupported(VFP2)) { |
| 3305 CpuFeatures::Scope scope(VFP3); | 3305 CpuFeatures::Scope scope(VFP2); |
| 3306 if (tagged) { | 3306 if (tagged) { |
| 3307 // Argument is a number and is on stack and in r0. | 3307 // Argument is a number and is on stack and in r0. |
| 3308 // Load argument and check if it is a smi. | 3308 // Load argument and check if it is a smi. |
| 3309 __ JumpIfNotSmi(r0, &input_not_smi); | 3309 __ JumpIfNotSmi(r0, &input_not_smi); |
| 3310 | 3310 |
| 3311 // Input is a smi. Convert to double and load the low and high words | 3311 // Input is a smi. Convert to double and load the low and high words |
| 3312 // of the double into r2, r3. | 3312 // of the double into r2, r3. |
| 3313 __ IntegerToDoubleConversionWithVFP3(r0, r3, r2); | 3313 __ IntegerToDoubleConversionWithVFP3(r0, r3, r2); |
| 3314 __ b(&loaded); | 3314 __ b(&loaded); |
| 3315 | 3315 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3396 __ bind(&calculate); | 3396 __ bind(&calculate); |
| 3397 Counters* counters = masm->isolate()->counters(); | 3397 Counters* counters = masm->isolate()->counters(); |
| 3398 __ IncrementCounter( | 3398 __ IncrementCounter( |
| 3399 counters->transcendental_cache_miss(), 1, scratch0, scratch1); | 3399 counters->transcendental_cache_miss(), 1, scratch0, scratch1); |
| 3400 if (tagged) { | 3400 if (tagged) { |
| 3401 __ bind(&invalid_cache); | 3401 __ bind(&invalid_cache); |
| 3402 ExternalReference runtime_function = | 3402 ExternalReference runtime_function = |
| 3403 ExternalReference(RuntimeFunction(), masm->isolate()); | 3403 ExternalReference(RuntimeFunction(), masm->isolate()); |
| 3404 __ TailCallExternalReference(runtime_function, 1, 1); | 3404 __ TailCallExternalReference(runtime_function, 1, 1); |
| 3405 } else { | 3405 } else { |
| 3406 ASSERT(CpuFeatures::IsSupported(VFP3)); | 3406 ASSERT(CpuFeatures::IsSupported(VFP2)); |
| 3407 CpuFeatures::Scope scope(VFP3); | 3407 CpuFeatures::Scope scope(VFP2); |
| 3408 | 3408 |
| 3409 Label no_update; | 3409 Label no_update; |
| 3410 Label skip_cache; | 3410 Label skip_cache; |
| 3411 | 3411 |
| 3412 // Call C function to calculate the result and update the cache. | 3412 // Call C function to calculate the result and update the cache. |
| 3413 // r0: precalculated cache entry address. | 3413 // r0: precalculated cache entry address. |
| 3414 // r2 and r3: parts of the double value. | 3414 // r2 and r3: parts of the double value. |
| 3415 // Store r0, r2 and r3 on stack for later before calling C function. | 3415 // Store r0, r2 and r3 on stack for later before calling C function. |
| 3416 __ Push(r3, r2, cache_entry); | 3416 __ Push(r3, r2, cache_entry); |
| 3417 GenerateCallCFunction(masm, scratch0); | 3417 GenerateCallCFunction(masm, scratch0); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3458 __ push(scratch0); | 3458 __ push(scratch0); |
| 3459 __ CallRuntimeSaveDoubles(Runtime::kAllocateInNewSpace); | 3459 __ CallRuntimeSaveDoubles(Runtime::kAllocateInNewSpace); |
| 3460 } | 3460 } |
| 3461 __ Ret(); | 3461 __ Ret(); |
| 3462 } | 3462 } |
| 3463 } | 3463 } |
| 3464 | 3464 |
| 3465 | 3465 |
| 3466 void TranscendentalCacheStub::GenerateCallCFunction(MacroAssembler* masm, | 3466 void TranscendentalCacheStub::GenerateCallCFunction(MacroAssembler* masm, |
| 3467 Register scratch) { | 3467 Register scratch) { |
| 3468 ASSERT(CpuFeatures::IsEnabled(VFP2)); | |
| 3468 Isolate* isolate = masm->isolate(); | 3469 Isolate* isolate = masm->isolate(); |
| 3469 | 3470 |
| 3470 __ push(lr); | 3471 __ push(lr); |
| 3471 __ PrepareCallCFunction(0, 1, scratch); | 3472 __ PrepareCallCFunction(0, 1, scratch); |
| 3472 if (masm->use_eabi_hardfloat()) { | 3473 if (masm->use_eabi_hardfloat()) { |
| 3473 __ vmov(d0, d2); | 3474 __ vmov(d0, d2); |
| 3474 } else { | 3475 } else { |
| 3475 __ vmov(r0, r1, d2); | 3476 __ vmov(r0, r1, d2); |
| 3476 } | 3477 } |
| 3477 AllowExternalCallThatCantCauseGC scope(masm); | 3478 AllowExternalCallThatCantCauseGC scope(masm); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3518 __ TailCallRuntime(Runtime::kStackGuard, 0, 1); | 3519 __ TailCallRuntime(Runtime::kStackGuard, 0, 1); |
| 3519 } | 3520 } |
| 3520 | 3521 |
| 3521 | 3522 |
| 3522 void InterruptStub::Generate(MacroAssembler* masm) { | 3523 void InterruptStub::Generate(MacroAssembler* masm) { |
| 3523 __ TailCallRuntime(Runtime::kInterrupt, 0, 1); | 3524 __ TailCallRuntime(Runtime::kInterrupt, 0, 1); |
| 3524 } | 3525 } |
| 3525 | 3526 |
| 3526 | 3527 |
| 3527 void MathPowStub::Generate(MacroAssembler* masm) { | 3528 void MathPowStub::Generate(MacroAssembler* masm) { |
| 3528 CpuFeatures::Scope vfp3_scope(VFP3); | 3529 CpuFeatures::Scope vfp2_scope(VFP2); |
| 3529 const Register base = r1; | 3530 const Register base = r1; |
| 3530 const Register exponent = r2; | 3531 const Register exponent = r2; |
| 3531 const Register heapnumbermap = r5; | 3532 const Register heapnumbermap = r5; |
| 3532 const Register heapnumber = r0; | 3533 const Register heapnumber = r0; |
| 3533 const DoubleRegister double_base = d1; | 3534 const DoubleRegister double_base = d1; |
| 3534 const DoubleRegister double_exponent = d2; | 3535 const DoubleRegister double_exponent = d2; |
| 3535 const DoubleRegister double_result = d3; | 3536 const DoubleRegister double_result = d3; |
| 3536 const DoubleRegister double_scratch = d0; | 3537 const DoubleRegister double_scratch = d0; |
| 3537 const SwVfpRegister single_scratch = s0; | 3538 const SwVfpRegister single_scratch = s0; |
| 3538 const Register scratch = r9; | 3539 const Register scratch = r9; |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3617 | 3618 |
| 3618 // Calculates square root of base. Check for the special case of | 3619 // Calculates square root of base. Check for the special case of |
| 3619 // Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13). | 3620 // Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13). |
| 3620 __ vmov(double_scratch, -V8_INFINITY); | 3621 __ vmov(double_scratch, -V8_INFINITY); |
| 3621 __ VFPCompareAndSetFlags(double_base, double_scratch); | 3622 __ VFPCompareAndSetFlags(double_base, double_scratch); |
| 3622 __ vmov(double_result, kDoubleRegZero, eq); | 3623 __ vmov(double_result, kDoubleRegZero, eq); |
| 3623 __ b(eq, &done); | 3624 __ b(eq, &done); |
| 3624 | 3625 |
| 3625 // Add +0 to convert -0 to +0. | 3626 // Add +0 to convert -0 to +0. |
| 3626 __ vadd(double_scratch, double_base, kDoubleRegZero); | 3627 __ vadd(double_scratch, double_base, kDoubleRegZero); |
| 3627 __ vmov(double_result, 1); | 3628 __ vmov(double_result, 1.0); |
| 3628 __ vsqrt(double_scratch, double_scratch); | 3629 __ vsqrt(double_scratch, double_scratch); |
| 3629 __ vdiv(double_result, double_result, double_scratch); | 3630 __ vdiv(double_result, double_result, double_scratch); |
| 3630 __ jmp(&done); | 3631 __ jmp(&done); |
| 3631 } | 3632 } |
| 3632 | 3633 |
| 3633 __ push(lr); | 3634 __ push(lr); |
| 3634 { | 3635 { |
| 3635 AllowExternalCallThatCantCauseGC scope(masm); | 3636 AllowExternalCallThatCantCauseGC scope(masm); |
| 3636 __ PrepareCallCFunction(0, 2, scratch); | 3637 __ PrepareCallCFunction(0, 2, scratch); |
| 3637 __ SetCallCDoubleArguments(double_base, double_exponent); | 3638 __ SetCallCDoubleArguments(double_base, double_exponent); |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3974 // r3: argc | 3975 // r3: argc |
| 3975 // [sp+0]: argv | 3976 // [sp+0]: argv |
| 3976 | 3977 |
| 3977 Label invoke, handler_entry, exit; | 3978 Label invoke, handler_entry, exit; |
| 3978 | 3979 |
| 3979 // Called from C, so do not pop argc and args on exit (preserve sp) | 3980 // Called from C, so do not pop argc and args on exit (preserve sp) |
| 3980 // No need to save register-passed args | 3981 // No need to save register-passed args |
| 3981 // Save callee-saved registers (incl. cp and fp), sp, and lr | 3982 // Save callee-saved registers (incl. cp and fp), sp, and lr |
| 3982 __ stm(db_w, sp, kCalleeSaved | lr.bit()); | 3983 __ stm(db_w, sp, kCalleeSaved | lr.bit()); |
| 3983 | 3984 |
| 3984 if (CpuFeatures::IsSupported(VFP3)) { | 3985 if (CpuFeatures::IsSupported(VFP2)) { |
| 3985 CpuFeatures::Scope scope(VFP3); | 3986 CpuFeatures::Scope scope(VFP2); |
| 3986 // Save callee-saved vfp registers. | 3987 // Save callee-saved vfp registers. |
| 3987 __ vstm(db_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg); | 3988 __ vstm(db_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg); |
| 3988 // Set up the reserved register for 0.0. | 3989 // Set up the reserved register for 0.0. |
| 3989 __ vmov(kDoubleRegZero, 0.0); | 3990 __ Vmov(kDoubleRegZero, 0.0); |
|
Rodolph Perfetta
2012/07/25 10:59:54
The Vmov macro will use kDoubleRegZero if one wont
| |
| 3990 } | 3991 } |
| 3991 | 3992 |
| 3992 // Get address of argv, see stm above. | 3993 // Get address of argv, see stm above. |
| 3993 // r0: code entry | 3994 // r0: code entry |
| 3994 // r1: function | 3995 // r1: function |
| 3995 // r2: receiver | 3996 // r2: receiver |
| 3996 // r3: argc | 3997 // r3: argc |
| 3997 | 3998 |
| 3998 // Set up argv in r4. | 3999 // Set up argv in r4. |
| 3999 int offset_to_argv = (kNumCalleeSaved + 1) * kPointerSize; | 4000 int offset_to_argv = (kNumCalleeSaved + 1) * kPointerSize; |
| 4000 if (CpuFeatures::IsSupported(VFP3)) { | 4001 if (CpuFeatures::IsSupported(VFP2)) { |
| 4001 offset_to_argv += kNumDoubleCalleeSaved * kDoubleSize; | 4002 offset_to_argv += kNumDoubleCalleeSaved * kDoubleSize; |
| 4002 } | 4003 } |
| 4003 __ ldr(r4, MemOperand(sp, offset_to_argv)); | 4004 __ ldr(r4, MemOperand(sp, offset_to_argv)); |
| 4004 | 4005 |
| 4005 // Push a frame with special values setup to mark it as an entry frame. | 4006 // Push a frame with special values setup to mark it as an entry frame. |
| 4006 // r0: code entry | 4007 // r0: code entry |
| 4007 // r1: function | 4008 // r1: function |
| 4008 // r2: receiver | 4009 // r2: receiver |
| 4009 // r3: argc | 4010 // r3: argc |
| 4010 // r4: argv | 4011 // r4: argv |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4128 // Reset the stack to the callee saved registers. | 4129 // Reset the stack to the callee saved registers. |
| 4129 __ add(sp, sp, Operand(-EntryFrameConstants::kCallerFPOffset)); | 4130 __ add(sp, sp, Operand(-EntryFrameConstants::kCallerFPOffset)); |
| 4130 | 4131 |
| 4131 // Restore callee-saved registers and return. | 4132 // Restore callee-saved registers and return. |
| 4132 #ifdef DEBUG | 4133 #ifdef DEBUG |
| 4133 if (FLAG_debug_code) { | 4134 if (FLAG_debug_code) { |
| 4134 __ mov(lr, Operand(pc)); | 4135 __ mov(lr, Operand(pc)); |
| 4135 } | 4136 } |
| 4136 #endif | 4137 #endif |
| 4137 | 4138 |
| 4138 if (CpuFeatures::IsSupported(VFP3)) { | 4139 if (CpuFeatures::IsSupported(VFP2)) { |
| 4139 CpuFeatures::Scope scope(VFP3); | 4140 CpuFeatures::Scope scope(VFP2); |
| 4140 // Restore callee-saved vfp registers. | 4141 // Restore callee-saved vfp registers. |
| 4141 __ vldm(ia_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg); | 4142 __ vldm(ia_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg); |
| 4142 } | 4143 } |
| 4143 | 4144 |
| 4144 __ ldm(ia_w, sp, kCalleeSaved | pc.bit()); | 4145 __ ldm(ia_w, sp, kCalleeSaved | pc.bit()); |
| 4145 } | 4146 } |
| 4146 | 4147 |
| 4147 | 4148 |
| 4148 // Uses registers r0 to r4. | 4149 // Uses registers r0 to r4. |
| 4149 // Expected input (depending on whether args are in registers or on the stack): | 4150 // Expected input (depending on whether args are in registers or on the stack): |
| (...skipping 2506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6656 __ and_(r2, r1, Operand(r0)); | 6657 __ and_(r2, r1, Operand(r0)); |
| 6657 __ JumpIfSmi(r2, &generic_stub); | 6658 __ JumpIfSmi(r2, &generic_stub); |
| 6658 | 6659 |
| 6659 __ CompareObjectType(r0, r2, r2, HEAP_NUMBER_TYPE); | 6660 __ CompareObjectType(r0, r2, r2, HEAP_NUMBER_TYPE); |
| 6660 __ b(ne, &maybe_undefined1); | 6661 __ b(ne, &maybe_undefined1); |
| 6661 __ CompareObjectType(r1, r2, r2, HEAP_NUMBER_TYPE); | 6662 __ CompareObjectType(r1, r2, r2, HEAP_NUMBER_TYPE); |
| 6662 __ b(ne, &maybe_undefined2); | 6663 __ b(ne, &maybe_undefined2); |
| 6663 | 6664 |
| 6664 // Inlining the double comparison and falling back to the general compare | 6665 // Inlining the double comparison and falling back to the general compare |
| 6665 // stub if NaN is involved or VFP3 is unsupported. | 6666 // stub if NaN is involved or VFP3 is unsupported. |
| 6666 if (CpuFeatures::IsSupported(VFP3)) { | 6667 if (CpuFeatures::IsSupported(VFP2)) { |
| 6667 CpuFeatures::Scope scope(VFP3); | 6668 CpuFeatures::Scope scope(VFP2); |
| 6668 | 6669 |
| 6669 // Load left and right operand | 6670 // Load left and right operand |
| 6670 __ sub(r2, r1, Operand(kHeapObjectTag)); | 6671 __ sub(r2, r1, Operand(kHeapObjectTag)); |
| 6671 __ vldr(d0, r2, HeapNumber::kValueOffset); | 6672 __ vldr(d0, r2, HeapNumber::kValueOffset); |
| 6672 __ sub(r2, r0, Operand(kHeapObjectTag)); | 6673 __ sub(r2, r0, Operand(kHeapObjectTag)); |
| 6673 __ vldr(d1, r2, HeapNumber::kValueOffset); | 6674 __ vldr(d1, r2, HeapNumber::kValueOffset); |
| 6674 | 6675 |
| 6675 // Compare operands | 6676 // Compare operands |
| 6676 __ VFPCompareAndSetFlags(d0, d1); | 6677 __ VFPCompareAndSetFlags(d0, d1); |
| 6677 | 6678 |
| (...skipping 892 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7570 | 7571 |
| 7571 __ Pop(lr, r5, r1); | 7572 __ Pop(lr, r5, r1); |
| 7572 __ Ret(); | 7573 __ Ret(); |
| 7573 } | 7574 } |
| 7574 | 7575 |
| 7575 #undef __ | 7576 #undef __ |
| 7576 | 7577 |
| 7577 } } // namespace v8::internal | 7578 } } // namespace v8::internal |
| 7578 | 7579 |
| 7579 #endif // V8_TARGET_ARCH_ARM | 7580 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |