| 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 |