OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/arm/codegen-arm.h" | 5 #include "src/arm/codegen-arm.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM | 7 #if V8_TARGET_ARCH_ARM |
8 | 8 |
9 #include "src/arm/simulator-arm.h" | 9 #include "src/arm/simulator-arm.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
11 #include "src/macro-assembler.h" | 11 #include "src/macro-assembler.h" |
12 | 12 |
13 namespace v8 { | 13 namespace v8 { |
14 namespace internal { | 14 namespace internal { |
15 | 15 |
16 | 16 |
17 #define __ masm. | 17 #define __ masm. |
18 | 18 |
| 19 |
| 20 #if defined(USE_SIMULATOR) |
| 21 byte* fast_exp_arm_machine_code = nullptr; |
| 22 double fast_exp_simulator(double x, Isolate* isolate) { |
| 23 return Simulator::current(isolate) |
| 24 ->CallFPReturnsDouble(fast_exp_arm_machine_code, x, 0); |
| 25 } |
| 26 #endif |
| 27 |
| 28 |
| 29 UnaryMathFunctionWithIsolate CreateExpFunction(Isolate* isolate) { |
| 30 size_t actual_size; |
| 31 byte* buffer = |
| 32 static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true)); |
| 33 if (buffer == nullptr) return nullptr; |
| 34 ExternalReference::InitializeMathExpData(); |
| 35 |
| 36 MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size), |
| 37 CodeObjectRequired::kNo); |
| 38 |
| 39 { |
| 40 DwVfpRegister input = d0; |
| 41 DwVfpRegister result = d1; |
| 42 DwVfpRegister double_scratch1 = d2; |
| 43 DwVfpRegister double_scratch2 = d3; |
| 44 Register temp1 = r4; |
| 45 Register temp2 = r5; |
| 46 Register temp3 = r6; |
| 47 |
| 48 if (masm.use_eabi_hardfloat()) { |
| 49 // Input value is in d0 anyway, nothing to do. |
| 50 } else { |
| 51 __ vmov(input, r0, r1); |
| 52 } |
| 53 __ Push(temp3, temp2, temp1); |
| 54 MathExpGenerator::EmitMathExp( |
| 55 &masm, input, result, double_scratch1, double_scratch2, |
| 56 temp1, temp2, temp3); |
| 57 __ Pop(temp3, temp2, temp1); |
| 58 if (masm.use_eabi_hardfloat()) { |
| 59 __ vmov(d0, result); |
| 60 } else { |
| 61 __ vmov(r0, r1, result); |
| 62 } |
| 63 __ Ret(); |
| 64 } |
| 65 |
| 66 CodeDesc desc; |
| 67 masm.GetCode(&desc); |
| 68 DCHECK(!RelocInfo::RequiresRelocation(desc)); |
| 69 |
| 70 Assembler::FlushICache(isolate, buffer, actual_size); |
| 71 base::OS::ProtectCode(buffer, actual_size); |
| 72 |
| 73 #if !defined(USE_SIMULATOR) |
| 74 return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer); |
| 75 #else |
| 76 fast_exp_arm_machine_code = buffer; |
| 77 return &fast_exp_simulator; |
| 78 #endif |
| 79 } |
| 80 |
19 #if defined(V8_HOST_ARCH_ARM) | 81 #if defined(V8_HOST_ARCH_ARM) |
20 MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate, | 82 MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate, |
21 MemCopyUint8Function stub) { | 83 MemCopyUint8Function stub) { |
22 #if defined(USE_SIMULATOR) | 84 #if defined(USE_SIMULATOR) |
23 return stub; | 85 return stub; |
24 #else | 86 #else |
25 if (!CpuFeatures::IsSupported(UNALIGNED_ACCESSES)) return stub; | 87 if (!CpuFeatures::IsSupported(UNALIGNED_ACCESSES)) return stub; |
26 size_t actual_size; | 88 size_t actual_size; |
27 byte* buffer = | 89 byte* buffer = |
28 static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true)); | 90 static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true)); |
(...skipping 696 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
725 __ b(ne, &one_byte); | 787 __ b(ne, &one_byte); |
726 // Two-byte string. | 788 // Two-byte string. |
727 __ ldrh(result, MemOperand(string, index, LSL, 1)); | 789 __ ldrh(result, MemOperand(string, index, LSL, 1)); |
728 __ jmp(&done); | 790 __ jmp(&done); |
729 __ bind(&one_byte); | 791 __ bind(&one_byte); |
730 // One-byte string. | 792 // One-byte string. |
731 __ ldrb(result, MemOperand(string, index)); | 793 __ ldrb(result, MemOperand(string, index)); |
732 __ bind(&done); | 794 __ bind(&done); |
733 } | 795 } |
734 | 796 |
| 797 |
| 798 static MemOperand ExpConstant(int index, Register base) { |
| 799 return MemOperand(base, index * kDoubleSize); |
| 800 } |
| 801 |
| 802 |
| 803 void MathExpGenerator::EmitMathExp(MacroAssembler* masm, |
| 804 DwVfpRegister input, |
| 805 DwVfpRegister result, |
| 806 DwVfpRegister double_scratch1, |
| 807 DwVfpRegister double_scratch2, |
| 808 Register temp1, |
| 809 Register temp2, |
| 810 Register temp3) { |
| 811 DCHECK(!input.is(result)); |
| 812 DCHECK(!input.is(double_scratch1)); |
| 813 DCHECK(!input.is(double_scratch2)); |
| 814 DCHECK(!result.is(double_scratch1)); |
| 815 DCHECK(!result.is(double_scratch2)); |
| 816 DCHECK(!double_scratch1.is(double_scratch2)); |
| 817 DCHECK(!temp1.is(temp2)); |
| 818 DCHECK(!temp1.is(temp3)); |
| 819 DCHECK(!temp2.is(temp3)); |
| 820 DCHECK(ExternalReference::math_exp_constants(0).address() != NULL); |
| 821 DCHECK(!masm->serializer_enabled()); // External references not serializable. |
| 822 |
| 823 Label zero, infinity, done; |
| 824 |
| 825 __ mov(temp3, Operand(ExternalReference::math_exp_constants(0))); |
| 826 |
| 827 __ vldr(double_scratch1, ExpConstant(0, temp3)); |
| 828 __ VFPCompareAndSetFlags(double_scratch1, input); |
| 829 __ b(ge, &zero); |
| 830 |
| 831 __ vldr(double_scratch2, ExpConstant(1, temp3)); |
| 832 __ VFPCompareAndSetFlags(input, double_scratch2); |
| 833 __ b(ge, &infinity); |
| 834 |
| 835 __ vldr(double_scratch1, ExpConstant(3, temp3)); |
| 836 __ vldr(result, ExpConstant(4, temp3)); |
| 837 __ vmul(double_scratch1, double_scratch1, input); |
| 838 __ vadd(double_scratch1, double_scratch1, result); |
| 839 __ VmovLow(temp2, double_scratch1); |
| 840 __ vsub(double_scratch1, double_scratch1, result); |
| 841 __ vldr(result, ExpConstant(6, temp3)); |
| 842 __ vldr(double_scratch2, ExpConstant(5, temp3)); |
| 843 __ vmul(double_scratch1, double_scratch1, double_scratch2); |
| 844 __ vsub(double_scratch1, double_scratch1, input); |
| 845 __ vsub(result, result, double_scratch1); |
| 846 __ vmul(double_scratch2, double_scratch1, double_scratch1); |
| 847 __ vmul(result, result, double_scratch2); |
| 848 __ vldr(double_scratch2, ExpConstant(7, temp3)); |
| 849 __ vmul(result, result, double_scratch2); |
| 850 __ vsub(result, result, double_scratch1); |
| 851 // Mov 1 in double_scratch2 as math_exp_constants_array[8] == 1. |
| 852 DCHECK(*reinterpret_cast<double*> |
| 853 (ExternalReference::math_exp_constants(8).address()) == 1); |
| 854 __ vmov(double_scratch2, 1); |
| 855 __ vadd(result, result, double_scratch2); |
| 856 __ mov(temp1, Operand(temp2, LSR, 11)); |
| 857 __ Ubfx(temp2, temp2, 0, 11); |
| 858 __ add(temp1, temp1, Operand(0x3ff)); |
| 859 |
| 860 // Must not call ExpConstant() after overwriting temp3! |
| 861 __ mov(temp3, Operand(ExternalReference::math_exp_log_table())); |
| 862 __ add(temp3, temp3, Operand(temp2, LSL, 3)); |
| 863 __ ldm(ia, temp3, temp2.bit() | temp3.bit()); |
| 864 // The first word is loaded is the lower number register. |
| 865 if (temp2.code() < temp3.code()) { |
| 866 __ orr(temp1, temp3, Operand(temp1, LSL, 20)); |
| 867 __ vmov(double_scratch1, temp2, temp1); |
| 868 } else { |
| 869 __ orr(temp1, temp2, Operand(temp1, LSL, 20)); |
| 870 __ vmov(double_scratch1, temp3, temp1); |
| 871 } |
| 872 __ vmul(result, result, double_scratch1); |
| 873 __ b(&done); |
| 874 |
| 875 __ bind(&zero); |
| 876 __ vmov(result, kDoubleRegZero); |
| 877 __ b(&done); |
| 878 |
| 879 __ bind(&infinity); |
| 880 __ vldr(result, ExpConstant(2, temp3)); |
| 881 |
| 882 __ bind(&done); |
| 883 } |
| 884 |
735 #undef __ | 885 #undef __ |
736 | 886 |
737 #ifdef DEBUG | 887 #ifdef DEBUG |
738 // add(r0, pc, Operand(-8)) | 888 // add(r0, pc, Operand(-8)) |
739 static const uint32_t kCodeAgePatchFirstInstruction = 0xe24f0008; | 889 static const uint32_t kCodeAgePatchFirstInstruction = 0xe24f0008; |
740 #endif | 890 #endif |
741 | 891 |
742 CodeAgingHelper::CodeAgingHelper(Isolate* isolate) { | 892 CodeAgingHelper::CodeAgingHelper(Isolate* isolate) { |
743 USE(isolate); | 893 USE(isolate); |
744 DCHECK(young_sequence_.length() == kNoCodeAgeSequenceLength); | 894 DCHECK(young_sequence_.length() == kNoCodeAgeSequenceLength); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
800 patcher.masm()->ldr(pc, MemOperand(pc, -4)); | 950 patcher.masm()->ldr(pc, MemOperand(pc, -4)); |
801 patcher.masm()->emit_code_stub_address(stub); | 951 patcher.masm()->emit_code_stub_address(stub); |
802 } | 952 } |
803 } | 953 } |
804 | 954 |
805 | 955 |
806 } // namespace internal | 956 } // namespace internal |
807 } // namespace v8 | 957 } // namespace v8 |
808 | 958 |
809 #endif // V8_TARGET_ARCH_ARM | 959 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |