| 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  |  | 
|    73 #if defined(V8_HOST_ARCH_MIPS) |    20 #if defined(V8_HOST_ARCH_MIPS) | 
|    74 MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate, |    21 MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate, | 
|    75                                                 MemCopyUint8Function stub) { |    22                                                 MemCopyUint8Function stub) { | 
|    76 #if defined(USE_SIMULATOR) |    23 #if defined(USE_SIMULATOR) | 
|    77   return stub; |    24   return stub; | 
|    78 #else |    25 #else | 
|    79  |    26  | 
|    80   size_t actual_size; |    27   size_t actual_size; | 
|    81   byte* buffer = |    28   byte* buffer = | 
|    82       static_cast<byte*>(base::OS::Allocate(3 * KB, &actual_size, true)); |    29       static_cast<byte*>(base::OS::Allocate(3 * KB, &actual_size, true)); | 
| (...skipping 1000 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1083   __ Dlsa(at, string, index, 1); |  1030   __ Dlsa(at, string, index, 1); | 
|  1084   __ lhu(result, MemOperand(at)); |  1031   __ lhu(result, MemOperand(at)); | 
|  1085   __ jmp(&done); |  1032   __ jmp(&done); | 
|  1086   __ bind(&one_byte); |  1033   __ bind(&one_byte); | 
|  1087   // One_byte string. |  1034   // One_byte string. | 
|  1088   __ Daddu(at, string, index); |  1035   __ Daddu(at, string, index); | 
|  1089   __ lbu(result, MemOperand(at)); |  1036   __ lbu(result, MemOperand(at)); | 
|  1090   __ bind(&done); |  1037   __ bind(&done); | 
|  1091 } |  1038 } | 
|  1092  |  1039  | 
|  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  |  | 
|  1181 #ifdef DEBUG |  1040 #ifdef DEBUG | 
|  1182 // nop(CODE_AGE_MARKER_NOP) |  1041 // nop(CODE_AGE_MARKER_NOP) | 
|  1183 static const uint32_t kCodeAgePatchFirstInstruction = 0x00010180; |  1042 static const uint32_t kCodeAgePatchFirstInstruction = 0x00010180; | 
|  1184 #endif |  1043 #endif | 
|  1185  |  1044  | 
|  1186  |  1045  | 
|  1187 CodeAgingHelper::CodeAgingHelper(Isolate* isolate) { |  1046 CodeAgingHelper::CodeAgingHelper(Isolate* isolate) { | 
|  1188   USE(isolate); |  1047   USE(isolate); | 
|  1189   DCHECK(young_sequence_.length() == kNoCodeAgeSequenceLength); |  1048   DCHECK(young_sequence_.length() == kNoCodeAgeSequenceLength); | 
|  1190   // Since patcher is a large object, allocate it dynamically when needed, |  1049   // Since patcher is a large object, allocate it dynamically when needed, | 
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1258   } |  1117   } | 
|  1259 } |  1118 } | 
|  1260  |  1119  | 
|  1261  |  1120  | 
|  1262 #undef __ |  1121 #undef __ | 
|  1263  |  1122  | 
|  1264 }  // namespace internal |  1123 }  // namespace internal | 
|  1265 }  // namespace v8 |  1124 }  // namespace v8 | 
|  1266  |  1125  | 
|  1267 #endif  // V8_TARGET_ARCH_MIPS64 |  1126 #endif  // V8_TARGET_ARCH_MIPS64 | 
| OLD | NEW |