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/mips64/codegen-mips64.h" | 5 #include "src/mips64/codegen-mips64.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_MIPS64 | 7 #if V8_TARGET_ARCH_MIPS64 |
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/mips64/simulator-mips64.h" | 11 #include "src/mips64/simulator-mips64.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 | 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 = a4; |
| 44 Register temp2 = a5; |
| 45 Register temp3 = a6; |
| 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 |
20 #if defined(V8_HOST_ARCH_MIPS) | 73 #if defined(V8_HOST_ARCH_MIPS) |
21 MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate, | 74 MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate, |
22 MemCopyUint8Function stub) { | 75 MemCopyUint8Function stub) { |
23 #if defined(USE_SIMULATOR) | 76 #if defined(USE_SIMULATOR) |
24 return stub; | 77 return stub; |
25 #else | 78 #else |
26 | 79 |
27 size_t actual_size; | 80 size_t actual_size; |
28 byte* buffer = | 81 byte* buffer = |
29 static_cast<byte*>(base::OS::Allocate(3 * KB, &actual_size, true)); | 82 static_cast<byte*>(base::OS::Allocate(3 * KB, &actual_size, true)); |
(...skipping 1000 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1030 __ Dlsa(at, string, index, 1); | 1083 __ Dlsa(at, string, index, 1); |
1031 __ lhu(result, MemOperand(at)); | 1084 __ lhu(result, MemOperand(at)); |
1032 __ jmp(&done); | 1085 __ jmp(&done); |
1033 __ bind(&one_byte); | 1086 __ bind(&one_byte); |
1034 // One_byte string. | 1087 // One_byte string. |
1035 __ Daddu(at, string, index); | 1088 __ Daddu(at, string, index); |
1036 __ lbu(result, MemOperand(at)); | 1089 __ lbu(result, MemOperand(at)); |
1037 __ bind(&done); | 1090 __ bind(&done); |
1038 } | 1091 } |
1039 | 1092 |
| 1093 |
| 1094 static MemOperand ExpConstant(int index, Register base) { |
| 1095 return MemOperand(base, index * kDoubleSize); |
| 1096 } |
| 1097 |
| 1098 |
| 1099 void MathExpGenerator::EmitMathExp(MacroAssembler* masm, |
| 1100 DoubleRegister input, |
| 1101 DoubleRegister result, |
| 1102 DoubleRegister double_scratch1, |
| 1103 DoubleRegister double_scratch2, |
| 1104 Register temp1, |
| 1105 Register temp2, |
| 1106 Register temp3) { |
| 1107 DCHECK(!input.is(result)); |
| 1108 DCHECK(!input.is(double_scratch1)); |
| 1109 DCHECK(!input.is(double_scratch2)); |
| 1110 DCHECK(!result.is(double_scratch1)); |
| 1111 DCHECK(!result.is(double_scratch2)); |
| 1112 DCHECK(!double_scratch1.is(double_scratch2)); |
| 1113 DCHECK(!temp1.is(temp2)); |
| 1114 DCHECK(!temp1.is(temp3)); |
| 1115 DCHECK(!temp2.is(temp3)); |
| 1116 DCHECK(ExternalReference::math_exp_constants(0).address() != NULL); |
| 1117 DCHECK(!masm->serializer_enabled()); // External references not serializable. |
| 1118 |
| 1119 Label zero, infinity, done; |
| 1120 __ li(temp3, Operand(ExternalReference::math_exp_constants(0))); |
| 1121 |
| 1122 __ ldc1(double_scratch1, ExpConstant(0, temp3)); |
| 1123 __ BranchF(&zero, NULL, ge, double_scratch1, input); |
| 1124 |
| 1125 __ ldc1(double_scratch2, ExpConstant(1, temp3)); |
| 1126 __ BranchF(&infinity, NULL, ge, input, double_scratch2); |
| 1127 |
| 1128 __ ldc1(double_scratch1, ExpConstant(3, temp3)); |
| 1129 __ ldc1(result, ExpConstant(4, temp3)); |
| 1130 __ mul_d(double_scratch1, double_scratch1, input); |
| 1131 __ add_d(double_scratch1, double_scratch1, result); |
| 1132 __ FmoveLow(temp2, double_scratch1); |
| 1133 __ sub_d(double_scratch1, double_scratch1, result); |
| 1134 __ ldc1(result, ExpConstant(6, temp3)); |
| 1135 __ ldc1(double_scratch2, ExpConstant(5, temp3)); |
| 1136 __ mul_d(double_scratch1, double_scratch1, double_scratch2); |
| 1137 __ sub_d(double_scratch1, double_scratch1, input); |
| 1138 __ sub_d(result, result, double_scratch1); |
| 1139 __ mul_d(double_scratch2, double_scratch1, double_scratch1); |
| 1140 __ mul_d(result, result, double_scratch2); |
| 1141 __ ldc1(double_scratch2, ExpConstant(7, temp3)); |
| 1142 __ mul_d(result, result, double_scratch2); |
| 1143 __ sub_d(result, result, double_scratch1); |
| 1144 // Mov 1 in double_scratch2 as math_exp_constants_array[8] == 1. |
| 1145 DCHECK(*reinterpret_cast<double*> |
| 1146 (ExternalReference::math_exp_constants(8).address()) == 1); |
| 1147 __ Move(double_scratch2, 1.); |
| 1148 __ add_d(result, result, double_scratch2); |
| 1149 __ dsrl(temp1, temp2, 11); |
| 1150 __ Ext(temp2, temp2, 0, 11); |
| 1151 __ Daddu(temp1, temp1, Operand(0x3ff)); |
| 1152 |
| 1153 // Must not call ExpConstant() after overwriting temp3! |
| 1154 __ li(temp3, Operand(ExternalReference::math_exp_log_table())); |
| 1155 __ Dlsa(temp3, temp3, temp2, 3); |
| 1156 __ lwu(temp2, MemOperand(temp3, Register::kMantissaOffset)); |
| 1157 __ lwu(temp3, MemOperand(temp3, Register::kExponentOffset)); |
| 1158 // The first word is loaded is the lower number register. |
| 1159 if (temp2.code() < temp3.code()) { |
| 1160 __ dsll(at, temp1, 20); |
| 1161 __ Or(temp1, temp3, at); |
| 1162 __ Move(double_scratch1, temp2, temp1); |
| 1163 } else { |
| 1164 __ dsll(at, temp1, 20); |
| 1165 __ Or(temp1, temp2, at); |
| 1166 __ Move(double_scratch1, temp3, temp1); |
| 1167 } |
| 1168 __ mul_d(result, result, double_scratch1); |
| 1169 __ BranchShort(&done); |
| 1170 |
| 1171 __ bind(&zero); |
| 1172 __ Move(result, kDoubleRegZero); |
| 1173 __ BranchShort(&done); |
| 1174 |
| 1175 __ bind(&infinity); |
| 1176 __ ldc1(result, ExpConstant(2, temp3)); |
| 1177 |
| 1178 __ bind(&done); |
| 1179 } |
| 1180 |
1040 #ifdef DEBUG | 1181 #ifdef DEBUG |
1041 // nop(CODE_AGE_MARKER_NOP) | 1182 // nop(CODE_AGE_MARKER_NOP) |
1042 static const uint32_t kCodeAgePatchFirstInstruction = 0x00010180; | 1183 static const uint32_t kCodeAgePatchFirstInstruction = 0x00010180; |
1043 #endif | 1184 #endif |
1044 | 1185 |
1045 | 1186 |
1046 CodeAgingHelper::CodeAgingHelper(Isolate* isolate) { | 1187 CodeAgingHelper::CodeAgingHelper(Isolate* isolate) { |
1047 USE(isolate); | 1188 USE(isolate); |
1048 DCHECK(young_sequence_.length() == kNoCodeAgeSequenceLength); | 1189 DCHECK(young_sequence_.length() == kNoCodeAgeSequenceLength); |
1049 // Since patcher is a large object, allocate it dynamically when needed, | 1190 // Since patcher is a large object, allocate it dynamically when needed, |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1117 } | 1258 } |
1118 } | 1259 } |
1119 | 1260 |
1120 | 1261 |
1121 #undef __ | 1262 #undef __ |
1122 | 1263 |
1123 } // namespace internal | 1264 } // namespace internal |
1124 } // namespace v8 | 1265 } // namespace v8 |
1125 | 1266 |
1126 #endif // V8_TARGET_ARCH_MIPS64 | 1267 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |