| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 495 Register scratch1, | 495 Register scratch1, |
| 496 Register scratch2, | 496 Register scratch2, |
| 497 Label* not_number); | 497 Label* not_number); |
| 498 }; | 498 }; |
| 499 | 499 |
| 500 | 500 |
| 501 void FloatingPointHelper::LoadSmis(MacroAssembler* masm, | 501 void FloatingPointHelper::LoadSmis(MacroAssembler* masm, |
| 502 FloatingPointHelper::Destination destination, | 502 FloatingPointHelper::Destination destination, |
| 503 Register scratch1, | 503 Register scratch1, |
| 504 Register scratch2) { | 504 Register scratch2) { |
| 505 if (CpuFeatures::IsSupported(VFP3)) { | 505 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
| 506 CpuFeatures::Scope scope(VFP3); | 506 CpuFeatures::Scope scope(VFP3); |
| 507 __ mov(scratch1, Operand(r0, ASR, kSmiTagSize)); | 507 __ mov(scratch1, Operand(r0, ASR, kSmiTagSize)); |
| 508 __ vmov(d7.high(), scratch1); | 508 __ vmov(d7.high(), scratch1); |
| 509 __ vcvt_f64_s32(d7, d7.high()); | 509 __ vcvt_f64_s32(d7, d7.high()); |
| 510 __ mov(scratch1, Operand(r1, ASR, kSmiTagSize)); | 510 __ mov(scratch1, Operand(r1, ASR, kSmiTagSize)); |
| 511 __ vmov(d6.high(), scratch1); | 511 __ vmov(d6.high(), scratch1); |
| 512 __ vcvt_f64_s32(d6, d6.high()); | 512 __ vcvt_f64_s32(d6, d6.high()); |
| 513 if (destination == kCoreRegisters) { | 513 if (destination == kCoreRegisters) { |
| 514 __ vmov(r2, r3, d7); | 514 __ vmov(r2, r3, d7); |
| 515 __ vmov(r0, r1, d6); | 515 __ vmov(r0, r1, d6); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 563 Heap::kHeapNumberMapRootIndex, | 563 Heap::kHeapNumberMapRootIndex, |
| 564 "HeapNumberMap register clobbered."); | 564 "HeapNumberMap register clobbered."); |
| 565 } | 565 } |
| 566 | 566 |
| 567 Label is_smi, done; | 567 Label is_smi, done; |
| 568 | 568 |
| 569 __ JumpIfSmi(object, &is_smi); | 569 __ JumpIfSmi(object, &is_smi); |
| 570 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number); | 570 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number); |
| 571 | 571 |
| 572 // Handle loading a double from a heap number. | 572 // Handle loading a double from a heap number. |
| 573 if (CpuFeatures::IsSupported(VFP3) && | 573 if (Isolate::Current()->cpu_features()->IsSupported(VFP3) && |
| 574 destination == kVFPRegisters) { | 574 destination == kVFPRegisters) { |
| 575 CpuFeatures::Scope scope(VFP3); | 575 CpuFeatures::Scope scope(VFP3); |
| 576 // Load the double from tagged HeapNumber to double register. | 576 // Load the double from tagged HeapNumber to double register. |
| 577 __ sub(scratch1, object, Operand(kHeapObjectTag)); | 577 __ sub(scratch1, object, Operand(kHeapObjectTag)); |
| 578 __ vldr(dst, scratch1, HeapNumber::kValueOffset); | 578 __ vldr(dst, scratch1, HeapNumber::kValueOffset); |
| 579 } else { | 579 } else { |
| 580 ASSERT(destination == kCoreRegisters); | 580 ASSERT(destination == kCoreRegisters); |
| 581 // Load the double from heap number to dst1 and dst2 in double format. | 581 // Load the double from heap number to dst1 and dst2 in double format. |
| 582 __ Ldrd(dst1, dst2, FieldMemOperand(object, HeapNumber::kValueOffset)); | 582 __ Ldrd(dst1, dst2, FieldMemOperand(object, HeapNumber::kValueOffset)); |
| 583 } | 583 } |
| 584 __ jmp(&done); | 584 __ jmp(&done); |
| 585 | 585 |
| 586 // Handle loading a double from a smi. | 586 // Handle loading a double from a smi. |
| 587 __ bind(&is_smi); | 587 __ bind(&is_smi); |
| 588 if (CpuFeatures::IsSupported(VFP3)) { | 588 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
| 589 CpuFeatures::Scope scope(VFP3); | 589 CpuFeatures::Scope scope(VFP3); |
| 590 // Convert smi to double using VFP instructions. | 590 // Convert smi to double using VFP instructions. |
| 591 __ SmiUntag(scratch1, object); | 591 __ SmiUntag(scratch1, object); |
| 592 __ vmov(dst.high(), scratch1); | 592 __ vmov(dst.high(), scratch1); |
| 593 __ vcvt_f64_s32(dst, dst.high()); | 593 __ vcvt_f64_s32(dst, dst.high()); |
| 594 if (destination == kCoreRegisters) { | 594 if (destination == kCoreRegisters) { |
| 595 // Load the converted smi to dst1 and dst2 in double format. | 595 // Load the converted smi to dst1 and dst2 in double format. |
| 596 __ vmov(dst1, dst2, dst); | 596 __ vmov(dst1, dst2, dst); |
| 597 } | 597 } |
| 598 } else { | 598 } else { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 669 ASSERT(!scratch1.is(object) && !scratch2.is(object)); | 669 ASSERT(!scratch1.is(object) && !scratch2.is(object)); |
| 670 ASSERT(!scratch1.is(scratch2)); | 670 ASSERT(!scratch1.is(scratch2)); |
| 671 ASSERT(!heap_number_map.is(object) && | 671 ASSERT(!heap_number_map.is(object) && |
| 672 !heap_number_map.is(scratch1) && | 672 !heap_number_map.is(scratch1) && |
| 673 !heap_number_map.is(scratch2)); | 673 !heap_number_map.is(scratch2)); |
| 674 | 674 |
| 675 Label done, obj_is_not_smi; | 675 Label done, obj_is_not_smi; |
| 676 | 676 |
| 677 __ JumpIfNotSmi(object, &obj_is_not_smi); | 677 __ JumpIfNotSmi(object, &obj_is_not_smi); |
| 678 __ SmiUntag(scratch1, object); | 678 __ SmiUntag(scratch1, object); |
| 679 if (CpuFeatures::IsSupported(VFP3)) { | 679 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
| 680 CpuFeatures::Scope scope(VFP3); | 680 CpuFeatures::Scope scope(VFP3); |
| 681 __ vmov(single_scratch, scratch1); | 681 __ vmov(single_scratch, scratch1); |
| 682 __ vcvt_f64_s32(double_dst, single_scratch); | 682 __ vcvt_f64_s32(double_dst, single_scratch); |
| 683 if (destination == kCoreRegisters) { | 683 if (destination == kCoreRegisters) { |
| 684 __ vmov(dst1, dst2, double_dst); | 684 __ vmov(dst1, dst2, double_dst); |
| 685 } | 685 } |
| 686 } else { | 686 } else { |
| 687 Label fewer_than_20_useful_bits; | 687 Label fewer_than_20_useful_bits; |
| 688 // Expected output: | 688 // Expected output: |
| 689 // | dst1 | dst2 | | 689 // | dst1 | dst2 | |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 737 | 737 |
| 738 __ bind(&obj_is_not_smi); | 738 __ bind(&obj_is_not_smi); |
| 739 if (FLAG_debug_code) { | 739 if (FLAG_debug_code) { |
| 740 __ AbortIfNotRootValue(heap_number_map, | 740 __ AbortIfNotRootValue(heap_number_map, |
| 741 Heap::kHeapNumberMapRootIndex, | 741 Heap::kHeapNumberMapRootIndex, |
| 742 "HeapNumberMap register clobbered."); | 742 "HeapNumberMap register clobbered."); |
| 743 } | 743 } |
| 744 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32); | 744 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32); |
| 745 | 745 |
| 746 // Load the number. | 746 // Load the number. |
| 747 if (CpuFeatures::IsSupported(VFP3)) { | 747 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
| 748 CpuFeatures::Scope scope(VFP3); | 748 CpuFeatures::Scope scope(VFP3); |
| 749 // Load the double value. | 749 // Load the double value. |
| 750 __ sub(scratch1, object, Operand(kHeapObjectTag)); | 750 __ sub(scratch1, object, Operand(kHeapObjectTag)); |
| 751 __ vldr(double_dst, scratch1, HeapNumber::kValueOffset); | 751 __ vldr(double_dst, scratch1, HeapNumber::kValueOffset); |
| 752 | 752 |
| 753 __ EmitVFPTruncate(kRoundToZero, | 753 __ EmitVFPTruncate(kRoundToZero, |
| 754 single_scratch, | 754 single_scratch, |
| 755 double_dst, | 755 double_dst, |
| 756 scratch1, | 756 scratch1, |
| 757 scratch2, | 757 scratch2, |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 811 | 811 |
| 812 if (FLAG_debug_code) { | 812 if (FLAG_debug_code) { |
| 813 __ AbortIfNotRootValue(heap_number_map, | 813 __ AbortIfNotRootValue(heap_number_map, |
| 814 Heap::kHeapNumberMapRootIndex, | 814 Heap::kHeapNumberMapRootIndex, |
| 815 "HeapNumberMap register clobbered."); | 815 "HeapNumberMap register clobbered."); |
| 816 } | 816 } |
| 817 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32); | 817 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32); |
| 818 | 818 |
| 819 // Object is a heap number. | 819 // Object is a heap number. |
| 820 // Convert the floating point value to a 32-bit integer. | 820 // Convert the floating point value to a 32-bit integer. |
| 821 if (CpuFeatures::IsSupported(VFP3)) { | 821 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
| 822 CpuFeatures::Scope scope(VFP3); | 822 CpuFeatures::Scope scope(VFP3); |
| 823 SwVfpRegister single_scratch = double_scratch.low(); | 823 SwVfpRegister single_scratch = double_scratch.low(); |
| 824 // Load the double value. | 824 // Load the double value. |
| 825 __ sub(scratch1, object, Operand(kHeapObjectTag)); | 825 __ sub(scratch1, object, Operand(kHeapObjectTag)); |
| 826 __ vldr(double_scratch, scratch1, HeapNumber::kValueOffset); | 826 __ vldr(double_scratch, scratch1, HeapNumber::kValueOffset); |
| 827 | 827 |
| 828 __ EmitVFPTruncate(kRoundToZero, | 828 __ EmitVFPTruncate(kRoundToZero, |
| 829 single_scratch, | 829 single_scratch, |
| 830 double_scratch, | 830 double_scratch, |
| 831 scratch1, | 831 scratch1, |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1146 __ mov(r0, Operand(NOT_EQUAL), LeaveCC, ne); | 1146 __ mov(r0, Operand(NOT_EQUAL), LeaveCC, ne); |
| 1147 } | 1147 } |
| 1148 __ Ret(ne); | 1148 __ Ret(ne); |
| 1149 } else { | 1149 } else { |
| 1150 // Smi compared non-strictly with a non-Smi non-heap-number. Call | 1150 // Smi compared non-strictly with a non-Smi non-heap-number. Call |
| 1151 // the runtime. | 1151 // the runtime. |
| 1152 __ b(ne, slow); | 1152 __ b(ne, slow); |
| 1153 } | 1153 } |
| 1154 | 1154 |
| 1155 // Lhs is a smi, rhs is a number. | 1155 // Lhs is a smi, rhs is a number. |
| 1156 if (CpuFeatures::IsSupported(VFP3)) { | 1156 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
| 1157 // Convert lhs to a double in d7. | 1157 // Convert lhs to a double in d7. |
| 1158 CpuFeatures::Scope scope(VFP3); | 1158 CpuFeatures::Scope scope(VFP3); |
| 1159 __ SmiToDoubleVFPRegister(lhs, d7, r7, s15); | 1159 __ SmiToDoubleVFPRegister(lhs, d7, r7, s15); |
| 1160 // Load the double from rhs, tagged HeapNumber r0, to d6. | 1160 // Load the double from rhs, tagged HeapNumber r0, to d6. |
| 1161 __ sub(r7, rhs, Operand(kHeapObjectTag)); | 1161 __ sub(r7, rhs, Operand(kHeapObjectTag)); |
| 1162 __ vldr(d6, r7, HeapNumber::kValueOffset); | 1162 __ vldr(d6, r7, HeapNumber::kValueOffset); |
| 1163 } else { | 1163 } else { |
| 1164 __ push(lr); | 1164 __ push(lr); |
| 1165 // Convert lhs to a double in r2, r3. | 1165 // Convert lhs to a double in r2, r3. |
| 1166 __ mov(r7, Operand(lhs)); | 1166 __ mov(r7, Operand(lhs)); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1186 __ mov(r0, Operand(NOT_EQUAL), LeaveCC, ne); | 1186 __ mov(r0, Operand(NOT_EQUAL), LeaveCC, ne); |
| 1187 } | 1187 } |
| 1188 __ Ret(ne); | 1188 __ Ret(ne); |
| 1189 } else { | 1189 } else { |
| 1190 // Smi compared non-strictly with a non-smi non-heap-number. Call | 1190 // Smi compared non-strictly with a non-smi non-heap-number. Call |
| 1191 // the runtime. | 1191 // the runtime. |
| 1192 __ b(ne, slow); | 1192 __ b(ne, slow); |
| 1193 } | 1193 } |
| 1194 | 1194 |
| 1195 // Rhs is a smi, lhs is a heap number. | 1195 // Rhs is a smi, lhs is a heap number. |
| 1196 if (CpuFeatures::IsSupported(VFP3)) { | 1196 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
| 1197 CpuFeatures::Scope scope(VFP3); | 1197 CpuFeatures::Scope scope(VFP3); |
| 1198 // Load the double from lhs, tagged HeapNumber r1, to d7. | 1198 // Load the double from lhs, tagged HeapNumber r1, to d7. |
| 1199 __ sub(r7, lhs, Operand(kHeapObjectTag)); | 1199 __ sub(r7, lhs, Operand(kHeapObjectTag)); |
| 1200 __ vldr(d7, r7, HeapNumber::kValueOffset); | 1200 __ vldr(d7, r7, HeapNumber::kValueOffset); |
| 1201 // Convert rhs to a double in d6 . | 1201 // Convert rhs to a double in d6 . |
| 1202 __ SmiToDoubleVFPRegister(rhs, d6, r7, s13); | 1202 __ SmiToDoubleVFPRegister(rhs, d6, r7, s13); |
| 1203 } else { | 1203 } else { |
| 1204 __ push(lr); | 1204 __ push(lr); |
| 1205 // Load lhs to a double in r2, r3. | 1205 // Load lhs to a double in r2, r3. |
| 1206 __ Ldrd(r2, r3, FieldMemOperand(lhs, HeapNumber::kValueOffset)); | 1206 __ Ldrd(r2, r3, FieldMemOperand(lhs, HeapNumber::kValueOffset)); |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1366 (lhs.is(r1) && rhs.is(r0))); | 1366 (lhs.is(r1) && rhs.is(r0))); |
| 1367 | 1367 |
| 1368 __ CompareObjectType(rhs, r3, r2, HEAP_NUMBER_TYPE); | 1368 __ CompareObjectType(rhs, r3, r2, HEAP_NUMBER_TYPE); |
| 1369 __ b(ne, not_heap_numbers); | 1369 __ b(ne, not_heap_numbers); |
| 1370 __ ldr(r2, FieldMemOperand(lhs, HeapObject::kMapOffset)); | 1370 __ ldr(r2, FieldMemOperand(lhs, HeapObject::kMapOffset)); |
| 1371 __ cmp(r2, r3); | 1371 __ cmp(r2, r3); |
| 1372 __ b(ne, slow); // First was a heap number, second wasn't. Go slow case. | 1372 __ b(ne, slow); // First was a heap number, second wasn't. Go slow case. |
| 1373 | 1373 |
| 1374 // Both are heap numbers. Load them up then jump to the code we have | 1374 // Both are heap numbers. Load them up then jump to the code we have |
| 1375 // for that. | 1375 // for that. |
| 1376 if (CpuFeatures::IsSupported(VFP3)) { | 1376 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
| 1377 CpuFeatures::Scope scope(VFP3); | 1377 CpuFeatures::Scope scope(VFP3); |
| 1378 __ sub(r7, rhs, Operand(kHeapObjectTag)); | 1378 __ sub(r7, rhs, Operand(kHeapObjectTag)); |
| 1379 __ vldr(d6, r7, HeapNumber::kValueOffset); | 1379 __ vldr(d6, r7, HeapNumber::kValueOffset); |
| 1380 __ sub(r7, lhs, Operand(kHeapObjectTag)); | 1380 __ sub(r7, lhs, Operand(kHeapObjectTag)); |
| 1381 __ vldr(d7, r7, HeapNumber::kValueOffset); | 1381 __ vldr(d7, r7, HeapNumber::kValueOffset); |
| 1382 } else { | 1382 } else { |
| 1383 __ Ldrd(r2, r3, FieldMemOperand(lhs, HeapNumber::kValueOffset)); | 1383 __ Ldrd(r2, r3, FieldMemOperand(lhs, HeapNumber::kValueOffset)); |
| 1384 __ Ldrd(r0, r1, FieldMemOperand(rhs, HeapNumber::kValueOffset)); | 1384 __ Ldrd(r0, r1, FieldMemOperand(rhs, HeapNumber::kValueOffset)); |
| 1385 } | 1385 } |
| 1386 __ jmp(both_loaded_as_doubles); | 1386 __ jmp(both_loaded_as_doubles); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1456 | 1456 |
| 1457 // Calculate the entry in the number string cache. The hash value in the | 1457 // Calculate the entry in the number string cache. The hash value in the |
| 1458 // number string cache for smis is just the smi value, and the hash for | 1458 // number string cache for smis is just the smi value, and the hash for |
| 1459 // doubles is the xor of the upper and lower words. See | 1459 // doubles is the xor of the upper and lower words. See |
| 1460 // Heap::GetNumberStringCache. | 1460 // Heap::GetNumberStringCache. |
| 1461 Isolate* isolate = masm->isolate(); | 1461 Isolate* isolate = masm->isolate(); |
| 1462 Label is_smi; | 1462 Label is_smi; |
| 1463 Label load_result_from_cache; | 1463 Label load_result_from_cache; |
| 1464 if (!object_is_smi) { | 1464 if (!object_is_smi) { |
| 1465 __ JumpIfSmi(object, &is_smi); | 1465 __ JumpIfSmi(object, &is_smi); |
| 1466 if (CpuFeatures::IsSupported(VFP3)) { | 1466 if (isolate->cpu_features()->IsSupported(VFP3)) { |
| 1467 CpuFeatures::Scope scope(VFP3); | 1467 CpuFeatures::Scope scope(VFP3); |
| 1468 __ CheckMap(object, | 1468 __ CheckMap(object, |
| 1469 scratch1, | 1469 scratch1, |
| 1470 Heap::kHeapNumberMapRootIndex, | 1470 Heap::kHeapNumberMapRootIndex, |
| 1471 not_found, | 1471 not_found, |
| 1472 true); | 1472 true); |
| 1473 | 1473 |
| 1474 STATIC_ASSERT(8 == kDoubleSize); | 1474 STATIC_ASSERT(8 == kDoubleSize); |
| 1475 __ add(scratch1, | 1475 __ add(scratch1, |
| 1476 object, | 1476 object, |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1590 // In cases 3 and 4 we have found out we were dealing with a number-number | 1590 // In cases 3 and 4 we have found out we were dealing with a number-number |
| 1591 // comparison. If VFP3 is supported the double values of the numbers have | 1591 // comparison. If VFP3 is supported the double values of the numbers have |
| 1592 // been loaded into d7 and d6. Otherwise, the double values have been loaded | 1592 // been loaded into d7 and d6. Otherwise, the double values have been loaded |
| 1593 // into r0, r1, r2, and r3. | 1593 // into r0, r1, r2, and r3. |
| 1594 EmitSmiNonsmiComparison(masm, lhs_, rhs_, &lhs_not_nan, &slow, strict_); | 1594 EmitSmiNonsmiComparison(masm, lhs_, rhs_, &lhs_not_nan, &slow, strict_); |
| 1595 | 1595 |
| 1596 __ bind(&both_loaded_as_doubles); | 1596 __ bind(&both_loaded_as_doubles); |
| 1597 // The arguments have been converted to doubles and stored in d6 and d7, if | 1597 // The arguments have been converted to doubles and stored in d6 and d7, if |
| 1598 // VFP3 is supported, or in r0, r1, r2, and r3. | 1598 // VFP3 is supported, or in r0, r1, r2, and r3. |
| 1599 Isolate* isolate = masm->isolate(); | 1599 Isolate* isolate = masm->isolate(); |
| 1600 if (CpuFeatures::IsSupported(VFP3)) { | 1600 if (isolate->cpu_features()->IsSupported(VFP3)) { |
| 1601 __ bind(&lhs_not_nan); | 1601 __ bind(&lhs_not_nan); |
| 1602 CpuFeatures::Scope scope(VFP3); | 1602 CpuFeatures::Scope scope(VFP3); |
| 1603 Label no_nan; | 1603 Label no_nan; |
| 1604 // ARMv7 VFP3 instructions to implement double precision comparison. | 1604 // ARMv7 VFP3 instructions to implement double precision comparison. |
| 1605 __ VFPCompareAndSetFlags(d7, d6); | 1605 __ VFPCompareAndSetFlags(d7, d6); |
| 1606 Label nan; | 1606 Label nan; |
| 1607 __ b(vs, &nan); | 1607 __ b(vs, &nan); |
| 1608 __ mov(r0, Operand(EQUAL), LeaveCC, eq); | 1608 __ mov(r0, Operand(EQUAL), LeaveCC, eq); |
| 1609 __ mov(r0, Operand(LESS), LeaveCC, lt); | 1609 __ mov(r0, Operand(LESS), LeaveCC, lt); |
| 1610 __ mov(r0, Operand(GREATER), LeaveCC, gt); | 1610 __ mov(r0, Operand(GREATER), LeaveCC, gt); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1700 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) | 1700 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) |
| 1701 // tagged as a small integer. | 1701 // tagged as a small integer. |
| 1702 __ InvokeBuiltin(native, JUMP_JS); | 1702 __ InvokeBuiltin(native, JUMP_JS); |
| 1703 } | 1703 } |
| 1704 | 1704 |
| 1705 | 1705 |
| 1706 // This stub does not handle the inlined cases (Smis, Booleans, undefined). | 1706 // This stub does not handle the inlined cases (Smis, Booleans, undefined). |
| 1707 // The stub returns zero for false, and a non-zero value for true. | 1707 // The stub returns zero for false, and a non-zero value for true. |
| 1708 void ToBooleanStub::Generate(MacroAssembler* masm) { | 1708 void ToBooleanStub::Generate(MacroAssembler* masm) { |
| 1709 // This stub uses VFP3 instructions. | 1709 // This stub uses VFP3 instructions. |
| 1710 ASSERT(CpuFeatures::IsEnabled(VFP3)); | 1710 ASSERT(Isolate::Current()->cpu_features()->IsEnabled(VFP3)); |
| 1711 | 1711 |
| 1712 Label false_result; | 1712 Label false_result; |
| 1713 Label not_heap_number; | 1713 Label not_heap_number; |
| 1714 Register scratch = r9.is(tos_) ? r7 : r9; | 1714 Register scratch = r9.is(tos_) ? r7 : r9; |
| 1715 | 1715 |
| 1716 __ LoadRoot(ip, Heap::kNullValueRootIndex); | 1716 __ LoadRoot(ip, Heap::kNullValueRootIndex); |
| 1717 __ cmp(tos_, ip); | 1717 __ cmp(tos_, ip); |
| 1718 __ b(eq, &false_result); | 1718 __ b(eq, &false_result); |
| 1719 | 1719 |
| 1720 // HeapNumber => false iff +0, -0, or NaN. | 1720 // HeapNumber => false iff +0, -0, or NaN. |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1787 // with the double precision floating point operands in r0 and r1 (for the | 1787 // with the double precision floating point operands in r0 and r1 (for the |
| 1788 // value in r1) and r2 and r3 (for the value in r0). | 1788 // value in r1) and r2 and r3 (for the value in r0). |
| 1789 void GenericBinaryOpStub::HandleBinaryOpSlowCases( | 1789 void GenericBinaryOpStub::HandleBinaryOpSlowCases( |
| 1790 MacroAssembler* masm, | 1790 MacroAssembler* masm, |
| 1791 Label* not_smi, | 1791 Label* not_smi, |
| 1792 Register lhs, | 1792 Register lhs, |
| 1793 Register rhs, | 1793 Register rhs, |
| 1794 const Builtins::JavaScript& builtin) { | 1794 const Builtins::JavaScript& builtin) { |
| 1795 Label slow, slow_reverse, do_the_call; | 1795 Label slow, slow_reverse, do_the_call; |
| 1796 bool use_fp_registers = | 1796 bool use_fp_registers = |
| 1797 CpuFeatures::IsSupported(VFP3) && | 1797 Isolate::Current()->cpu_features()->IsSupported(VFP3) && |
| 1798 Token::MOD != op_; | 1798 Token::MOD != op_; |
| 1799 | 1799 |
| 1800 ASSERT((lhs.is(r0) && rhs.is(r1)) || (lhs.is(r1) && rhs.is(r0))); | 1800 ASSERT((lhs.is(r0) && rhs.is(r1)) || (lhs.is(r1) && rhs.is(r0))); |
| 1801 Register heap_number_map = r6; | 1801 Register heap_number_map = r6; |
| 1802 | 1802 |
| 1803 if (ShouldGenerateSmiCode()) { | 1803 if (ShouldGenerateSmiCode()) { |
| 1804 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); | 1804 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
| 1805 | 1805 |
| 1806 // Smi-smi case (overflow). | 1806 // Smi-smi case (overflow). |
| 1807 // Since both are Smis there is no heap number to overwrite, so allocate. | 1807 // Since both are Smis there is no heap number to overwrite, so allocate. |
| 1808 // The new heap number is in r5. r3 and r7 are scratch. | 1808 // The new heap number is in r5. r3 and r7 are scratch. |
| 1809 __ AllocateHeapNumber( | 1809 __ AllocateHeapNumber( |
| 1810 r5, r3, r7, heap_number_map, lhs.is(r0) ? &slow_reverse : &slow); | 1810 r5, r3, r7, heap_number_map, lhs.is(r0) ? &slow_reverse : &slow); |
| 1811 | 1811 |
| 1812 // If we have floating point hardware, inline ADD, SUB, MUL, and DIV, | 1812 // If we have floating point hardware, inline ADD, SUB, MUL, and DIV, |
| 1813 // using registers d7 and d6 for the double values. | 1813 // using registers d7 and d6 for the double values. |
| 1814 if (CpuFeatures::IsSupported(VFP3)) { | 1814 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
| 1815 CpuFeatures::Scope scope(VFP3); | 1815 CpuFeatures::Scope scope(VFP3); |
| 1816 __ mov(r7, Operand(rhs, ASR, kSmiTagSize)); | 1816 __ mov(r7, Operand(rhs, ASR, kSmiTagSize)); |
| 1817 __ vmov(s15, r7); | 1817 __ vmov(s15, r7); |
| 1818 __ vcvt_f64_s32(d7, s15); | 1818 __ vcvt_f64_s32(d7, s15); |
| 1819 __ mov(r7, Operand(lhs, ASR, kSmiTagSize)); | 1819 __ mov(r7, Operand(lhs, ASR, kSmiTagSize)); |
| 1820 __ vmov(s13, r7); | 1820 __ vmov(s13, r7); |
| 1821 __ vcvt_f64_s32(d6, s13); | 1821 __ vcvt_f64_s32(d6, s13); |
| 1822 if (!use_fp_registers) { | 1822 if (!use_fp_registers) { |
| 1823 __ vmov(r2, r3, d7); | 1823 __ vmov(r2, r3, d7); |
| 1824 __ vmov(r0, r1, d6); | 1824 __ vmov(r0, r1, d6); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1900 // Calling convention says that second double is in r2 and r3. | 1900 // Calling convention says that second double is in r2 and r3. |
| 1901 __ Ldrd(r2, r3, FieldMemOperand(r0, HeapNumber::kValueOffset)); | 1901 __ Ldrd(r2, r3, FieldMemOperand(r0, HeapNumber::kValueOffset)); |
| 1902 } | 1902 } |
| 1903 __ jmp(&finished_loading_r0); | 1903 __ jmp(&finished_loading_r0); |
| 1904 __ bind(&r0_is_smi); | 1904 __ bind(&r0_is_smi); |
| 1905 if (mode_ == OVERWRITE_RIGHT) { | 1905 if (mode_ == OVERWRITE_RIGHT) { |
| 1906 // We can't overwrite a Smi so get address of new heap number into r5. | 1906 // We can't overwrite a Smi so get address of new heap number into r5. |
| 1907 __ AllocateHeapNumber(r5, r4, r7, heap_number_map, &slow); | 1907 __ AllocateHeapNumber(r5, r4, r7, heap_number_map, &slow); |
| 1908 } | 1908 } |
| 1909 | 1909 |
| 1910 if (CpuFeatures::IsSupported(VFP3)) { | 1910 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
| 1911 CpuFeatures::Scope scope(VFP3); | 1911 CpuFeatures::Scope scope(VFP3); |
| 1912 // Convert smi in r0 to double in d7. | 1912 // Convert smi in r0 to double in d7. |
| 1913 __ mov(r7, Operand(r0, ASR, kSmiTagSize)); | 1913 __ mov(r7, Operand(r0, ASR, kSmiTagSize)); |
| 1914 __ vmov(s15, r7); | 1914 __ vmov(s15, r7); |
| 1915 __ vcvt_f64_s32(d7, s15); | 1915 __ vcvt_f64_s32(d7, s15); |
| 1916 if (!use_fp_registers) { | 1916 if (!use_fp_registers) { |
| 1917 __ vmov(r2, r3, d7); | 1917 __ vmov(r2, r3, d7); |
| 1918 } | 1918 } |
| 1919 } else { | 1919 } else { |
| 1920 // Write Smi from r0 to r3 and r2 in double format. | 1920 // Write Smi from r0 to r3 and r2 in double format. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1957 // Calling convention says that first double is in r0 and r1. | 1957 // Calling convention says that first double is in r0 and r1. |
| 1958 __ Ldrd(r0, r1, FieldMemOperand(r1, HeapNumber::kValueOffset)); | 1958 __ Ldrd(r0, r1, FieldMemOperand(r1, HeapNumber::kValueOffset)); |
| 1959 } | 1959 } |
| 1960 __ jmp(&finished_loading_r1); | 1960 __ jmp(&finished_loading_r1); |
| 1961 __ bind(&r1_is_smi); | 1961 __ bind(&r1_is_smi); |
| 1962 if (mode_ == OVERWRITE_LEFT) { | 1962 if (mode_ == OVERWRITE_LEFT) { |
| 1963 // We can't overwrite a Smi so get address of new heap number into r5. | 1963 // We can't overwrite a Smi so get address of new heap number into r5. |
| 1964 __ AllocateHeapNumber(r5, r4, r7, heap_number_map, &slow); | 1964 __ AllocateHeapNumber(r5, r4, r7, heap_number_map, &slow); |
| 1965 } | 1965 } |
| 1966 | 1966 |
| 1967 if (CpuFeatures::IsSupported(VFP3)) { | 1967 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
| 1968 CpuFeatures::Scope scope(VFP3); | 1968 CpuFeatures::Scope scope(VFP3); |
| 1969 // Convert smi in r1 to double in d6. | 1969 // Convert smi in r1 to double in d6. |
| 1970 __ mov(r7, Operand(r1, ASR, kSmiTagSize)); | 1970 __ mov(r7, Operand(r1, ASR, kSmiTagSize)); |
| 1971 __ vmov(s13, r7); | 1971 __ vmov(s13, r7); |
| 1972 __ vcvt_f64_s32(d6, s13); | 1972 __ vcvt_f64_s32(d6, s13); |
| 1973 if (!use_fp_registers) { | 1973 if (!use_fp_registers) { |
| 1974 __ vmov(r0, r1, d6); | 1974 __ vmov(r0, r1, d6); |
| 1975 } | 1975 } |
| 1976 } else { | 1976 } else { |
| 1977 // Write Smi from r1 to r1 and r0 in double format. | 1977 // Write Smi from r1 to r1 and r0 in double format. |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2170 __ mov(r2, Operand(r3, ASR, r2)); | 2170 __ mov(r2, Operand(r3, ASR, r2)); |
| 2171 break; | 2171 break; |
| 2172 case Token::SHR: | 2172 case Token::SHR: |
| 2173 // Use only the 5 least significant bits of the shift count. | 2173 // Use only the 5 least significant bits of the shift count. |
| 2174 __ and_(r2, r2, Operand(0x1f)); | 2174 __ and_(r2, r2, Operand(0x1f)); |
| 2175 __ mov(r2, Operand(r3, LSR, r2), SetCC); | 2175 __ mov(r2, Operand(r3, LSR, r2), SetCC); |
| 2176 // SHR is special because it is required to produce a positive answer. | 2176 // SHR is special because it is required to produce a positive answer. |
| 2177 // The code below for writing into heap numbers isn't capable of writing | 2177 // The code below for writing into heap numbers isn't capable of writing |
| 2178 // the register as an unsigned int so we go to slow case if we hit this | 2178 // the register as an unsigned int so we go to slow case if we hit this |
| 2179 // case. | 2179 // case. |
| 2180 if (CpuFeatures::IsSupported(VFP3)) { | 2180 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
| 2181 __ b(mi, &result_not_a_smi); | 2181 __ b(mi, &result_not_a_smi); |
| 2182 } else { | 2182 } else { |
| 2183 __ b(mi, &slow); | 2183 __ b(mi, &slow); |
| 2184 } | 2184 } |
| 2185 break; | 2185 break; |
| 2186 case Token::SHL: | 2186 case Token::SHL: |
| 2187 // Use only the 5 least significant bits of the shift count. | 2187 // Use only the 5 least significant bits of the shift count. |
| 2188 __ and_(r2, r2, Operand(0x1f)); | 2188 __ and_(r2, r2, Operand(0x1f)); |
| 2189 __ mov(r2, Operand(r3, LSL, r2)); | 2189 __ mov(r2, Operand(r3, LSL, r2)); |
| 2190 break; | 2190 break; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 2218 default: break; | 2218 default: break; |
| 2219 } | 2219 } |
| 2220 __ bind(&got_a_heap_number); | 2220 __ bind(&got_a_heap_number); |
| 2221 // r2: Answer as signed int32. | 2221 // r2: Answer as signed int32. |
| 2222 // r5: Heap number to write answer into. | 2222 // r5: Heap number to write answer into. |
| 2223 | 2223 |
| 2224 // Nothing can go wrong now, so move the heap number to r0, which is the | 2224 // Nothing can go wrong now, so move the heap number to r0, which is the |
| 2225 // result. | 2225 // result. |
| 2226 __ mov(r0, Operand(r5)); | 2226 __ mov(r0, Operand(r5)); |
| 2227 | 2227 |
| 2228 if (CpuFeatures::IsSupported(VFP3)) { | 2228 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
| 2229 // Convert the int32 in r2 to the heap number in r0. r3 is corrupted. | 2229 // Convert the int32 in r2 to the heap number in r0. r3 is corrupted. |
| 2230 CpuFeatures::Scope scope(VFP3); | 2230 CpuFeatures::Scope scope(VFP3); |
| 2231 __ vmov(s0, r2); | 2231 __ vmov(s0, r2); |
| 2232 if (op_ == Token::SHR) { | 2232 if (op_ == Token::SHR) { |
| 2233 __ vcvt_f64_u32(d0, s0); | 2233 __ vcvt_f64_u32(d0, s0); |
| 2234 } else { | 2234 } else { |
| 2235 __ vcvt_f64_s32(d0, s0); | 2235 __ vcvt_f64_s32(d0, s0); |
| 2236 } | 2236 } |
| 2237 __ sub(r3, r0, Operand(kHeapObjectTag)); | 2237 __ sub(r3, r0, Operand(kHeapObjectTag)); |
| 2238 __ vstr(d0, r3, HeapNumber::kValueOffset); | 2238 __ vstr(d0, r3, HeapNumber::kValueOffset); |
| (...skipping 831 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3070 | 3070 |
| 3071 switch (op_) { | 3071 switch (op_) { |
| 3072 case Token::ADD: | 3072 case Token::ADD: |
| 3073 case Token::SUB: | 3073 case Token::SUB: |
| 3074 case Token::MUL: | 3074 case Token::MUL: |
| 3075 case Token::DIV: | 3075 case Token::DIV: |
| 3076 case Token::MOD: { | 3076 case Token::MOD: { |
| 3077 // Load left and right operands into d6 and d7 or r0/r1 and r2/r3 | 3077 // Load left and right operands into d6 and d7 or r0/r1 and r2/r3 |
| 3078 // depending on whether VFP3 is available or not. | 3078 // depending on whether VFP3 is available or not. |
| 3079 FloatingPointHelper::Destination destination = | 3079 FloatingPointHelper::Destination destination = |
| 3080 CpuFeatures::IsSupported(VFP3) && | 3080 Isolate::Current()->cpu_features()->IsSupported(VFP3) && |
| 3081 op_ != Token::MOD ? | 3081 op_ != Token::MOD ? |
| 3082 FloatingPointHelper::kVFPRegisters : | 3082 FloatingPointHelper::kVFPRegisters : |
| 3083 FloatingPointHelper::kCoreRegisters; | 3083 FloatingPointHelper::kCoreRegisters; |
| 3084 | 3084 |
| 3085 // Allocate new heap number for result. | 3085 // Allocate new heap number for result. |
| 3086 Register result = r5; | 3086 Register result = r5; |
| 3087 GenerateHeapResultAllocation( | 3087 GenerateHeapResultAllocation( |
| 3088 masm, result, heap_number_map, scratch1, scratch2, gc_required); | 3088 masm, result, heap_number_map, scratch1, scratch2, gc_required); |
| 3089 | 3089 |
| 3090 // Load the operands. | 3090 // Load the operands. |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3183 __ mov(r2, Operand(r3, ASR, r2)); | 3183 __ mov(r2, Operand(r3, ASR, r2)); |
| 3184 break; | 3184 break; |
| 3185 case Token::SHR: | 3185 case Token::SHR: |
| 3186 // Use only the 5 least significant bits of the shift count. | 3186 // Use only the 5 least significant bits of the shift count. |
| 3187 __ GetLeastBitsFromInt32(r2, r2, 5); | 3187 __ GetLeastBitsFromInt32(r2, r2, 5); |
| 3188 __ mov(r2, Operand(r3, LSR, r2), SetCC); | 3188 __ mov(r2, Operand(r3, LSR, r2), SetCC); |
| 3189 // SHR is special because it is required to produce a positive answer. | 3189 // SHR is special because it is required to produce a positive answer. |
| 3190 // The code below for writing into heap numbers isn't capable of | 3190 // The code below for writing into heap numbers isn't capable of |
| 3191 // writing the register as an unsigned int so we go to slow case if we | 3191 // writing the register as an unsigned int so we go to slow case if we |
| 3192 // hit this case. | 3192 // hit this case. |
| 3193 if (CpuFeatures::IsSupported(VFP3)) { | 3193 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
| 3194 __ b(mi, &result_not_a_smi); | 3194 __ b(mi, &result_not_a_smi); |
| 3195 } else { | 3195 } else { |
| 3196 __ b(mi, not_numbers); | 3196 __ b(mi, not_numbers); |
| 3197 } | 3197 } |
| 3198 break; | 3198 break; |
| 3199 case Token::SHL: | 3199 case Token::SHL: |
| 3200 // Use only the 5 least significant bits of the shift count. | 3200 // Use only the 5 least significant bits of the shift count. |
| 3201 __ GetLeastBitsFromInt32(r2, r2, 5); | 3201 __ GetLeastBitsFromInt32(r2, r2, 5); |
| 3202 __ mov(r2, Operand(r3, LSL, r2)); | 3202 __ mov(r2, Operand(r3, LSL, r2)); |
| 3203 break; | 3203 break; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 3222 masm, result, heap_number_map, scratch1, scratch2, gc_required); | 3222 masm, result, heap_number_map, scratch1, scratch2, gc_required); |
| 3223 } | 3223 } |
| 3224 | 3224 |
| 3225 // r2: Answer as signed int32. | 3225 // r2: Answer as signed int32. |
| 3226 // r5: Heap number to write answer into. | 3226 // r5: Heap number to write answer into. |
| 3227 | 3227 |
| 3228 // Nothing can go wrong now, so move the heap number to r0, which is the | 3228 // Nothing can go wrong now, so move the heap number to r0, which is the |
| 3229 // result. | 3229 // result. |
| 3230 __ mov(r0, Operand(r5)); | 3230 __ mov(r0, Operand(r5)); |
| 3231 | 3231 |
| 3232 if (CpuFeatures::IsSupported(VFP3)) { | 3232 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
| 3233 // Convert the int32 in r2 to the heap number in r0. r3 is corrupted. As | 3233 // Convert the int32 in r2 to the heap number in r0. r3 is corrupted. As |
| 3234 // mentioned above SHR needs to always produce a positive result. | 3234 // mentioned above SHR needs to always produce a positive result. |
| 3235 CpuFeatures::Scope scope(VFP3); | 3235 CpuFeatures::Scope scope(VFP3); |
| 3236 __ vmov(s0, r2); | 3236 __ vmov(s0, r2); |
| 3237 if (op_ == Token::SHR) { | 3237 if (op_ == Token::SHR) { |
| 3238 __ vcvt_f64_u32(d0, s0); | 3238 __ vcvt_f64_u32(d0, s0); |
| 3239 } else { | 3239 } else { |
| 3240 __ vcvt_f64_s32(d0, s0); | 3240 __ vcvt_f64_s32(d0, s0); |
| 3241 } | 3241 } |
| 3242 __ sub(r3, r0, Operand(kHeapObjectTag)); | 3242 __ sub(r3, r0, Operand(kHeapObjectTag)); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3351 switch (op_) { | 3351 switch (op_) { |
| 3352 case Token::ADD: | 3352 case Token::ADD: |
| 3353 case Token::SUB: | 3353 case Token::SUB: |
| 3354 case Token::MUL: | 3354 case Token::MUL: |
| 3355 case Token::DIV: | 3355 case Token::DIV: |
| 3356 case Token::MOD: { | 3356 case Token::MOD: { |
| 3357 // Load both operands and check that they are 32-bit integer. | 3357 // Load both operands and check that they are 32-bit integer. |
| 3358 // Jump to type transition if they are not. The registers r0 and r1 (right | 3358 // Jump to type transition if they are not. The registers r0 and r1 (right |
| 3359 // and left) are preserved for the runtime call. | 3359 // and left) are preserved for the runtime call. |
| 3360 FloatingPointHelper::Destination destination = | 3360 FloatingPointHelper::Destination destination = |
| 3361 CpuFeatures::IsSupported(VFP3) && | 3361 Isolate::Current()->cpu_features()->IsSupported(VFP3) && |
| 3362 op_ != Token::MOD ? | 3362 op_ != Token::MOD ? |
| 3363 FloatingPointHelper::kVFPRegisters : | 3363 FloatingPointHelper::kVFPRegisters : |
| 3364 FloatingPointHelper::kCoreRegisters; | 3364 FloatingPointHelper::kCoreRegisters; |
| 3365 | 3365 |
| 3366 FloatingPointHelper::LoadNumberAsInt32Double(masm, | 3366 FloatingPointHelper::LoadNumberAsInt32Double(masm, |
| 3367 right, | 3367 right, |
| 3368 destination, | 3368 destination, |
| 3369 d7, | 3369 d7, |
| 3370 r2, | 3370 r2, |
| 3371 r3, | 3371 r3, |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3538 break; | 3538 break; |
| 3539 case Token::SHR: | 3539 case Token::SHR: |
| 3540 __ and_(r2, r2, Operand(0x1f)); | 3540 __ and_(r2, r2, Operand(0x1f)); |
| 3541 __ mov(r2, Operand(r3, LSR, r2), SetCC); | 3541 __ mov(r2, Operand(r3, LSR, r2), SetCC); |
| 3542 // SHR is special because it is required to produce a positive answer. | 3542 // SHR is special because it is required to produce a positive answer. |
| 3543 // We only get a negative result if the shift value (r2) is 0. | 3543 // We only get a negative result if the shift value (r2) is 0. |
| 3544 // This result cannot be respresented as a signed 32-bit integer, try | 3544 // This result cannot be respresented as a signed 32-bit integer, try |
| 3545 // to return a heap number if we can. | 3545 // to return a heap number if we can. |
| 3546 // The non vfp3 code does not support this special case, so jump to | 3546 // The non vfp3 code does not support this special case, so jump to |
| 3547 // runtime if we don't support it. | 3547 // runtime if we don't support it. |
| 3548 if (CpuFeatures::IsSupported(VFP3)) { | 3548 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
| 3549 __ b(mi, | 3549 __ b(mi, |
| 3550 (result_type_ <= TRBinaryOpIC::INT32) ? &transition | 3550 (result_type_ <= TRBinaryOpIC::INT32) ? &transition |
| 3551 : &return_heap_number); | 3551 : &return_heap_number); |
| 3552 } else { | 3552 } else { |
| 3553 __ b(mi, (result_type_ <= TRBinaryOpIC::INT32) ? &transition | 3553 __ b(mi, (result_type_ <= TRBinaryOpIC::INT32) ? &transition |
| 3554 : &call_runtime); | 3554 : &call_runtime); |
| 3555 } | 3555 } |
| 3556 break; | 3556 break; |
| 3557 case Token::SHL: | 3557 case Token::SHL: |
| 3558 __ and_(r2, r2, Operand(0x1f)); | 3558 __ and_(r2, r2, Operand(0x1f)); |
| 3559 __ mov(r2, Operand(r3, LSL, r2)); | 3559 __ mov(r2, Operand(r3, LSL, r2)); |
| 3560 break; | 3560 break; |
| 3561 default: | 3561 default: |
| 3562 UNREACHABLE(); | 3562 UNREACHABLE(); |
| 3563 } | 3563 } |
| 3564 | 3564 |
| 3565 // Check if the result fits in a smi. | 3565 // Check if the result fits in a smi. |
| 3566 __ add(scratch1, r2, Operand(0x40000000), SetCC); | 3566 __ add(scratch1, r2, Operand(0x40000000), SetCC); |
| 3567 // If not try to return a heap number. (We know the result is an int32.) | 3567 // If not try to return a heap number. (We know the result is an int32.) |
| 3568 __ b(mi, &return_heap_number); | 3568 __ b(mi, &return_heap_number); |
| 3569 // Tag the result and return. | 3569 // Tag the result and return. |
| 3570 __ SmiTag(r0, r2); | 3570 __ SmiTag(r0, r2); |
| 3571 __ Ret(); | 3571 __ Ret(); |
| 3572 | 3572 |
| 3573 __ bind(&return_heap_number); | 3573 __ bind(&return_heap_number); |
| 3574 if (CpuFeatures::IsSupported(VFP3)) { | 3574 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
| 3575 CpuFeatures::Scope scope(VFP3); | 3575 CpuFeatures::Scope scope(VFP3); |
| 3576 heap_number_result = r5; | 3576 heap_number_result = r5; |
| 3577 GenerateHeapResultAllocation(masm, | 3577 GenerateHeapResultAllocation(masm, |
| 3578 heap_number_result, | 3578 heap_number_result, |
| 3579 heap_number_map, | 3579 heap_number_map, |
| 3580 scratch1, | 3580 scratch1, |
| 3581 scratch2, | 3581 scratch2, |
| 3582 &call_runtime); | 3582 &call_runtime); |
| 3583 | 3583 |
| 3584 if (op_ != Token::SHR) { | 3584 if (op_ != Token::SHR) { |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3799 | 3799 |
| 3800 Label input_not_smi; | 3800 Label input_not_smi; |
| 3801 Label loaded; | 3801 Label loaded; |
| 3802 Label calculate; | 3802 Label calculate; |
| 3803 Label invalid_cache; | 3803 Label invalid_cache; |
| 3804 const Register scratch0 = r9; | 3804 const Register scratch0 = r9; |
| 3805 const Register scratch1 = r7; | 3805 const Register scratch1 = r7; |
| 3806 const Register cache_entry = r0; | 3806 const Register cache_entry = r0; |
| 3807 const bool tagged = (argument_type_ == TAGGED); | 3807 const bool tagged = (argument_type_ == TAGGED); |
| 3808 | 3808 |
| 3809 if (CpuFeatures::IsSupported(VFP3)) { | 3809 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
| 3810 CpuFeatures::Scope scope(VFP3); | 3810 CpuFeatures::Scope scope(VFP3); |
| 3811 if (tagged) { | 3811 if (tagged) { |
| 3812 // Argument is a number and is on stack and in r0. | 3812 // Argument is a number and is on stack and in r0. |
| 3813 // Load argument and check if it is a smi. | 3813 // Load argument and check if it is a smi. |
| 3814 __ JumpIfNotSmi(r0, &input_not_smi); | 3814 __ JumpIfNotSmi(r0, &input_not_smi); |
| 3815 | 3815 |
| 3816 // Input is a smi. Convert to double and load the low and high words | 3816 // Input is a smi. Convert to double and load the low and high words |
| 3817 // of the double into r2, r3. | 3817 // of the double into r2, r3. |
| 3818 __ IntegerToDoubleConversionWithVFP3(r0, r3, r2); | 3818 __ IntegerToDoubleConversionWithVFP3(r0, r3, r2); |
| 3819 __ b(&loaded); | 3819 __ b(&loaded); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3887 // Cache hit. Load result, cleanup and return. | 3887 // Cache hit. Load result, cleanup and return. |
| 3888 if (tagged) { | 3888 if (tagged) { |
| 3889 // Pop input value from stack and load result into r0. | 3889 // Pop input value from stack and load result into r0. |
| 3890 __ pop(); | 3890 __ pop(); |
| 3891 __ mov(r0, Operand(r6)); | 3891 __ mov(r0, Operand(r6)); |
| 3892 } else { | 3892 } else { |
| 3893 // Load result into d2. | 3893 // Load result into d2. |
| 3894 __ vldr(d2, FieldMemOperand(r6, HeapNumber::kValueOffset)); | 3894 __ vldr(d2, FieldMemOperand(r6, HeapNumber::kValueOffset)); |
| 3895 } | 3895 } |
| 3896 __ Ret(); | 3896 __ Ret(); |
| 3897 } // if (CpuFeatures::IsSupported(VFP3)) | 3897 } // if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) |
| 3898 | 3898 |
| 3899 __ bind(&calculate); | 3899 __ bind(&calculate); |
| 3900 if (tagged) { | 3900 if (tagged) { |
| 3901 __ bind(&invalid_cache); | 3901 __ bind(&invalid_cache); |
| 3902 ExternalReference runtime_function = | 3902 ExternalReference runtime_function = |
| 3903 ExternalReference(RuntimeFunction(), masm->isolate()); | 3903 ExternalReference(RuntimeFunction(), masm->isolate()); |
| 3904 __ TailCallExternalReference(runtime_function, 1, 1); | 3904 __ TailCallExternalReference(runtime_function, 1, 1); |
| 3905 } else { | 3905 } else { |
| 3906 if (!CpuFeatures::IsSupported(VFP3)) UNREACHABLE(); | 3906 if (!Isolate::Current()->cpu_features()->IsSupported(VFP3)) UNREACHABLE(); |
| 3907 CpuFeatures::Scope scope(VFP3); | 3907 CpuFeatures::Scope scope(VFP3); |
| 3908 | 3908 |
| 3909 Label no_update; | 3909 Label no_update; |
| 3910 Label skip_cache; | 3910 Label skip_cache; |
| 3911 const Register heap_number_map = r5; | 3911 const Register heap_number_map = r5; |
| 3912 | 3912 |
| 3913 // Call C function to calculate the result and update the cache. | 3913 // Call C function to calculate the result and update the cache. |
| 3914 // Register r0 holds precalculated cache entry address; preserve | 3914 // Register r0 holds precalculated cache entry address; preserve |
| 3915 // it on the stack and pop it into register cache_entry after the | 3915 // it on the stack and pop it into register cache_entry after the |
| 3916 // call. | 3916 // call. |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4095 | 4095 |
| 4096 __ bind(&try_float); | 4096 __ bind(&try_float); |
| 4097 if (!overwrite_ == UNARY_OVERWRITE) { | 4097 if (!overwrite_ == UNARY_OVERWRITE) { |
| 4098 // Allocate a fresh heap number, but don't overwrite r0 until | 4098 // Allocate a fresh heap number, but don't overwrite r0 until |
| 4099 // we're sure we can do it without going through the slow case | 4099 // we're sure we can do it without going through the slow case |
| 4100 // that needs the value in r0. | 4100 // that needs the value in r0. |
| 4101 __ AllocateHeapNumber(r2, r3, r4, r6, &slow); | 4101 __ AllocateHeapNumber(r2, r3, r4, r6, &slow); |
| 4102 __ mov(r0, Operand(r2)); | 4102 __ mov(r0, Operand(r2)); |
| 4103 } | 4103 } |
| 4104 | 4104 |
| 4105 if (CpuFeatures::IsSupported(VFP3)) { | 4105 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
| 4106 // Convert the int32 in r1 to the heap number in r0. r2 is corrupted. | 4106 // Convert the int32 in r1 to the heap number in r0. r2 is corrupted. |
| 4107 CpuFeatures::Scope scope(VFP3); | 4107 CpuFeatures::Scope scope(VFP3); |
| 4108 __ vmov(s0, r1); | 4108 __ vmov(s0, r1); |
| 4109 __ vcvt_f64_s32(d0, s0); | 4109 __ vcvt_f64_s32(d0, s0); |
| 4110 __ sub(r2, r0, Operand(kHeapObjectTag)); | 4110 __ sub(r2, r0, Operand(kHeapObjectTag)); |
| 4111 __ vstr(d0, r2, HeapNumber::kValueOffset); | 4111 __ vstr(d0, r2, HeapNumber::kValueOffset); |
| 4112 } else { | 4112 } else { |
| 4113 // WriteInt32ToHeapNumberStub does not trigger GC, so we do not | 4113 // WriteInt32ToHeapNumberStub does not trigger GC, so we do not |
| 4114 // have to set up a frame. | 4114 // have to set up a frame. |
| 4115 WriteInt32ToHeapNumberStub stub(r1, r0, r2); | 4115 WriteInt32ToHeapNumberStub stub(r1, r0, r2); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 4136 break; | 4136 break; |
| 4137 default: | 4137 default: |
| 4138 UNREACHABLE(); | 4138 UNREACHABLE(); |
| 4139 } | 4139 } |
| 4140 } | 4140 } |
| 4141 | 4141 |
| 4142 | 4142 |
| 4143 void MathPowStub::Generate(MacroAssembler* masm) { | 4143 void MathPowStub::Generate(MacroAssembler* masm) { |
| 4144 Label call_runtime; | 4144 Label call_runtime; |
| 4145 | 4145 |
| 4146 if (CpuFeatures::IsSupported(VFP3)) { | 4146 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
| 4147 CpuFeatures::Scope scope(VFP3); | 4147 CpuFeatures::Scope scope(VFP3); |
| 4148 | 4148 |
| 4149 Label base_not_smi; | 4149 Label base_not_smi; |
| 4150 Label exponent_not_smi; | 4150 Label exponent_not_smi; |
| 4151 Label convert_exponent; | 4151 Label convert_exponent; |
| 4152 | 4152 |
| 4153 const Register base = r0; | 4153 const Register base = r0; |
| 4154 const Register exponent = r1; | 4154 const Register exponent = r1; |
| 4155 const Register heapnumbermap = r5; | 4155 const Register heapnumbermap = r5; |
| 4156 const Register heapnumber = r6; | 4156 const Register heapnumber = r6; |
| (...skipping 2648 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6805 __ tst(r2, Operand(kSmiTagMask)); | 6805 __ tst(r2, Operand(kSmiTagMask)); |
| 6806 __ b(eq, &generic_stub); | 6806 __ b(eq, &generic_stub); |
| 6807 | 6807 |
| 6808 __ CompareObjectType(r0, r2, r2, HEAP_NUMBER_TYPE); | 6808 __ CompareObjectType(r0, r2, r2, HEAP_NUMBER_TYPE); |
| 6809 __ b(ne, &miss); | 6809 __ b(ne, &miss); |
| 6810 __ CompareObjectType(r1, r2, r2, HEAP_NUMBER_TYPE); | 6810 __ CompareObjectType(r1, r2, r2, HEAP_NUMBER_TYPE); |
| 6811 __ b(ne, &miss); | 6811 __ b(ne, &miss); |
| 6812 | 6812 |
| 6813 // Inlining the double comparison and falling back to the general compare | 6813 // Inlining the double comparison and falling back to the general compare |
| 6814 // stub if NaN is involved or VFP3 is unsupported. | 6814 // stub if NaN is involved or VFP3 is unsupported. |
| 6815 if (CpuFeatures::IsSupported(VFP3)) { | 6815 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
| 6816 CpuFeatures::Scope scope(VFP3); | 6816 CpuFeatures::Scope scope(VFP3); |
| 6817 | 6817 |
| 6818 // Load left and right operand | 6818 // Load left and right operand |
| 6819 __ sub(r2, r1, Operand(kHeapObjectTag)); | 6819 __ sub(r2, r1, Operand(kHeapObjectTag)); |
| 6820 __ vldr(d0, r2, HeapNumber::kValueOffset); | 6820 __ vldr(d0, r2, HeapNumber::kValueOffset); |
| 6821 __ sub(r2, r0, Operand(kHeapObjectTag)); | 6821 __ sub(r2, r0, Operand(kHeapObjectTag)); |
| 6822 __ vldr(d1, r2, HeapNumber::kValueOffset); | 6822 __ vldr(d1, r2, HeapNumber::kValueOffset); |
| 6823 | 6823 |
| 6824 // Compare operands | 6824 // Compare operands |
| 6825 __ VFPCompareAndSetFlags(d0, d1); | 6825 __ VFPCompareAndSetFlags(d0, d1); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6913 __ str(pc, MemOperand(sp, 0)); | 6913 __ str(pc, MemOperand(sp, 0)); |
| 6914 __ Jump(target); // Call the C++ function. | 6914 __ Jump(target); // Call the C++ function. |
| 6915 } | 6915 } |
| 6916 | 6916 |
| 6917 | 6917 |
| 6918 #undef __ | 6918 #undef __ |
| 6919 | 6919 |
| 6920 } } // namespace v8::internal | 6920 } } // namespace v8::internal |
| 6921 | 6921 |
| 6922 #endif // V8_TARGET_ARCH_ARM | 6922 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |