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/mips/codegen-mips.h" | 5 #include "src/mips/codegen-mips.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_MIPS | 7 #if V8_TARGET_ARCH_MIPS |
8 | 8 |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/macro-assembler.h" | 10 #include "src/macro-assembler.h" |
11 #include "src/mips/simulator-mips.h" | 11 #include "src/mips/simulator-mips.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_mips_machine_code = nullptr; |
| 22 double fast_exp_simulator(double x, Isolate* isolate) { |
| 23 return Simulator::current(isolate)->CallFP(fast_exp_mips_machine_code, x, 0); |
| 24 } |
| 25 #endif |
| 26 |
| 27 |
| 28 UnaryMathFunctionWithIsolate CreateExpFunction(Isolate* isolate) { |
| 29 size_t actual_size; |
| 30 byte* buffer = |
| 31 static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true)); |
| 32 if (buffer == nullptr) return nullptr; |
| 33 ExternalReference::InitializeMathExpData(); |
| 34 |
| 35 MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size), |
| 36 CodeObjectRequired::kNo); |
| 37 |
| 38 { |
| 39 DoubleRegister input = f12; |
| 40 DoubleRegister result = f0; |
| 41 DoubleRegister double_scratch1 = f4; |
| 42 DoubleRegister double_scratch2 = f6; |
| 43 Register temp1 = t0; |
| 44 Register temp2 = t1; |
| 45 Register temp3 = t2; |
| 46 |
| 47 __ MovFromFloatParameter(input); |
| 48 __ Push(temp3, temp2, temp1); |
| 49 MathExpGenerator::EmitMathExp( |
| 50 &masm, input, result, double_scratch1, double_scratch2, |
| 51 temp1, temp2, temp3); |
| 52 __ Pop(temp3, temp2, temp1); |
| 53 __ MovToFloatResult(result); |
| 54 __ Ret(); |
| 55 } |
| 56 |
| 57 CodeDesc desc; |
| 58 masm.GetCode(&desc); |
| 59 DCHECK(!RelocInfo::RequiresRelocation(desc)); |
| 60 |
| 61 Assembler::FlushICache(isolate, buffer, actual_size); |
| 62 base::OS::ProtectCode(buffer, actual_size); |
| 63 |
| 64 #if !defined(USE_SIMULATOR) |
| 65 return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer); |
| 66 #else |
| 67 fast_exp_mips_machine_code = buffer; |
| 68 return &fast_exp_simulator; |
| 69 #endif |
| 70 } |
| 71 |
| 72 |
19 #if defined(V8_HOST_ARCH_MIPS) | 73 #if defined(V8_HOST_ARCH_MIPS) |
20 MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate, | 74 MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate, |
21 MemCopyUint8Function stub) { | 75 MemCopyUint8Function stub) { |
22 #if defined(USE_SIMULATOR) || defined(_MIPS_ARCH_MIPS32R6) || \ | 76 #if defined(USE_SIMULATOR) || defined(_MIPS_ARCH_MIPS32R6) || \ |
23 defined(_MIPS_ARCH_MIPS32RX) | 77 defined(_MIPS_ARCH_MIPS32RX) |
24 return stub; | 78 return stub; |
25 #else | 79 #else |
26 size_t actual_size; | 80 size_t actual_size; |
27 byte* buffer = | 81 byte* buffer = |
28 static_cast<byte*>(base::OS::Allocate(3 * KB, &actual_size, true)); | 82 static_cast<byte*>(base::OS::Allocate(3 * KB, &actual_size, true)); |
(...skipping 1002 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1031 __ Lsa(at, string, index, 1); | 1085 __ Lsa(at, string, index, 1); |
1032 __ lhu(result, MemOperand(at)); | 1086 __ lhu(result, MemOperand(at)); |
1033 __ jmp(&done); | 1087 __ jmp(&done); |
1034 __ bind(&one_byte); | 1088 __ bind(&one_byte); |
1035 // One_byte string. | 1089 // One_byte string. |
1036 __ Addu(at, string, index); | 1090 __ Addu(at, string, index); |
1037 __ lbu(result, MemOperand(at)); | 1091 __ lbu(result, MemOperand(at)); |
1038 __ bind(&done); | 1092 __ bind(&done); |
1039 } | 1093 } |
1040 | 1094 |
| 1095 |
| 1096 static MemOperand ExpConstant(int index, Register base) { |
| 1097 return MemOperand(base, index * kDoubleSize); |
| 1098 } |
| 1099 |
| 1100 |
| 1101 void MathExpGenerator::EmitMathExp(MacroAssembler* masm, |
| 1102 DoubleRegister input, |
| 1103 DoubleRegister result, |
| 1104 DoubleRegister double_scratch1, |
| 1105 DoubleRegister double_scratch2, |
| 1106 Register temp1, |
| 1107 Register temp2, |
| 1108 Register temp3) { |
| 1109 DCHECK(!input.is(result)); |
| 1110 DCHECK(!input.is(double_scratch1)); |
| 1111 DCHECK(!input.is(double_scratch2)); |
| 1112 DCHECK(!result.is(double_scratch1)); |
| 1113 DCHECK(!result.is(double_scratch2)); |
| 1114 DCHECK(!double_scratch1.is(double_scratch2)); |
| 1115 DCHECK(!temp1.is(temp2)); |
| 1116 DCHECK(!temp1.is(temp3)); |
| 1117 DCHECK(!temp2.is(temp3)); |
| 1118 DCHECK(ExternalReference::math_exp_constants(0).address() != NULL); |
| 1119 DCHECK(!masm->serializer_enabled()); // External references not serializable. |
| 1120 |
| 1121 Label zero, infinity, done; |
| 1122 |
| 1123 __ li(temp3, Operand(ExternalReference::math_exp_constants(0))); |
| 1124 |
| 1125 __ ldc1(double_scratch1, ExpConstant(0, temp3)); |
| 1126 __ BranchF(&zero, NULL, ge, double_scratch1, input); |
| 1127 |
| 1128 __ ldc1(double_scratch2, ExpConstant(1, temp3)); |
| 1129 __ BranchF(&infinity, NULL, ge, input, double_scratch2); |
| 1130 |
| 1131 __ ldc1(double_scratch1, ExpConstant(3, temp3)); |
| 1132 __ ldc1(result, ExpConstant(4, temp3)); |
| 1133 __ mul_d(double_scratch1, double_scratch1, input); |
| 1134 __ add_d(double_scratch1, double_scratch1, result); |
| 1135 __ FmoveLow(temp2, double_scratch1); |
| 1136 __ sub_d(double_scratch1, double_scratch1, result); |
| 1137 __ ldc1(result, ExpConstant(6, temp3)); |
| 1138 __ ldc1(double_scratch2, ExpConstant(5, temp3)); |
| 1139 __ mul_d(double_scratch1, double_scratch1, double_scratch2); |
| 1140 __ sub_d(double_scratch1, double_scratch1, input); |
| 1141 __ sub_d(result, result, double_scratch1); |
| 1142 __ mul_d(double_scratch2, double_scratch1, double_scratch1); |
| 1143 __ mul_d(result, result, double_scratch2); |
| 1144 __ ldc1(double_scratch2, ExpConstant(7, temp3)); |
| 1145 __ mul_d(result, result, double_scratch2); |
| 1146 __ sub_d(result, result, double_scratch1); |
| 1147 // Mov 1 in double_scratch2 as math_exp_constants_array[8] == 1. |
| 1148 DCHECK(*reinterpret_cast<double*> |
| 1149 (ExternalReference::math_exp_constants(8).address()) == 1); |
| 1150 __ Move(double_scratch2, 1.); |
| 1151 __ add_d(result, result, double_scratch2); |
| 1152 __ srl(temp1, temp2, 11); |
| 1153 __ Ext(temp2, temp2, 0, 11); |
| 1154 __ Addu(temp1, temp1, Operand(0x3ff)); |
| 1155 |
| 1156 // Must not call ExpConstant() after overwriting temp3! |
| 1157 __ li(temp3, Operand(ExternalReference::math_exp_log_table())); |
| 1158 __ Lsa(temp3, temp3, temp2, 3); |
| 1159 __ lw(temp2, MemOperand(temp3, Register::kMantissaOffset)); |
| 1160 __ lw(temp3, MemOperand(temp3, Register::kExponentOffset)); |
| 1161 // The first word is loaded is the lower number register. |
| 1162 if (temp2.code() < temp3.code()) { |
| 1163 __ sll(at, temp1, 20); |
| 1164 __ Or(temp1, temp3, at); |
| 1165 __ Move(double_scratch1, temp2, temp1); |
| 1166 } else { |
| 1167 __ sll(at, temp1, 20); |
| 1168 __ Or(temp1, temp2, at); |
| 1169 __ Move(double_scratch1, temp3, temp1); |
| 1170 } |
| 1171 __ mul_d(result, result, double_scratch1); |
| 1172 __ BranchShort(&done); |
| 1173 |
| 1174 __ bind(&zero); |
| 1175 __ Move(result, kDoubleRegZero); |
| 1176 __ BranchShort(&done); |
| 1177 |
| 1178 __ bind(&infinity); |
| 1179 __ ldc1(result, ExpConstant(2, temp3)); |
| 1180 |
| 1181 __ bind(&done); |
| 1182 } |
| 1183 |
1041 #ifdef DEBUG | 1184 #ifdef DEBUG |
1042 // nop(CODE_AGE_MARKER_NOP) | 1185 // nop(CODE_AGE_MARKER_NOP) |
1043 static const uint32_t kCodeAgePatchFirstInstruction = 0x00010180; | 1186 static const uint32_t kCodeAgePatchFirstInstruction = 0x00010180; |
1044 #endif | 1187 #endif |
1045 | 1188 |
1046 | 1189 |
1047 CodeAgingHelper::CodeAgingHelper(Isolate* isolate) { | 1190 CodeAgingHelper::CodeAgingHelper(Isolate* isolate) { |
1048 USE(isolate); | 1191 USE(isolate); |
1049 DCHECK(young_sequence_.length() == kNoCodeAgeSequenceLength); | 1192 DCHECK(young_sequence_.length() == kNoCodeAgeSequenceLength); |
1050 // Since patcher is a large object, allocate it dynamically when needed, | 1193 // Since patcher is a large object, allocate it dynamically when needed, |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1116 } | 1259 } |
1117 } | 1260 } |
1118 | 1261 |
1119 | 1262 |
1120 #undef __ | 1263 #undef __ |
1121 | 1264 |
1122 } // namespace internal | 1265 } // namespace internal |
1123 } // namespace v8 | 1266 } // namespace v8 |
1124 | 1267 |
1125 #endif // V8_TARGET_ARCH_MIPS | 1268 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |