| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include <math.h> // for isnan. | 5 #include <math.h> // for isnan. |
| 6 #include <setjmp.h> | 6 #include <setjmp.h> |
| 7 #include <stdlib.h> | 7 #include <stdlib.h> |
| 8 | 8 |
| 9 #include "vm/globals.h" | 9 #include "vm/globals.h" |
| 10 #if defined(TARGET_ARCH_ARM64) | 10 #if defined(TARGET_ARCH_ARM64) |
| (...skipping 645 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 656 Simulator* simulator = Isolate::Current()->simulator(); | 656 Simulator* simulator = Isolate::Current()->simulator(); |
| 657 if (simulator == NULL) { | 657 if (simulator == NULL) { |
| 658 simulator = new Simulator(); | 658 simulator = new Simulator(); |
| 659 Isolate::Current()->set_simulator(simulator); | 659 Isolate::Current()->set_simulator(simulator); |
| 660 } | 660 } |
| 661 return simulator; | 661 return simulator; |
| 662 } | 662 } |
| 663 | 663 |
| 664 | 664 |
| 665 // Sets the register in the architecture state. | 665 // Sets the register in the architecture state. |
| 666 void Simulator::set_register(Register reg, int64_t value, R31Type r31t) { | 666 void Simulator::set_register( |
| 667 // register is in range, and if it is R31, a mode is specified. | 667 Instr* instr, Register reg, int64_t value, R31Type r31t) { |
| 668 // Register is in range. |
| 668 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); | 669 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); |
| 669 if ((reg != R31) || (r31t != R31IsZR)) { | 670 if ((reg != R31) || (r31t != R31IsZR)) { |
| 670 registers_[reg] = value; | 671 registers_[reg] = value; |
| 672 // If we're setting CSP, make sure it is 16-byte aligned. In truth, CSP |
| 673 // can store addresses that are not 16-byte aligned, but loads and stores |
| 674 // are not allowed through CSP when it is not aligned. Thus, this check is |
| 675 // more conservative that necessary. However, it will likely be more |
| 676 // useful to find the program locations where CSP is set to a bad value, |
| 677 // than to find only the resulting loads/stores that would cause a fault on |
| 678 // hardware. |
| 679 if ((instr != NULL) && (reg == R31) && !Utils::IsAligned(value, 16)) { |
| 680 UnalignedAccess("CSP set", value, instr); |
| 681 } |
| 671 } | 682 } |
| 672 } | 683 } |
| 673 | 684 |
| 674 | 685 |
| 675 // Get the register from the architecture state. | 686 // Get the register from the architecture state. |
| 676 int64_t Simulator::get_register(Register reg, R31Type r31t) const { | 687 int64_t Simulator::get_register(Register reg, R31Type r31t) const { |
| 677 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); | 688 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); |
| 678 if ((reg == R31) && (r31t == R31IsZR)) { | 689 if ((reg == R31) && (r31t == R31IsZR)) { |
| 679 return 0; | 690 return 0; |
| 680 } else { | 691 } else { |
| (...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1027 void Simulator::DecodeMoveWide(Instr* instr) { | 1038 void Simulator::DecodeMoveWide(Instr* instr) { |
| 1028 const Register rd = instr->RdField(); | 1039 const Register rd = instr->RdField(); |
| 1029 const int hw = instr->HWField(); | 1040 const int hw = instr->HWField(); |
| 1030 const int64_t shift = hw << 4; | 1041 const int64_t shift = hw << 4; |
| 1031 const int64_t shifted_imm = | 1042 const int64_t shifted_imm = |
| 1032 static_cast<int64_t>(instr->Imm16Field()) << shift; | 1043 static_cast<int64_t>(instr->Imm16Field()) << shift; |
| 1033 | 1044 |
| 1034 if (instr->SFField()) { | 1045 if (instr->SFField()) { |
| 1035 if (instr->Bits(29, 2) == 0) { | 1046 if (instr->Bits(29, 2) == 0) { |
| 1036 // Format(instr, "movn'sf 'rd, 'imm16 'hw"); | 1047 // Format(instr, "movn'sf 'rd, 'imm16 'hw"); |
| 1037 set_register(rd, ~shifted_imm, instr->RdMode()); | 1048 set_register(instr, rd, ~shifted_imm, instr->RdMode()); |
| 1038 } else if (instr->Bits(29, 2) == 2) { | 1049 } else if (instr->Bits(29, 2) == 2) { |
| 1039 // Format(instr, "movz'sf 'rd, 'imm16 'hw"); | 1050 // Format(instr, "movz'sf 'rd, 'imm16 'hw"); |
| 1040 set_register(rd, shifted_imm, instr->RdMode()); | 1051 set_register(instr, rd, shifted_imm, instr->RdMode()); |
| 1041 } else if (instr->Bits(29, 2) == 3) { | 1052 } else if (instr->Bits(29, 2) == 3) { |
| 1042 // Format(instr, "movk'sf 'rd, 'imm16 'hw"); | 1053 // Format(instr, "movk'sf 'rd, 'imm16 'hw"); |
| 1043 const int64_t rd_val = get_register(rd, instr->RdMode()); | 1054 const int64_t rd_val = get_register(rd, instr->RdMode()); |
| 1044 const int64_t result = (rd_val & ~(0xffffL << shift)) | shifted_imm; | 1055 const int64_t result = (rd_val & ~(0xffffL << shift)) | shifted_imm; |
| 1045 set_register(rd, result, instr->RdMode()); | 1056 set_register(instr, rd, result, instr->RdMode()); |
| 1046 } else { | 1057 } else { |
| 1047 UnimplementedInstruction(instr); | 1058 UnimplementedInstruction(instr); |
| 1048 } | 1059 } |
| 1049 } else if ((hw & 0x2) == 0) { | 1060 } else if ((hw & 0x2) == 0) { |
| 1050 if (instr->Bits(29, 2) == 0) { | 1061 if (instr->Bits(29, 2) == 0) { |
| 1051 // Format(instr, "movn'sf 'rd, 'imm16 'hw"); | 1062 // Format(instr, "movn'sf 'rd, 'imm16 'hw"); |
| 1052 set_wregister(rd, ~shifted_imm & kWRegMask, instr->RdMode()); | 1063 set_wregister(rd, ~shifted_imm & kWRegMask, instr->RdMode()); |
| 1053 } else if (instr->Bits(29, 2) == 2) { | 1064 } else if (instr->Bits(29, 2) == 2) { |
| 1054 // Format(instr, "movz'sf 'rd, 'imm16 'hw"); | 1065 // Format(instr, "movz'sf 'rd, 'imm16 'hw"); |
| 1055 set_wregister(rd, shifted_imm & kWRegMask, instr->RdMode()); | 1066 set_wregister(rd, shifted_imm & kWRegMask, instr->RdMode()); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1073 // Format(instr, "addi'sf's 'rd, 'rn, 'imm12s"); | 1084 // Format(instr, "addi'sf's 'rd, 'rn, 'imm12s"); |
| 1074 // Format(instr, "subi'sf's 'rd, 'rn, 'imm12s"); | 1085 // Format(instr, "subi'sf's 'rd, 'rn, 'imm12s"); |
| 1075 const Register rd = instr->RdField(); | 1086 const Register rd = instr->RdField(); |
| 1076 const Register rn = instr->RnField(); | 1087 const Register rn = instr->RnField(); |
| 1077 const uint32_t imm = (instr->Bit(22) == 1) ? (instr->Imm12Field() << 12) | 1088 const uint32_t imm = (instr->Bit(22) == 1) ? (instr->Imm12Field() << 12) |
| 1078 : (instr->Imm12Field()); | 1089 : (instr->Imm12Field()); |
| 1079 if (instr->SFField()) { | 1090 if (instr->SFField()) { |
| 1080 // 64-bit add. | 1091 // 64-bit add. |
| 1081 const int64_t rn_val = get_register(rn, instr->RnMode()); | 1092 const int64_t rn_val = get_register(rn, instr->RnMode()); |
| 1082 const int64_t alu_out = addition ? (rn_val + imm) : (rn_val - imm); | 1093 const int64_t alu_out = addition ? (rn_val + imm) : (rn_val - imm); |
| 1083 set_register(rd, alu_out, instr->RdMode()); | 1094 set_register(instr, rd, alu_out, instr->RdMode()); |
| 1084 if (instr->HasS()) { | 1095 if (instr->HasS()) { |
| 1085 SetNZFlagsX(alu_out); | 1096 SetNZFlagsX(alu_out); |
| 1086 if (addition) { | 1097 if (addition) { |
| 1087 SetCFlag(CarryFromX(rn_val, imm)); | 1098 SetCFlag(CarryFromX(rn_val, imm)); |
| 1088 } else { | 1099 } else { |
| 1089 SetCFlag(!BorrowFromX(rn_val, imm)); | 1100 SetCFlag(!BorrowFromX(rn_val, imm)); |
| 1090 } | 1101 } |
| 1091 SetVFlag(OverflowFromX(alu_out, rn_val, imm, addition)); | 1102 SetVFlag(OverflowFromX(alu_out, rn_val, imm, addition)); |
| 1092 } | 1103 } |
| 1093 } else { | 1104 } else { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1144 if (out_size == kXRegSizeInBits) { | 1155 if (out_size == kXRegSizeInBits) { |
| 1145 SetNZFlagsX(alu_out); | 1156 SetNZFlagsX(alu_out); |
| 1146 } else { | 1157 } else { |
| 1147 SetNZFlagsW(alu_out); | 1158 SetNZFlagsW(alu_out); |
| 1148 } | 1159 } |
| 1149 SetCFlag(false); | 1160 SetCFlag(false); |
| 1150 SetVFlag(false); | 1161 SetVFlag(false); |
| 1151 } | 1162 } |
| 1152 | 1163 |
| 1153 if (out_size == kXRegSizeInBits) { | 1164 if (out_size == kXRegSizeInBits) { |
| 1154 set_register(rd, alu_out, instr->RdMode()); | 1165 set_register(instr, rd, alu_out, instr->RdMode()); |
| 1155 } else { | 1166 } else { |
| 1156 set_wregister(rd, alu_out, instr->RdMode()); | 1167 set_wregister(rd, alu_out, instr->RdMode()); |
| 1157 } | 1168 } |
| 1158 } | 1169 } |
| 1159 | 1170 |
| 1160 | 1171 |
| 1161 void Simulator::DecodePCRel(Instr* instr) { | 1172 void Simulator::DecodePCRel(Instr* instr) { |
| 1162 const int op = instr->Bit(31); | 1173 const int op = instr->Bit(31); |
| 1163 if (op == 0) { | 1174 if (op == 0) { |
| 1164 // Format(instr, "adr 'rd, 'pcrel") | 1175 // Format(instr, "adr 'rd, 'pcrel") |
| 1165 const Register rd = instr->RdField(); | 1176 const Register rd = instr->RdField(); |
| 1166 const int64_t immhi = instr->SImm19Field(); | 1177 const int64_t immhi = instr->SImm19Field(); |
| 1167 const int64_t immlo = instr->Bits(29, 2); | 1178 const int64_t immlo = instr->Bits(29, 2); |
| 1168 const int64_t off = (immhi << 2) | immlo; | 1179 const int64_t off = (immhi << 2) | immlo; |
| 1169 const int64_t dest = get_pc() + off; | 1180 const int64_t dest = get_pc() + off; |
| 1170 set_register(rd, dest, instr->RdMode()); | 1181 set_register(instr, rd, dest, instr->RdMode()); |
| 1171 } else { | 1182 } else { |
| 1172 UnimplementedInstruction(instr); | 1183 UnimplementedInstruction(instr); |
| 1173 } | 1184 } |
| 1174 } | 1185 } |
| 1175 | 1186 |
| 1176 | 1187 |
| 1177 void Simulator::DecodeDPImmediate(Instr* instr) { | 1188 void Simulator::DecodeDPImmediate(Instr* instr) { |
| 1178 if (instr->IsMoveWideOp()) { | 1189 if (instr->IsMoveWideOp()) { |
| 1179 DecodeMoveWide(instr); | 1190 DecodeMoveWide(instr); |
| 1180 } else if (instr->IsAddSubImmOp()) { | 1191 } else if (instr->IsAddSubImmOp()) { |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1280 OS::Print("Call to host function at 0x%" Pd "\n", external); | 1291 OS::Print("Call to host function at 0x%" Pd "\n", external); |
| 1281 } | 1292 } |
| 1282 | 1293 |
| 1283 if ((redirection->call_kind() == kRuntimeCall) || | 1294 if ((redirection->call_kind() == kRuntimeCall) || |
| 1284 (redirection->call_kind() == kBootstrapNativeCall) || | 1295 (redirection->call_kind() == kBootstrapNativeCall) || |
| 1285 (redirection->call_kind() == kNativeCall)) { | 1296 (redirection->call_kind() == kNativeCall)) { |
| 1286 // Set the top_exit_frame_info of this simulator to the native stack. | 1297 // Set the top_exit_frame_info of this simulator to the native stack. |
| 1287 set_top_exit_frame_info(reinterpret_cast<uword>(&buffer)); | 1298 set_top_exit_frame_info(reinterpret_cast<uword>(&buffer)); |
| 1288 } | 1299 } |
| 1289 if (redirection->call_kind() == kRuntimeCall) { | 1300 if (redirection->call_kind() == kRuntimeCall) { |
| 1290 NativeArguments arguments; | 1301 NativeArguments* arguments = |
| 1291 ASSERT(sizeof(NativeArguments) == 4*kWordSize); | 1302 reinterpret_cast<NativeArguments*>(get_register(R0)); |
| 1292 arguments.isolate_ = reinterpret_cast<Isolate*>(get_register(R0)); | |
| 1293 arguments.argc_tag_ = get_register(R1); | |
| 1294 arguments.argv_ = reinterpret_cast<RawObject*(*)[]>(get_register(R2)); | |
| 1295 arguments.retval_ = reinterpret_cast<RawObject**>(get_register(R3)); | |
| 1296 SimulatorRuntimeCall target = | 1303 SimulatorRuntimeCall target = |
| 1297 reinterpret_cast<SimulatorRuntimeCall>(external); | 1304 reinterpret_cast<SimulatorRuntimeCall>(external); |
| 1298 target(arguments); | 1305 target(*arguments); |
| 1299 set_register(R0, icount_); // Zap result register from void function. | 1306 // Zap result register from void function. |
| 1300 set_register(R1, icount_); | 1307 set_register(instr, R0, icount_); |
| 1308 set_register(instr, R1, icount_); |
| 1301 } else if (redirection->call_kind() == kLeafRuntimeCall) { | 1309 } else if (redirection->call_kind() == kLeafRuntimeCall) { |
| 1302 ASSERT((0 <= redirection->argument_count()) && | 1310 ASSERT((0 <= redirection->argument_count()) && |
| 1303 (redirection->argument_count() <= 8)); | 1311 (redirection->argument_count() <= 8)); |
| 1304 SimulatorLeafRuntimeCall target = | 1312 SimulatorLeafRuntimeCall target = |
| 1305 reinterpret_cast<SimulatorLeafRuntimeCall>(external); | 1313 reinterpret_cast<SimulatorLeafRuntimeCall>(external); |
| 1306 const int64_t r0 = get_register(R0); | 1314 const int64_t r0 = get_register(R0); |
| 1307 const int64_t r1 = get_register(R1); | 1315 const int64_t r1 = get_register(R1); |
| 1308 const int64_t r2 = get_register(R2); | 1316 const int64_t r2 = get_register(R2); |
| 1309 const int64_t r3 = get_register(R3); | 1317 const int64_t r3 = get_register(R3); |
| 1310 const int64_t r4 = get_register(R4); | 1318 const int64_t r4 = get_register(R4); |
| 1311 const int64_t r5 = get_register(R5); | 1319 const int64_t r5 = get_register(R5); |
| 1312 const int64_t r6 = get_register(R6); | 1320 const int64_t r6 = get_register(R6); |
| 1313 const int64_t r7 = get_register(R7); | 1321 const int64_t r7 = get_register(R7); |
| 1314 const int64_t res = target(r0, r1, r2, r3, r4, r5, r6, r7); | 1322 const int64_t res = target(r0, r1, r2, r3, r4, r5, r6, r7); |
| 1315 set_register(R0, res); // Set returned result from function. | 1323 set_register(instr, R0, res); // Set returned result from function. |
| 1316 set_register(R1, icount_); // Zap unused result register. | 1324 set_register(instr, R1, icount_); // Zap unused result register. |
| 1317 } else if (redirection->call_kind() == kLeafFloatRuntimeCall) { | 1325 } else if (redirection->call_kind() == kLeafFloatRuntimeCall) { |
| 1318 ASSERT((0 <= redirection->argument_count()) && | 1326 ASSERT((0 <= redirection->argument_count()) && |
| 1319 (redirection->argument_count() <= 8)); | 1327 (redirection->argument_count() <= 8)); |
| 1320 SimulatorLeafFloatRuntimeCall target = | 1328 SimulatorLeafFloatRuntimeCall target = |
| 1321 reinterpret_cast<SimulatorLeafFloatRuntimeCall>(external); | 1329 reinterpret_cast<SimulatorLeafFloatRuntimeCall>(external); |
| 1322 const double d0 = bit_cast<double, int64_t>(get_vregisterd(V0, 0)); | 1330 const double d0 = bit_cast<double, int64_t>(get_vregisterd(V0, 0)); |
| 1323 const double d1 = bit_cast<double, int64_t>(get_vregisterd(V1, 0)); | 1331 const double d1 = bit_cast<double, int64_t>(get_vregisterd(V1, 0)); |
| 1324 const double d2 = bit_cast<double, int64_t>(get_vregisterd(V2, 0)); | 1332 const double d2 = bit_cast<double, int64_t>(get_vregisterd(V2, 0)); |
| 1325 const double d3 = bit_cast<double, int64_t>(get_vregisterd(V3, 0)); | 1333 const double d3 = bit_cast<double, int64_t>(get_vregisterd(V3, 0)); |
| 1326 const double d4 = bit_cast<double, int64_t>(get_vregisterd(V4, 0)); | 1334 const double d4 = bit_cast<double, int64_t>(get_vregisterd(V4, 0)); |
| 1327 const double d5 = bit_cast<double, int64_t>(get_vregisterd(V5, 0)); | 1335 const double d5 = bit_cast<double, int64_t>(get_vregisterd(V5, 0)); |
| 1328 const double d6 = bit_cast<double, int64_t>(get_vregisterd(V6, 0)); | 1336 const double d6 = bit_cast<double, int64_t>(get_vregisterd(V6, 0)); |
| 1329 const double d7 = bit_cast<double, int64_t>(get_vregisterd(V7, 0)); | 1337 const double d7 = bit_cast<double, int64_t>(get_vregisterd(V7, 0)); |
| 1330 const double res = target(d0, d1, d2, d3, d4, d5, d6, d7); | 1338 const double res = target(d0, d1, d2, d3, d4, d5, d6, d7); |
| 1331 set_vregisterd(V0, 0, bit_cast<int64_t, double>(res)); | 1339 set_vregisterd(V0, 0, bit_cast<int64_t, double>(res)); |
| 1332 set_vregisterd(V0, 1, 0); | 1340 set_vregisterd(V0, 1, 0); |
| 1333 } else if (redirection->call_kind() == kBootstrapNativeCall) { | 1341 } else if (redirection->call_kind() == kBootstrapNativeCall) { |
| 1334 NativeArguments* arguments; | 1342 NativeArguments* arguments; |
| 1335 arguments = reinterpret_cast<NativeArguments*>(get_register(R0)); | 1343 arguments = reinterpret_cast<NativeArguments*>(get_register(R0)); |
| 1336 SimulatorBootstrapNativeCall target = | 1344 SimulatorBootstrapNativeCall target = |
| 1337 reinterpret_cast<SimulatorBootstrapNativeCall>(external); | 1345 reinterpret_cast<SimulatorBootstrapNativeCall>(external); |
| 1338 target(arguments); | 1346 target(arguments); |
| 1339 set_register(R0, icount_); // Zap result register from void function. | 1347 // Zap result register from void function. |
| 1348 set_register(instr, R0, icount_); |
| 1340 } else { | 1349 } else { |
| 1341 ASSERT(redirection->call_kind() == kNativeCall); | 1350 ASSERT(redirection->call_kind() == kNativeCall); |
| 1342 NativeArguments* arguments; | 1351 NativeArguments* arguments; |
| 1343 arguments = reinterpret_cast<NativeArguments*>(get_register(R0)); | 1352 arguments = reinterpret_cast<NativeArguments*>(get_register(R0)); |
| 1344 uword target_func = get_register(R1); | 1353 uword target_func = get_register(R1); |
| 1345 SimulatorNativeCall target = | 1354 SimulatorNativeCall target = |
| 1346 reinterpret_cast<SimulatorNativeCall>(external); | 1355 reinterpret_cast<SimulatorNativeCall>(external); |
| 1347 target(arguments, target_func); | 1356 target(arguments, target_func); |
| 1348 set_register(R0, icount_); // Zap result register from void function. | 1357 // Zap result register from void function. |
| 1349 set_register(R1, icount_); | 1358 set_register(instr, R0, icount_); |
| 1359 set_register(instr, R1, icount_); |
| 1350 } | 1360 } |
| 1351 set_top_exit_frame_info(0); | 1361 set_top_exit_frame_info(0); |
| 1352 | 1362 |
| 1353 // Zap caller-saved registers, since the actual runtime call could have | 1363 // Zap caller-saved registers, since the actual runtime call could have |
| 1354 // used them. | 1364 // used them. |
| 1355 set_register(R2, icount_); | 1365 set_register(instr, R2, icount_); |
| 1356 set_register(R3, icount_); | 1366 set_register(instr, R3, icount_); |
| 1357 set_register(R4, icount_); | 1367 set_register(instr, R4, icount_); |
| 1358 set_register(R5, icount_); | 1368 set_register(instr, R5, icount_); |
| 1359 set_register(R6, icount_); | 1369 set_register(instr, R6, icount_); |
| 1360 set_register(R7, icount_); | 1370 set_register(instr, R7, icount_); |
| 1361 set_register(R8, icount_); | 1371 set_register(instr, R8, icount_); |
| 1362 set_register(R9, icount_); | 1372 set_register(instr, R9, icount_); |
| 1363 set_register(R10, icount_); | 1373 set_register(instr, R10, icount_); |
| 1364 set_register(R11, icount_); | 1374 set_register(instr, R11, icount_); |
| 1365 set_register(R12, icount_); | 1375 set_register(instr, R12, icount_); |
| 1366 set_register(R13, icount_); | 1376 set_register(instr, R13, icount_); |
| 1367 set_register(R14, icount_); | 1377 set_register(instr, R14, icount_); |
| 1368 set_register(R15, icount_); | 1378 set_register(instr, R15, icount_); |
| 1369 set_register(IP0, icount_); | 1379 set_register(instr, IP0, icount_); |
| 1370 set_register(IP1, icount_); | 1380 set_register(instr, IP1, icount_); |
| 1371 set_register(R18, icount_); | 1381 set_register(instr, R18, icount_); |
| 1372 set_register(LR, icount_); | 1382 set_register(instr, LR, icount_); |
| 1373 | 1383 |
| 1374 // TODO(zra): Zap caller-saved fpu registers. | 1384 // TODO(zra): Zap caller-saved fpu registers. |
| 1375 | 1385 |
| 1376 // Return. | 1386 // Return. |
| 1377 set_pc(saved_lr); | 1387 set_pc(saved_lr); |
| 1378 } else { | 1388 } else { |
| 1379 // Coming via long jump from a throw. Continue to exception handler. | 1389 // Coming via long jump from a throw. Continue to exception handler. |
| 1380 set_top_exit_frame_info(0); | 1390 set_top_exit_frame_info(0); |
| 1381 } | 1391 } |
| 1382 } | 1392 } |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1450 } | 1460 } |
| 1451 | 1461 |
| 1452 | 1462 |
| 1453 void Simulator::DecodeUnconditionalBranch(Instr* instr) { | 1463 void Simulator::DecodeUnconditionalBranch(Instr* instr) { |
| 1454 const bool link = instr->Bit(31) == 1; | 1464 const bool link = instr->Bit(31) == 1; |
| 1455 const int64_t imm26 = instr->SImm26Field(); | 1465 const int64_t imm26 = instr->SImm26Field(); |
| 1456 const int64_t dest = get_pc() + (imm26 << 2); | 1466 const int64_t dest = get_pc() + (imm26 << 2); |
| 1457 const int64_t ret = get_pc() + Instr::kInstrSize; | 1467 const int64_t ret = get_pc() + Instr::kInstrSize; |
| 1458 set_pc(dest); | 1468 set_pc(dest); |
| 1459 if (link) { | 1469 if (link) { |
| 1460 set_register(LR, ret); | 1470 set_register(instr, LR, ret); |
| 1461 } | 1471 } |
| 1462 } | 1472 } |
| 1463 | 1473 |
| 1464 | 1474 |
| 1465 void Simulator::DecodeUnconditionalBranchReg(Instr* instr) { | 1475 void Simulator::DecodeUnconditionalBranchReg(Instr* instr) { |
| 1466 if ((instr->Bits(0, 5) == 0) && (instr->Bits(10, 6) == 0) && | 1476 if ((instr->Bits(0, 5) == 0) && (instr->Bits(10, 6) == 0) && |
| 1467 (instr->Bits(16, 5) == 0x1f)) { | 1477 (instr->Bits(16, 5) == 0x1f)) { |
| 1468 switch (instr->Bits(21, 4)) { | 1478 switch (instr->Bits(21, 4)) { |
| 1469 case 0: { | 1479 case 0: { |
| 1470 // Format(instr, "br 'rn"); | 1480 // Format(instr, "br 'rn"); |
| 1471 const Register rn = instr->RnField(); | 1481 const Register rn = instr->RnField(); |
| 1472 const int64_t dest = get_register(rn, instr->RnMode()); | 1482 const int64_t dest = get_register(rn, instr->RnMode()); |
| 1473 set_pc(dest); | 1483 set_pc(dest); |
| 1474 break; | 1484 break; |
| 1475 } | 1485 } |
| 1476 case 1: { | 1486 case 1: { |
| 1477 // Format(instr, "blr 'rn"); | 1487 // Format(instr, "blr 'rn"); |
| 1478 const Register rn = instr->RnField(); | 1488 const Register rn = instr->RnField(); |
| 1479 const int64_t dest = get_register(rn, instr->RnMode()); | 1489 const int64_t dest = get_register(rn, instr->RnMode()); |
| 1480 const int64_t ret = get_pc() + Instr::kInstrSize; | 1490 const int64_t ret = get_pc() + Instr::kInstrSize; |
| 1481 set_pc(dest); | 1491 set_pc(dest); |
| 1482 set_register(LR, ret); | 1492 set_register(instr, LR, ret); |
| 1483 break; | 1493 break; |
| 1484 } | 1494 } |
| 1485 case 2: { | 1495 case 2: { |
| 1486 // Format(instr, "ret 'rn"); | 1496 // Format(instr, "ret 'rn"); |
| 1487 const Register rn = instr->RnField(); | 1497 const Register rn = instr->RnField(); |
| 1488 const int64_t rn_val = get_register(rn, instr->RnMode()); | 1498 const int64_t rn_val = get_register(rn, instr->RnMode()); |
| 1489 set_pc(rn_val); | 1499 set_pc(rn_val); |
| 1490 break; | 1500 break; |
| 1491 } | 1501 } |
| 1492 default: | 1502 default: |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1696 break; | 1706 break; |
| 1697 default: | 1707 default: |
| 1698 UNREACHABLE(); | 1708 UNREACHABLE(); |
| 1699 break; | 1709 break; |
| 1700 } | 1710 } |
| 1701 | 1711 |
| 1702 // Write to register. | 1712 // Write to register. |
| 1703 if (use_w) { | 1713 if (use_w) { |
| 1704 set_wregister(rt, static_cast<int32_t>(val), R31IsZR); | 1714 set_wregister(rt, static_cast<int32_t>(val), R31IsZR); |
| 1705 } else { | 1715 } else { |
| 1706 set_register(rt, val, R31IsZR); | 1716 set_register(instr, rt, val, R31IsZR); |
| 1707 } | 1717 } |
| 1708 } | 1718 } |
| 1709 } | 1719 } |
| 1710 | 1720 |
| 1711 // Do writeback. | 1721 // Do writeback. |
| 1712 if (wb) { | 1722 if (wb) { |
| 1713 set_register(rn, wb_address, R31IsSP); | 1723 set_register(instr, rn, wb_address, R31IsSP); |
| 1714 } | 1724 } |
| 1715 } | 1725 } |
| 1716 | 1726 |
| 1717 | 1727 |
| 1718 void Simulator::DecodeLoadRegLiteral(Instr* instr) { | 1728 void Simulator::DecodeLoadRegLiteral(Instr* instr) { |
| 1719 if ((instr->Bit(31) != 0) || (instr->Bit(29) != 0) || | 1729 if ((instr->Bit(31) != 0) || (instr->Bit(29) != 0) || |
| 1720 (instr->Bits(24, 3) != 0)) { | 1730 (instr->Bits(24, 3) != 0)) { |
| 1721 UnimplementedInstruction(instr); | 1731 UnimplementedInstruction(instr); |
| 1722 } | 1732 } |
| 1723 | 1733 |
| 1724 const Register rt = instr->RtField(); | 1734 const Register rt = instr->RtField(); |
| 1725 const int64_t off = instr->SImm19Field() << 2; | 1735 const int64_t off = instr->SImm19Field() << 2; |
| 1726 const int64_t pc = reinterpret_cast<int64_t>(instr); | 1736 const int64_t pc = reinterpret_cast<int64_t>(instr); |
| 1727 const int64_t address = pc + off; | 1737 const int64_t address = pc + off; |
| 1728 const int64_t val = ReadX(address, instr); | 1738 const int64_t val = ReadX(address, instr); |
| 1729 if (instr->Bit(30)) { | 1739 if (instr->Bit(30)) { |
| 1730 // Format(instr, "ldrx 'rt, 'pcldr"); | 1740 // Format(instr, "ldrx 'rt, 'pcldr"); |
| 1731 set_register(rt, val, R31IsZR); | 1741 set_register(instr, rt, val, R31IsZR); |
| 1732 } else { | 1742 } else { |
| 1733 // Format(instr, "ldrw 'rt, 'pcldr"); | 1743 // Format(instr, "ldrw 'rt, 'pcldr"); |
| 1734 set_wregister(rt, static_cast<int32_t>(val), R31IsZR); | 1744 set_wregister(rt, static_cast<int32_t>(val), R31IsZR); |
| 1735 } | 1745 } |
| 1736 } | 1746 } |
| 1737 | 1747 |
| 1738 | 1748 |
| 1739 void Simulator::DecodeLoadStore(Instr* instr) { | 1749 void Simulator::DecodeLoadStore(Instr* instr) { |
| 1740 if (instr->IsLoadStoreRegOp()) { | 1750 if (instr->IsLoadStoreRegOp()) { |
| 1741 DecodeLoadStoreReg(instr); | 1751 DecodeLoadStoreReg(instr); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1844 const int64_t rm_val = DecodeShiftExtendOperand(instr); | 1854 const int64_t rm_val = DecodeShiftExtendOperand(instr); |
| 1845 if (instr->SFField()) { | 1855 if (instr->SFField()) { |
| 1846 // 64-bit add. | 1856 // 64-bit add. |
| 1847 const int64_t rn_val = get_register(rn, instr->RnMode()); | 1857 const int64_t rn_val = get_register(rn, instr->RnMode()); |
| 1848 int64_t alu_out = 0; | 1858 int64_t alu_out = 0; |
| 1849 if (subtract) { | 1859 if (subtract) { |
| 1850 alu_out = rn_val - rm_val; | 1860 alu_out = rn_val - rm_val; |
| 1851 } else { | 1861 } else { |
| 1852 alu_out = rn_val + rm_val; | 1862 alu_out = rn_val + rm_val; |
| 1853 } | 1863 } |
| 1854 set_register(rd, alu_out, instr->RdMode()); | 1864 set_register(instr, rd, alu_out, instr->RdMode()); |
| 1855 if (instr->HasS()) { | 1865 if (instr->HasS()) { |
| 1856 SetNZFlagsX(alu_out); | 1866 SetNZFlagsX(alu_out); |
| 1857 if (subtract) { | 1867 if (subtract) { |
| 1858 SetCFlag(!BorrowFromX(rn_val, rm_val)); | 1868 SetCFlag(!BorrowFromX(rn_val, rm_val)); |
| 1859 } else { | 1869 } else { |
| 1860 SetCFlag(CarryFromX(rn_val, rm_val)); | 1870 SetCFlag(CarryFromX(rn_val, rm_val)); |
| 1861 } | 1871 } |
| 1862 SetVFlag(OverflowFromX(alu_out, rn_val, rm_val, !subtract)); | 1872 SetVFlag(OverflowFromX(alu_out, rn_val, rm_val, !subtract)); |
| 1863 } | 1873 } |
| 1864 } else { | 1874 } else { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1935 if (instr->SFField() == 1) { | 1945 if (instr->SFField() == 1) { |
| 1936 SetNZFlagsX(alu_out); | 1946 SetNZFlagsX(alu_out); |
| 1937 } else { | 1947 } else { |
| 1938 SetNZFlagsW(alu_out); | 1948 SetNZFlagsW(alu_out); |
| 1939 } | 1949 } |
| 1940 SetCFlag(false); | 1950 SetCFlag(false); |
| 1941 SetVFlag(false); | 1951 SetVFlag(false); |
| 1942 } | 1952 } |
| 1943 | 1953 |
| 1944 if (instr->SFField() == 1) { | 1954 if (instr->SFField() == 1) { |
| 1945 set_register(rd, alu_out, instr->RdMode()); | 1955 set_register(instr, rd, alu_out, instr->RdMode()); |
| 1946 } else { | 1956 } else { |
| 1947 set_wregister(rd, alu_out & kWRegMask, instr->RdMode()); | 1957 set_wregister(rd, alu_out & kWRegMask, instr->RdMode()); |
| 1948 } | 1958 } |
| 1949 } | 1959 } |
| 1950 | 1960 |
| 1951 | 1961 |
| 1952 static int64_t divide64(int64_t top, int64_t bottom, bool signd) { | 1962 static int64_t divide64(int64_t top, int64_t bottom, bool signd) { |
| 1953 // ARM64 does not trap on integer division by zero. The destination register | 1963 // ARM64 does not trap on integer division by zero. The destination register |
| 1954 // is instead set to 0. | 1964 // is instead set to 0. |
| 1955 if (bottom == 0) { | 1965 if (bottom == 0) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2008 const int64_t rm_val64 = get_register(rm, R31IsZR); | 2018 const int64_t rm_val64 = get_register(rm, R31IsZR); |
| 2009 const int32_t rn_val32 = get_wregister(rn, R31IsZR); | 2019 const int32_t rn_val32 = get_wregister(rn, R31IsZR); |
| 2010 const int32_t rm_val32 = get_wregister(rm, R31IsZR); | 2020 const int32_t rm_val32 = get_wregister(rm, R31IsZR); |
| 2011 switch (op) { | 2021 switch (op) { |
| 2012 case 2: | 2022 case 2: |
| 2013 case 3: { | 2023 case 3: { |
| 2014 // Format(instr, "udiv'sf 'rd, 'rn, 'rm"); | 2024 // Format(instr, "udiv'sf 'rd, 'rn, 'rm"); |
| 2015 // Format(instr, "sdiv'sf 'rd, 'rn, 'rm"); | 2025 // Format(instr, "sdiv'sf 'rd, 'rn, 'rm"); |
| 2016 const bool signd = instr->Bit(10) == 1; | 2026 const bool signd = instr->Bit(10) == 1; |
| 2017 if (instr->SFField() == 1) { | 2027 if (instr->SFField() == 1) { |
| 2018 set_register(rd, divide64(rn_val64, rm_val64, signd), R31IsZR); | 2028 set_register(instr, rd, divide64(rn_val64, rm_val64, signd), R31IsZR); |
| 2019 } else { | 2029 } else { |
| 2020 set_wregister(rd, divide32(rn_val32, rm_val32, signd), R31IsZR); | 2030 set_wregister(rd, divide32(rn_val32, rm_val32, signd), R31IsZR); |
| 2021 } | 2031 } |
| 2022 break; | 2032 break; |
| 2023 } | 2033 } |
| 2024 case 8: { | 2034 case 8: { |
| 2025 // Format(instr, "lsl'sf 'rd, 'rn, 'rm"); | 2035 // Format(instr, "lsl'sf 'rd, 'rn, 'rm"); |
| 2026 if (instr->SFField() == 1) { | 2036 if (instr->SFField() == 1) { |
| 2027 const int64_t alu_out = rn_val64 << (rm_val64 & (kXRegSizeInBits - 1)); | 2037 const int64_t alu_out = rn_val64 << (rm_val64 & (kXRegSizeInBits - 1)); |
| 2028 set_register(rd, alu_out, R31IsZR); | 2038 set_register(instr, rd, alu_out, R31IsZR); |
| 2029 } else { | 2039 } else { |
| 2030 const int32_t alu_out = rn_val32 << (rm_val32 & (kXRegSizeInBits - 1)); | 2040 const int32_t alu_out = rn_val32 << (rm_val32 & (kXRegSizeInBits - 1)); |
| 2031 set_wregister(rd, alu_out, R31IsZR); | 2041 set_wregister(rd, alu_out, R31IsZR); |
| 2032 } | 2042 } |
| 2033 break; | 2043 break; |
| 2034 } | 2044 } |
| 2035 case 9: { | 2045 case 9: { |
| 2036 // Format(instr, "lsr'sf 'rd, 'rn, 'rm"); | 2046 // Format(instr, "lsr'sf 'rd, 'rn, 'rm"); |
| 2037 if (instr->SFField() == 1) { | 2047 if (instr->SFField() == 1) { |
| 2038 const uint64_t rn_u64 = static_cast<uint64_t>(rn_val64); | 2048 const uint64_t rn_u64 = static_cast<uint64_t>(rn_val64); |
| 2039 const int64_t alu_out = rn_u64 >> (rm_val64 & (kXRegSizeInBits - 1)); | 2049 const int64_t alu_out = rn_u64 >> (rm_val64 & (kXRegSizeInBits - 1)); |
| 2040 set_register(rd, alu_out, R31IsZR); | 2050 set_register(instr, rd, alu_out, R31IsZR); |
| 2041 } else { | 2051 } else { |
| 2042 const uint32_t rn_u32 = static_cast<uint32_t>(rn_val32); | 2052 const uint32_t rn_u32 = static_cast<uint32_t>(rn_val32); |
| 2043 const int32_t alu_out = rn_u32 >> (rm_val32 & (kXRegSizeInBits - 1)); | 2053 const int32_t alu_out = rn_u32 >> (rm_val32 & (kXRegSizeInBits - 1)); |
| 2044 set_wregister(rd, alu_out, R31IsZR); | 2054 set_wregister(rd, alu_out, R31IsZR); |
| 2045 } | 2055 } |
| 2046 break; | 2056 break; |
| 2047 } | 2057 } |
| 2048 case 10: { | 2058 case 10: { |
| 2049 // Format(instr, "asr'sf 'rd, 'rn, 'rm"); | 2059 // Format(instr, "asr'sf 'rd, 'rn, 'rm"); |
| 2050 if (instr->SFField() == 1) { | 2060 if (instr->SFField() == 1) { |
| 2051 const int64_t alu_out = rn_val64 >> (rm_val64 & (kXRegSizeInBits - 1)); | 2061 const int64_t alu_out = rn_val64 >> (rm_val64 & (kXRegSizeInBits - 1)); |
| 2052 set_register(rd, alu_out, R31IsZR); | 2062 set_register(instr, rd, alu_out, R31IsZR); |
| 2053 } else { | 2063 } else { |
| 2054 const int32_t alu_out = rn_val32 >> (rm_val32 & (kXRegSizeInBits - 1)); | 2064 const int32_t alu_out = rn_val32 >> (rm_val32 & (kXRegSizeInBits - 1)); |
| 2055 set_wregister(rd, alu_out, R31IsZR); | 2065 set_wregister(rd, alu_out, R31IsZR); |
| 2056 } | 2066 } |
| 2057 break; | 2067 break; |
| 2058 } | 2068 } |
| 2059 default: | 2069 default: |
| 2060 UnimplementedInstruction(instr); | 2070 UnimplementedInstruction(instr); |
| 2061 break; | 2071 break; |
| 2062 } | 2072 } |
| 2063 } | 2073 } |
| 2064 | 2074 |
| 2065 | 2075 |
| 2066 void Simulator::DecodeMiscDP3Source(Instr* instr) { | 2076 void Simulator::DecodeMiscDP3Source(Instr* instr) { |
| 2067 const Register rd = instr->RdField(); | 2077 const Register rd = instr->RdField(); |
| 2068 const Register rn = instr->RnField(); | 2078 const Register rn = instr->RnField(); |
| 2069 const Register rm = instr->RmField(); | 2079 const Register rm = instr->RmField(); |
| 2070 const Register ra = instr->RaField(); | 2080 const Register ra = instr->RaField(); |
| 2071 if ((instr->Bits(29, 2) == 0) && (instr->Bits(21, 3) == 0) && | 2081 if ((instr->Bits(29, 2) == 0) && (instr->Bits(21, 3) == 0) && |
| 2072 (instr->Bit(15) == 0)) { | 2082 (instr->Bit(15) == 0)) { |
| 2073 // Format(instr, "madd'sf 'rd, 'rn, 'rm, 'ra"); | 2083 // Format(instr, "madd'sf 'rd, 'rn, 'rm, 'ra"); |
| 2074 if (instr->SFField() == 1) { | 2084 if (instr->SFField() == 1) { |
| 2075 const int64_t rn_val = get_register(rn, R31IsZR); | 2085 const int64_t rn_val = get_register(rn, R31IsZR); |
| 2076 const int64_t rm_val = get_register(rm, R31IsZR); | 2086 const int64_t rm_val = get_register(rm, R31IsZR); |
| 2077 const int64_t ra_val = get_register(ra, R31IsZR); | 2087 const int64_t ra_val = get_register(ra, R31IsZR); |
| 2078 const int64_t alu_out = ra_val + (rn_val * rm_val); | 2088 const int64_t alu_out = ra_val + (rn_val * rm_val); |
| 2079 set_register(rd, alu_out, R31IsZR); | 2089 set_register(instr, rd, alu_out, R31IsZR); |
| 2080 } else { | 2090 } else { |
| 2081 const int32_t rn_val = get_wregister(rn, R31IsZR); | 2091 const int32_t rn_val = get_wregister(rn, R31IsZR); |
| 2082 const int32_t rm_val = get_wregister(rm, R31IsZR); | 2092 const int32_t rm_val = get_wregister(rm, R31IsZR); |
| 2083 const int32_t ra_val = get_wregister(ra, R31IsZR); | 2093 const int32_t ra_val = get_wregister(ra, R31IsZR); |
| 2084 const int32_t alu_out = ra_val + (rn_val * rm_val); | 2094 const int32_t alu_out = ra_val + (rn_val * rm_val); |
| 2085 set_wregister(rd, alu_out, R31IsZR); | 2095 set_wregister(rd, alu_out, R31IsZR); |
| 2086 } | 2096 } |
| 2087 } else if ((instr->Bits(29, 2) == 0) && (instr->Bits(21, 3) == 0) && | 2097 } else if ((instr->Bits(29, 2) == 0) && (instr->Bits(21, 3) == 0) && |
| 2088 (instr->Bit(15) == 1)) { | 2098 (instr->Bit(15) == 1)) { |
| 2089 // Format(instr, "msub'sf 'rd, 'rn, 'rm, 'ra"); | 2099 // Format(instr, "msub'sf 'rd, 'rn, 'rm, 'ra"); |
| 2090 if (instr->SFField() == 1) { | 2100 if (instr->SFField() == 1) { |
| 2091 const int64_t rn_val = get_register(rn, R31IsZR); | 2101 const int64_t rn_val = get_register(rn, R31IsZR); |
| 2092 const int64_t rm_val = get_register(rm, R31IsZR); | 2102 const int64_t rm_val = get_register(rm, R31IsZR); |
| 2093 const int64_t ra_val = get_register(ra, R31IsZR); | 2103 const int64_t ra_val = get_register(ra, R31IsZR); |
| 2094 const int64_t alu_out = ra_val - (rn_val * rm_val); | 2104 const int64_t alu_out = ra_val - (rn_val * rm_val); |
| 2095 set_register(rd, alu_out, R31IsZR); | 2105 set_register(instr, rd, alu_out, R31IsZR); |
| 2096 } else { | 2106 } else { |
| 2097 const int32_t rn_val = get_wregister(rn, R31IsZR); | 2107 const int32_t rn_val = get_wregister(rn, R31IsZR); |
| 2098 const int32_t rm_val = get_wregister(rm, R31IsZR); | 2108 const int32_t rm_val = get_wregister(rm, R31IsZR); |
| 2099 const int32_t ra_val = get_wregister(ra, R31IsZR); | 2109 const int32_t ra_val = get_wregister(ra, R31IsZR); |
| 2100 const int32_t alu_out = ra_val - (rn_val * rm_val); | 2110 const int32_t alu_out = ra_val - (rn_val * rm_val); |
| 2101 set_wregister(rd, alu_out, R31IsZR); | 2111 set_wregister(rd, alu_out, R31IsZR); |
| 2102 } | 2112 } |
| 2103 } else if ((instr->Bits(29, 2) == 0) && (instr->Bits(21, 3) == 2) && | 2113 } else if ((instr->Bits(29, 2) == 0) && (instr->Bits(21, 3) == 2) && |
| 2104 (instr->Bit(15) == 0)) { | 2114 (instr->Bit(15) == 0)) { |
| 2105 // Format(instr, "smulh 'rd, 'rn, 'rm"); | 2115 // Format(instr, "smulh 'rd, 'rn, 'rm"); |
| 2106 const int64_t rn_val = get_register(rn, R31IsZR); | 2116 const int64_t rn_val = get_register(rn, R31IsZR); |
| 2107 const int64_t rm_val = get_register(rm, R31IsZR); | 2117 const int64_t rm_val = get_register(rm, R31IsZR); |
| 2108 const __int128 res = | 2118 const __int128 res = |
| 2109 static_cast<__int128>(rn_val) * static_cast<__int128>(rm_val); | 2119 static_cast<__int128>(rn_val) * static_cast<__int128>(rm_val); |
| 2110 const int64_t alu_out = static_cast<int64_t>(res >> 64); | 2120 const int64_t alu_out = static_cast<int64_t>(res >> 64); |
| 2111 set_register(rd, alu_out, R31IsZR); | 2121 set_register(instr, rd, alu_out, R31IsZR); |
| 2112 } else { | 2122 } else { |
| 2113 UnimplementedInstruction(instr); | 2123 UnimplementedInstruction(instr); |
| 2114 } | 2124 } |
| 2115 } | 2125 } |
| 2116 | 2126 |
| 2117 | 2127 |
| 2118 void Simulator::DecodeConditionalSelect(Instr* instr) { | 2128 void Simulator::DecodeConditionalSelect(Instr* instr) { |
| 2119 const Register rd = instr->RdField(); | 2129 const Register rd = instr->RdField(); |
| 2120 const Register rn = instr->RnField(); | 2130 const Register rn = instr->RnField(); |
| 2121 const Register rm = instr->RmField(); | 2131 const Register rm = instr->RmField(); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 2149 if (ConditionallyExecute(instr)) { | 2159 if (ConditionallyExecute(instr)) { |
| 2150 result64 = rn_val64; | 2160 result64 = rn_val64; |
| 2151 result32 = rn_val32; | 2161 result32 = rn_val32; |
| 2152 } | 2162 } |
| 2153 } else { | 2163 } else { |
| 2154 UnimplementedInstruction(instr); | 2164 UnimplementedInstruction(instr); |
| 2155 return; | 2165 return; |
| 2156 } | 2166 } |
| 2157 | 2167 |
| 2158 if (instr->SFField() == 1) { | 2168 if (instr->SFField() == 1) { |
| 2159 set_register(rd, result64, instr->RdMode()); | 2169 set_register(instr, rd, result64, instr->RdMode()); |
| 2160 } else { | 2170 } else { |
| 2161 set_wregister(rd, result32, instr->RdMode()); | 2171 set_wregister(rd, result32, instr->RdMode()); |
| 2162 } | 2172 } |
| 2163 } | 2173 } |
| 2164 | 2174 |
| 2165 | 2175 |
| 2166 void Simulator::DecodeDPRegister(Instr* instr) { | 2176 void Simulator::DecodeDPRegister(Instr* instr) { |
| 2167 if (instr->IsAddSubShiftExtOp()) { | 2177 if (instr->IsAddSubShiftExtOp()) { |
| 2168 DecodeAddSubShiftExt(instr); | 2178 DecodeAddSubShiftExt(instr); |
| 2169 } else if (instr->IsLogicalShiftOp()) { | 2179 } else if (instr->IsLogicalShiftOp()) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2214 const VRegister vd = instr->VdField(); | 2224 const VRegister vd = instr->VdField(); |
| 2215 const VRegister vn = instr->VnField(); | 2225 const VRegister vn = instr->VnField(); |
| 2216 const Register rn = instr->RnField(); | 2226 const Register rn = instr->RnField(); |
| 2217 const Register rd = instr->RdField(); | 2227 const Register rd = instr->RdField(); |
| 2218 if ((op == 0) && (imm4 == 7)) { | 2228 if ((op == 0) && (imm4 == 7)) { |
| 2219 if (Q == 0) { | 2229 if (Q == 0) { |
| 2220 // Format(instr, "vmovrs 'rd, 'vn'idx5"); | 2230 // Format(instr, "vmovrs 'rd, 'vn'idx5"); |
| 2221 set_wregister(rd, get_vregisters(vn, idx5), R31IsZR); | 2231 set_wregister(rd, get_vregisters(vn, idx5), R31IsZR); |
| 2222 } else { | 2232 } else { |
| 2223 // Format(instr, "vmovrd 'rd, 'vn'idx5"); | 2233 // Format(instr, "vmovrd 'rd, 'vn'idx5"); |
| 2224 set_register(rd, get_vregisterd(vn, idx5), R31IsZR); | 2234 set_register(instr, rd, get_vregisterd(vn, idx5), R31IsZR); |
| 2225 } | 2235 } |
| 2226 } else if ((Q == 1) && (op == 0) && (imm4 == 0)) { | 2236 } else if ((Q == 1) && (op == 0) && (imm4 == 0)) { |
| 2227 // Format(instr, "vdup'csz 'vd, 'vn'idx5"); | 2237 // Format(instr, "vdup'csz 'vd, 'vn'idx5"); |
| 2228 if (element_bytes == 4) { | 2238 if (element_bytes == 4) { |
| 2229 for (int i = 0; i < 4; i++) { | 2239 for (int i = 0; i < 4; i++) { |
| 2230 set_vregisters(vd, i, get_vregisters(vn, idx5)); | 2240 set_vregisters(vd, i, get_vregisters(vn, idx5)); |
| 2231 } | 2241 } |
| 2232 } else if (element_bytes == 8) { | 2242 } else if (element_bytes == 8) { |
| 2233 for (int i = 0; i < 2; i++) { | 2243 for (int i = 0; i < 2; i++) { |
| 2234 set_vregisterd(vd, i, get_vregisterd(vn, idx5)); | 2244 set_vregisterd(vd, i, get_vregisterd(vn, idx5)); |
| (...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2665 } | 2675 } |
| 2666 if (instr->Bits(16, 5) == 2) { | 2676 if (instr->Bits(16, 5) == 2) { |
| 2667 // Format(instr, "scvtfd 'vd, 'vn"); | 2677 // Format(instr, "scvtfd 'vd, 'vn"); |
| 2668 const int64_t rn_val = get_register(rn, instr->RnMode()); | 2678 const int64_t rn_val = get_register(rn, instr->RnMode()); |
| 2669 const double vn_dbl = static_cast<double>(rn_val); | 2679 const double vn_dbl = static_cast<double>(rn_val); |
| 2670 set_vregisterd(vd, 0, bit_cast<int64_t, double>(vn_dbl)); | 2680 set_vregisterd(vd, 0, bit_cast<int64_t, double>(vn_dbl)); |
| 2671 set_vregisterd(vd, 1, 0); | 2681 set_vregisterd(vd, 1, 0); |
| 2672 } else if (instr->Bits(16, 5) == 6) { | 2682 } else if (instr->Bits(16, 5) == 6) { |
| 2673 // Format(instr, "fmovrd 'rd, 'vn"); | 2683 // Format(instr, "fmovrd 'rd, 'vn"); |
| 2674 const int64_t vn_val = get_vregisterd(vn, 0); | 2684 const int64_t vn_val = get_vregisterd(vn, 0); |
| 2675 set_register(rd, vn_val, R31IsZR); | 2685 set_register(instr, rd, vn_val, R31IsZR); |
| 2676 } else if (instr->Bits(16, 5) == 7) { | 2686 } else if (instr->Bits(16, 5) == 7) { |
| 2677 // Format(instr, "fmovdr 'vd, 'rn"); | 2687 // Format(instr, "fmovdr 'vd, 'rn"); |
| 2678 const int64_t rn_val = get_register(rn, R31IsZR); | 2688 const int64_t rn_val = get_register(rn, R31IsZR); |
| 2679 set_vregisterd(vd, 0, rn_val); | 2689 set_vregisterd(vd, 0, rn_val); |
| 2680 set_vregisterd(vd, 1, 0); | 2690 set_vregisterd(vd, 1, 0); |
| 2681 } else if (instr->Bits(16, 5) == 24) { | 2691 } else if (instr->Bits(16, 5) == 24) { |
| 2682 // Format(instr, "fcvtzds 'rd, 'vn"); | 2692 // Format(instr, "fcvtzds 'rd, 'vn"); |
| 2683 const double vn_val = bit_cast<double, int64_t>(get_vregisterd(vn, 0)); | 2693 const double vn_val = bit_cast<double, int64_t>(get_vregisterd(vn, 0)); |
| 2684 set_register(rd, static_cast<int64_t>(vn_val), instr->RdMode()); | 2694 set_register(instr, rd, static_cast<int64_t>(vn_val), instr->RdMode()); |
| 2685 } else { | 2695 } else { |
| 2686 UnimplementedInstruction(instr); | 2696 UnimplementedInstruction(instr); |
| 2687 } | 2697 } |
| 2688 } | 2698 } |
| 2689 | 2699 |
| 2690 | 2700 |
| 2691 void Simulator::DecodeFPOneSource(Instr* instr) { | 2701 void Simulator::DecodeFPOneSource(Instr* instr) { |
| 2692 const int opc = instr->Bits(15, 6); | 2702 const int opc = instr->Bits(15, 6); |
| 2693 const VRegister vd = instr->VdField(); | 2703 const VRegister vd = instr->VdField(); |
| 2694 const VRegister vn = instr->VnField(); | 2704 const VRegister vn = instr->VnField(); |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2933 if (fp_args) { | 2943 if (fp_args) { |
| 2934 set_vregisterd(V0, 0, parameter0); | 2944 set_vregisterd(V0, 0, parameter0); |
| 2935 set_vregisterd(V0, 1, 0); | 2945 set_vregisterd(V0, 1, 0); |
| 2936 set_vregisterd(V1, 0, parameter1); | 2946 set_vregisterd(V1, 0, parameter1); |
| 2937 set_vregisterd(V1, 1, 0); | 2947 set_vregisterd(V1, 1, 0); |
| 2938 set_vregisterd(V2, 0, parameter2); | 2948 set_vregisterd(V2, 0, parameter2); |
| 2939 set_vregisterd(V2, 1, 0); | 2949 set_vregisterd(V2, 1, 0); |
| 2940 set_vregisterd(V3, 0, parameter3); | 2950 set_vregisterd(V3, 0, parameter3); |
| 2941 set_vregisterd(V3, 1, 0); | 2951 set_vregisterd(V3, 1, 0); |
| 2942 } else { | 2952 } else { |
| 2943 set_register(R0, parameter0); | 2953 set_register(NULL, R0, parameter0); |
| 2944 set_register(R1, parameter1); | 2954 set_register(NULL, R1, parameter1); |
| 2945 set_register(R2, parameter2); | 2955 set_register(NULL, R2, parameter2); |
| 2946 set_register(R3, parameter3); | 2956 set_register(NULL, R3, parameter3); |
| 2947 } | 2957 } |
| 2948 | 2958 |
| 2949 // Make sure the activation frames are properly aligned. | 2959 // Make sure the activation frames are properly aligned. |
| 2950 intptr_t stack_pointer = sp_before_call; | 2960 intptr_t stack_pointer = sp_before_call; |
| 2951 if (OS::ActivationFrameAlignment() > 1) { | 2961 if (OS::ActivationFrameAlignment() > 1) { |
| 2952 stack_pointer = | 2962 stack_pointer = |
| 2953 Utils::RoundDown(stack_pointer, OS::ActivationFrameAlignment()); | 2963 Utils::RoundDown(stack_pointer, OS::ActivationFrameAlignment()); |
| 2954 } | 2964 } |
| 2955 set_register(R31, stack_pointer, R31IsSP); | 2965 set_register(NULL, R31, stack_pointer, R31IsSP); |
| 2956 | 2966 |
| 2957 // Prepare to execute the code at entry. | 2967 // Prepare to execute the code at entry. |
| 2958 set_pc(entry); | 2968 set_pc(entry); |
| 2959 // Put down marker for end of simulation. The simulator will stop simulation | 2969 // Put down marker for end of simulation. The simulator will stop simulation |
| 2960 // when the PC reaches this value. By saving the "end simulation" value into | 2970 // when the PC reaches this value. By saving the "end simulation" value into |
| 2961 // the LR the simulation stops when returning to this call point. | 2971 // the LR the simulation stops when returning to this call point. |
| 2962 set_register(LR, kEndSimulatingPC); | 2972 set_register(NULL, LR, kEndSimulatingPC); |
| 2963 | 2973 |
| 2964 // Remember the values of callee-saved registers, and set them up with a | 2974 // Remember the values of callee-saved registers, and set them up with a |
| 2965 // known value so that we are able to check that they are preserved | 2975 // known value so that we are able to check that they are preserved |
| 2966 // properly across Dart execution. | 2976 // properly across Dart execution. |
| 2967 int64_t preserved_vals[kAbiPreservedCpuRegCount]; | 2977 int64_t preserved_vals[kAbiPreservedCpuRegCount]; |
| 2968 const double dicount = static_cast<double>(icount_); | 2978 const double dicount = static_cast<double>(icount_); |
| 2969 const int64_t callee_saved_value = bit_cast<int64_t, double>(dicount); | 2979 const int64_t callee_saved_value = bit_cast<int64_t, double>(dicount); |
| 2970 for (int i = kAbiFirstPreservedCpuReg; i <= kAbiLastPreservedCpuReg; i++) { | 2980 for (int i = kAbiFirstPreservedCpuReg; i <= kAbiLastPreservedCpuReg; i++) { |
| 2971 const Register r = static_cast<Register>(i); | 2981 const Register r = static_cast<Register>(i); |
| 2972 preserved_vals[i - kAbiFirstPreservedCpuReg] = get_register(r); | 2982 preserved_vals[i - kAbiFirstPreservedCpuReg] = get_register(r); |
| 2973 set_register(r, callee_saved_value); | 2983 set_register(NULL, r, callee_saved_value); |
| 2974 } | 2984 } |
| 2975 | 2985 |
| 2976 // Only the bottom half of the V registers must be preserved. | 2986 // Only the bottom half of the V registers must be preserved. |
| 2977 int64_t preserved_dvals[kAbiPreservedFpuRegCount]; | 2987 int64_t preserved_dvals[kAbiPreservedFpuRegCount]; |
| 2978 for (int i = kAbiFirstPreservedFpuReg; i <= kAbiLastPreservedFpuReg; i++) { | 2988 for (int i = kAbiFirstPreservedFpuReg; i <= kAbiLastPreservedFpuReg; i++) { |
| 2979 const VRegister r = static_cast<VRegister>(i); | 2989 const VRegister r = static_cast<VRegister>(i); |
| 2980 preserved_dvals[i - kAbiFirstPreservedFpuReg] = get_vregisterd(r, 0); | 2990 preserved_dvals[i - kAbiFirstPreservedFpuReg] = get_vregisterd(r, 0); |
| 2981 set_vregisterd(r, 0, callee_saved_value); | 2991 set_vregisterd(r, 0, callee_saved_value); |
| 2982 set_vregisterd(r, 1, 0); | 2992 set_vregisterd(r, 1, 0); |
| 2983 } | 2993 } |
| 2984 | 2994 |
| 2985 // Start the simulation. | 2995 // Start the simulation. |
| 2986 Execute(); | 2996 Execute(); |
| 2987 | 2997 |
| 2988 // Check that the callee-saved registers have been preserved, | 2998 // Check that the callee-saved registers have been preserved, |
| 2989 // and restore them with the original value. | 2999 // and restore them with the original value. |
| 2990 for (int i = kAbiFirstPreservedCpuReg; i <= kAbiLastPreservedCpuReg; i++) { | 3000 for (int i = kAbiFirstPreservedCpuReg; i <= kAbiLastPreservedCpuReg; i++) { |
| 2991 const Register r = static_cast<Register>(i); | 3001 const Register r = static_cast<Register>(i); |
| 2992 ASSERT(callee_saved_value == get_register(r)); | 3002 ASSERT(callee_saved_value == get_register(r)); |
| 2993 set_register(r, preserved_vals[i - kAbiFirstPreservedCpuReg]); | 3003 set_register(NULL, r, preserved_vals[i - kAbiFirstPreservedCpuReg]); |
| 2994 } | 3004 } |
| 2995 | 3005 |
| 2996 for (int i = kAbiFirstPreservedFpuReg; i <= kAbiLastPreservedFpuReg; i++) { | 3006 for (int i = kAbiFirstPreservedFpuReg; i <= kAbiLastPreservedFpuReg; i++) { |
| 2997 const VRegister r = static_cast<VRegister>(i); | 3007 const VRegister r = static_cast<VRegister>(i); |
| 2998 ASSERT(callee_saved_value == get_vregisterd(r, 0)); | 3008 ASSERT(callee_saved_value == get_vregisterd(r, 0)); |
| 2999 set_vregisterd(r, 0, preserved_dvals[i - kAbiFirstPreservedFpuReg]); | 3009 set_vregisterd(r, 0, preserved_dvals[i - kAbiFirstPreservedFpuReg]); |
| 3000 set_vregisterd(r, 1, 0); | 3010 set_vregisterd(r, 1, 0); |
| 3001 } | 3011 } |
| 3002 | 3012 |
| 3003 // Restore the SP register and return R0. | 3013 // Restore the SP register and return R0. |
| 3004 set_register(R31, sp_before_call, R31IsSP); | 3014 set_register(NULL, R31, sp_before_call, R31IsSP); |
| 3005 int64_t return_value; | 3015 int64_t return_value; |
| 3006 if (fp_return) { | 3016 if (fp_return) { |
| 3007 return_value = get_vregisterd(V0, 0); | 3017 return_value = get_vregisterd(V0, 0); |
| 3008 } else { | 3018 } else { |
| 3009 return_value = get_register(R0); | 3019 return_value = get_register(R0); |
| 3010 } | 3020 } |
| 3011 return return_value; | 3021 return return_value; |
| 3012 } | 3022 } |
| 3013 | 3023 |
| 3014 | 3024 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 3030 // in the previous C++ frames. | 3040 // in the previous C++ frames. |
| 3031 uword native_sp = buf->native_sp(); | 3041 uword native_sp = buf->native_sp(); |
| 3032 Isolate* isolate = Isolate::Current(); | 3042 Isolate* isolate = Isolate::Current(); |
| 3033 while (isolate->top_resource() != NULL && | 3043 while (isolate->top_resource() != NULL && |
| 3034 (reinterpret_cast<uword>(isolate->top_resource()) < native_sp)) { | 3044 (reinterpret_cast<uword>(isolate->top_resource()) < native_sp)) { |
| 3035 isolate->top_resource()->~StackResource(); | 3045 isolate->top_resource()->~StackResource(); |
| 3036 } | 3046 } |
| 3037 | 3047 |
| 3038 // Unwind the C++ stack and continue simulation in the target frame. | 3048 // Unwind the C++ stack and continue simulation in the target frame. |
| 3039 set_pc(static_cast<int64_t>(pc)); | 3049 set_pc(static_cast<int64_t>(pc)); |
| 3040 set_register(R31, static_cast<int64_t>(sp), R31IsSP); | 3050 set_register(NULL, SP, static_cast<int64_t>(sp)); |
| 3041 set_register(FP, static_cast<int64_t>(fp)); | 3051 set_register(NULL, FP, static_cast<int64_t>(fp)); |
| 3042 | 3052 |
| 3043 ASSERT(raw_exception != Object::null()); | 3053 ASSERT(raw_exception != Object::null()); |
| 3044 set_register(kExceptionObjectReg, bit_cast<int64_t>(raw_exception)); | 3054 set_register(NULL, kExceptionObjectReg, bit_cast<int64_t>(raw_exception)); |
| 3045 set_register(kStackTraceObjectReg, bit_cast<int64_t>(raw_stacktrace)); | 3055 set_register(NULL, kStackTraceObjectReg, bit_cast<int64_t>(raw_stacktrace)); |
| 3046 buf->Longjmp(); | 3056 buf->Longjmp(); |
| 3047 } | 3057 } |
| 3048 | 3058 |
| 3049 } // namespace dart | 3059 } // namespace dart |
| 3050 | 3060 |
| 3051 #endif // !defined(HOST_ARCH_ARM64) | 3061 #endif // !defined(HOST_ARCH_ARM64) |
| 3052 | 3062 |
| 3053 #endif // defined TARGET_ARCH_ARM64 | 3063 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |