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 | |
81 #if defined(V8_HOST_ARCH_ARM) | 19 #if defined(V8_HOST_ARCH_ARM) |
82 MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate, | 20 MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate, |
83 MemCopyUint8Function stub) { | 21 MemCopyUint8Function stub) { |
84 #if defined(USE_SIMULATOR) | 22 #if defined(USE_SIMULATOR) |
85 return stub; | 23 return stub; |
86 #else | 24 #else |
87 if (!CpuFeatures::IsSupported(UNALIGNED_ACCESSES)) return stub; | 25 if (!CpuFeatures::IsSupported(UNALIGNED_ACCESSES)) return stub; |
88 size_t actual_size; | 26 size_t actual_size; |
89 byte* buffer = | 27 byte* buffer = |
90 static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true)); | 28 static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true)); |
(...skipping 696 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
787 __ b(ne, &one_byte); | 725 __ b(ne, &one_byte); |
788 // Two-byte string. | 726 // Two-byte string. |
789 __ ldrh(result, MemOperand(string, index, LSL, 1)); | 727 __ ldrh(result, MemOperand(string, index, LSL, 1)); |
790 __ jmp(&done); | 728 __ jmp(&done); |
791 __ bind(&one_byte); | 729 __ bind(&one_byte); |
792 // One-byte string. | 730 // One-byte string. |
793 __ ldrb(result, MemOperand(string, index)); | 731 __ ldrb(result, MemOperand(string, index)); |
794 __ bind(&done); | 732 __ bind(&done); |
795 } | 733 } |
796 | 734 |
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 | |
885 #undef __ | 735 #undef __ |
886 | 736 |
887 #ifdef DEBUG | 737 #ifdef DEBUG |
888 // add(r0, pc, Operand(-8)) | 738 // add(r0, pc, Operand(-8)) |
889 static const uint32_t kCodeAgePatchFirstInstruction = 0xe24f0008; | 739 static const uint32_t kCodeAgePatchFirstInstruction = 0xe24f0008; |
890 #endif | 740 #endif |
891 | 741 |
892 CodeAgingHelper::CodeAgingHelper(Isolate* isolate) { | 742 CodeAgingHelper::CodeAgingHelper(Isolate* isolate) { |
893 USE(isolate); | 743 USE(isolate); |
894 DCHECK(young_sequence_.length() == kNoCodeAgeSequenceLength); | 744 DCHECK(young_sequence_.length() == kNoCodeAgeSequenceLength); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
950 patcher.masm()->ldr(pc, MemOperand(pc, -4)); | 800 patcher.masm()->ldr(pc, MemOperand(pc, -4)); |
951 patcher.masm()->emit_code_stub_address(stub); | 801 patcher.masm()->emit_code_stub_address(stub); |
952 } | 802 } |
953 } | 803 } |
954 | 804 |
955 | 805 |
956 } // namespace internal | 806 } // namespace internal |
957 } // namespace v8 | 807 } // namespace v8 |
958 | 808 |
959 #endif // V8_TARGET_ARCH_ARM | 809 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |