Index: runtime/vm/simulator_arm64.cc |
=================================================================== |
--- runtime/vm/simulator_arm64.cc (revision 36919) |
+++ runtime/vm/simulator_arm64.cc (working copy) |
@@ -663,11 +663,22 @@ |
// Sets the register in the architecture state. |
-void Simulator::set_register(Register reg, int64_t value, R31Type r31t) { |
- // register is in range, and if it is R31, a mode is specified. |
+void Simulator::set_register( |
+ Instr* instr, Register reg, int64_t value, R31Type r31t) { |
+ // Register is in range. |
ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); |
if ((reg != R31) || (r31t != R31IsZR)) { |
registers_[reg] = value; |
+ // If we're setting CSP, make sure it is 16-byte aligned. In truth, CSP |
+ // can store addresses that are not 16-byte aligned, but loads and stores |
+ // are not allowed through CSP when it is not aligned. Thus, this check is |
+ // more conservative that necessary. However, it will likely be more |
+ // useful to find the program locations where CSP is set to a bad value, |
+ // than to find only the resulting loads/stores that would cause a fault on |
+ // hardware. |
+ if ((instr != NULL) && (reg == R31) && !Utils::IsAligned(value, 16)) { |
+ UnalignedAccess("CSP set", value, instr); |
+ } |
} |
} |
@@ -1034,15 +1045,15 @@ |
if (instr->SFField()) { |
if (instr->Bits(29, 2) == 0) { |
// Format(instr, "movn'sf 'rd, 'imm16 'hw"); |
- set_register(rd, ~shifted_imm, instr->RdMode()); |
+ set_register(instr, rd, ~shifted_imm, instr->RdMode()); |
} else if (instr->Bits(29, 2) == 2) { |
// Format(instr, "movz'sf 'rd, 'imm16 'hw"); |
- set_register(rd, shifted_imm, instr->RdMode()); |
+ set_register(instr, rd, shifted_imm, instr->RdMode()); |
} else if (instr->Bits(29, 2) == 3) { |
// Format(instr, "movk'sf 'rd, 'imm16 'hw"); |
const int64_t rd_val = get_register(rd, instr->RdMode()); |
const int64_t result = (rd_val & ~(0xffffL << shift)) | shifted_imm; |
- set_register(rd, result, instr->RdMode()); |
+ set_register(instr, rd, result, instr->RdMode()); |
} else { |
UnimplementedInstruction(instr); |
} |
@@ -1080,7 +1091,7 @@ |
// 64-bit add. |
const int64_t rn_val = get_register(rn, instr->RnMode()); |
const int64_t alu_out = addition ? (rn_val + imm) : (rn_val - imm); |
- set_register(rd, alu_out, instr->RdMode()); |
+ set_register(instr, rd, alu_out, instr->RdMode()); |
if (instr->HasS()) { |
SetNZFlagsX(alu_out); |
if (addition) { |
@@ -1151,7 +1162,7 @@ |
} |
if (out_size == kXRegSizeInBits) { |
- set_register(rd, alu_out, instr->RdMode()); |
+ set_register(instr, rd, alu_out, instr->RdMode()); |
} else { |
set_wregister(rd, alu_out, instr->RdMode()); |
} |
@@ -1167,7 +1178,7 @@ |
const int64_t immlo = instr->Bits(29, 2); |
const int64_t off = (immhi << 2) | immlo; |
const int64_t dest = get_pc() + off; |
- set_register(rd, dest, instr->RdMode()); |
+ set_register(instr, rd, dest, instr->RdMode()); |
} else { |
UnimplementedInstruction(instr); |
} |
@@ -1287,17 +1298,14 @@ |
set_top_exit_frame_info(reinterpret_cast<uword>(&buffer)); |
} |
if (redirection->call_kind() == kRuntimeCall) { |
- NativeArguments arguments; |
- ASSERT(sizeof(NativeArguments) == 4*kWordSize); |
- arguments.isolate_ = reinterpret_cast<Isolate*>(get_register(R0)); |
- arguments.argc_tag_ = get_register(R1); |
- arguments.argv_ = reinterpret_cast<RawObject*(*)[]>(get_register(R2)); |
- arguments.retval_ = reinterpret_cast<RawObject**>(get_register(R3)); |
+ NativeArguments* arguments = |
+ reinterpret_cast<NativeArguments*>(get_register(R0)); |
SimulatorRuntimeCall target = |
reinterpret_cast<SimulatorRuntimeCall>(external); |
- target(arguments); |
- set_register(R0, icount_); // Zap result register from void function. |
- set_register(R1, icount_); |
+ target(*arguments); |
+ // Zap result register from void function. |
+ set_register(instr, R0, icount_); |
+ set_register(instr, R1, icount_); |
} else if (redirection->call_kind() == kLeafRuntimeCall) { |
ASSERT((0 <= redirection->argument_count()) && |
(redirection->argument_count() <= 8)); |
@@ -1312,8 +1320,8 @@ |
const int64_t r6 = get_register(R6); |
const int64_t r7 = get_register(R7); |
const int64_t res = target(r0, r1, r2, r3, r4, r5, r6, r7); |
- set_register(R0, res); // Set returned result from function. |
- set_register(R1, icount_); // Zap unused result register. |
+ set_register(instr, R0, res); // Set returned result from function. |
+ set_register(instr, R1, icount_); // Zap unused result register. |
} else if (redirection->call_kind() == kLeafFloatRuntimeCall) { |
ASSERT((0 <= redirection->argument_count()) && |
(redirection->argument_count() <= 8)); |
@@ -1336,7 +1344,8 @@ |
SimulatorBootstrapNativeCall target = |
reinterpret_cast<SimulatorBootstrapNativeCall>(external); |
target(arguments); |
- set_register(R0, icount_); // Zap result register from void function. |
+ // Zap result register from void function. |
+ set_register(instr, R0, icount_); |
} else { |
ASSERT(redirection->call_kind() == kNativeCall); |
NativeArguments* arguments; |
@@ -1345,31 +1354,32 @@ |
SimulatorNativeCall target = |
reinterpret_cast<SimulatorNativeCall>(external); |
target(arguments, target_func); |
- set_register(R0, icount_); // Zap result register from void function. |
- set_register(R1, icount_); |
+ // Zap result register from void function. |
+ set_register(instr, R0, icount_); |
+ set_register(instr, R1, icount_); |
} |
set_top_exit_frame_info(0); |
// Zap caller-saved registers, since the actual runtime call could have |
// used them. |
- set_register(R2, icount_); |
- set_register(R3, icount_); |
- set_register(R4, icount_); |
- set_register(R5, icount_); |
- set_register(R6, icount_); |
- set_register(R7, icount_); |
- set_register(R8, icount_); |
- set_register(R9, icount_); |
- set_register(R10, icount_); |
- set_register(R11, icount_); |
- set_register(R12, icount_); |
- set_register(R13, icount_); |
- set_register(R14, icount_); |
- set_register(R15, icount_); |
- set_register(IP0, icount_); |
- set_register(IP1, icount_); |
- set_register(R18, icount_); |
- set_register(LR, icount_); |
+ set_register(instr, R2, icount_); |
+ set_register(instr, R3, icount_); |
+ set_register(instr, R4, icount_); |
+ set_register(instr, R5, icount_); |
+ set_register(instr, R6, icount_); |
+ set_register(instr, R7, icount_); |
+ set_register(instr, R8, icount_); |
+ set_register(instr, R9, icount_); |
+ set_register(instr, R10, icount_); |
+ set_register(instr, R11, icount_); |
+ set_register(instr, R12, icount_); |
+ set_register(instr, R13, icount_); |
+ set_register(instr, R14, icount_); |
+ set_register(instr, R15, icount_); |
+ set_register(instr, IP0, icount_); |
+ set_register(instr, IP1, icount_); |
+ set_register(instr, R18, icount_); |
+ set_register(instr, LR, icount_); |
// TODO(zra): Zap caller-saved fpu registers. |
@@ -1457,7 +1467,7 @@ |
const int64_t ret = get_pc() + Instr::kInstrSize; |
set_pc(dest); |
if (link) { |
- set_register(LR, ret); |
+ set_register(instr, LR, ret); |
} |
} |
@@ -1479,7 +1489,7 @@ |
const int64_t dest = get_register(rn, instr->RnMode()); |
const int64_t ret = get_pc() + Instr::kInstrSize; |
set_pc(dest); |
- set_register(LR, ret); |
+ set_register(instr, LR, ret); |
break; |
} |
case 2: { |
@@ -1703,14 +1713,14 @@ |
if (use_w) { |
set_wregister(rt, static_cast<int32_t>(val), R31IsZR); |
} else { |
- set_register(rt, val, R31IsZR); |
+ set_register(instr, rt, val, R31IsZR); |
} |
} |
} |
// Do writeback. |
if (wb) { |
- set_register(rn, wb_address, R31IsSP); |
+ set_register(instr, rn, wb_address, R31IsSP); |
} |
} |
@@ -1728,7 +1738,7 @@ |
const int64_t val = ReadX(address, instr); |
if (instr->Bit(30)) { |
// Format(instr, "ldrx 'rt, 'pcldr"); |
- set_register(rt, val, R31IsZR); |
+ set_register(instr, rt, val, R31IsZR); |
} else { |
// Format(instr, "ldrw 'rt, 'pcldr"); |
set_wregister(rt, static_cast<int32_t>(val), R31IsZR); |
@@ -1851,7 +1861,7 @@ |
} else { |
alu_out = rn_val + rm_val; |
} |
- set_register(rd, alu_out, instr->RdMode()); |
+ set_register(instr, rd, alu_out, instr->RdMode()); |
if (instr->HasS()) { |
SetNZFlagsX(alu_out); |
if (subtract) { |
@@ -1942,7 +1952,7 @@ |
} |
if (instr->SFField() == 1) { |
- set_register(rd, alu_out, instr->RdMode()); |
+ set_register(instr, rd, alu_out, instr->RdMode()); |
} else { |
set_wregister(rd, alu_out & kWRegMask, instr->RdMode()); |
} |
@@ -2015,7 +2025,7 @@ |
// Format(instr, "sdiv'sf 'rd, 'rn, 'rm"); |
const bool signd = instr->Bit(10) == 1; |
if (instr->SFField() == 1) { |
- set_register(rd, divide64(rn_val64, rm_val64, signd), R31IsZR); |
+ set_register(instr, rd, divide64(rn_val64, rm_val64, signd), R31IsZR); |
} else { |
set_wregister(rd, divide32(rn_val32, rm_val32, signd), R31IsZR); |
} |
@@ -2025,7 +2035,7 @@ |
// Format(instr, "lsl'sf 'rd, 'rn, 'rm"); |
if (instr->SFField() == 1) { |
const int64_t alu_out = rn_val64 << (rm_val64 & (kXRegSizeInBits - 1)); |
- set_register(rd, alu_out, R31IsZR); |
+ set_register(instr, rd, alu_out, R31IsZR); |
} else { |
const int32_t alu_out = rn_val32 << (rm_val32 & (kXRegSizeInBits - 1)); |
set_wregister(rd, alu_out, R31IsZR); |
@@ -2037,7 +2047,7 @@ |
if (instr->SFField() == 1) { |
const uint64_t rn_u64 = static_cast<uint64_t>(rn_val64); |
const int64_t alu_out = rn_u64 >> (rm_val64 & (kXRegSizeInBits - 1)); |
- set_register(rd, alu_out, R31IsZR); |
+ set_register(instr, rd, alu_out, R31IsZR); |
} else { |
const uint32_t rn_u32 = static_cast<uint32_t>(rn_val32); |
const int32_t alu_out = rn_u32 >> (rm_val32 & (kXRegSizeInBits - 1)); |
@@ -2049,7 +2059,7 @@ |
// Format(instr, "asr'sf 'rd, 'rn, 'rm"); |
if (instr->SFField() == 1) { |
const int64_t alu_out = rn_val64 >> (rm_val64 & (kXRegSizeInBits - 1)); |
- set_register(rd, alu_out, R31IsZR); |
+ set_register(instr, rd, alu_out, R31IsZR); |
} else { |
const int32_t alu_out = rn_val32 >> (rm_val32 & (kXRegSizeInBits - 1)); |
set_wregister(rd, alu_out, R31IsZR); |
@@ -2076,7 +2086,7 @@ |
const int64_t rm_val = get_register(rm, R31IsZR); |
const int64_t ra_val = get_register(ra, R31IsZR); |
const int64_t alu_out = ra_val + (rn_val * rm_val); |
- set_register(rd, alu_out, R31IsZR); |
+ set_register(instr, rd, alu_out, R31IsZR); |
} else { |
const int32_t rn_val = get_wregister(rn, R31IsZR); |
const int32_t rm_val = get_wregister(rm, R31IsZR); |
@@ -2092,7 +2102,7 @@ |
const int64_t rm_val = get_register(rm, R31IsZR); |
const int64_t ra_val = get_register(ra, R31IsZR); |
const int64_t alu_out = ra_val - (rn_val * rm_val); |
- set_register(rd, alu_out, R31IsZR); |
+ set_register(instr, rd, alu_out, R31IsZR); |
} else { |
const int32_t rn_val = get_wregister(rn, R31IsZR); |
const int32_t rm_val = get_wregister(rm, R31IsZR); |
@@ -2108,7 +2118,7 @@ |
const __int128 res = |
static_cast<__int128>(rn_val) * static_cast<__int128>(rm_val); |
const int64_t alu_out = static_cast<int64_t>(res >> 64); |
- set_register(rd, alu_out, R31IsZR); |
+ set_register(instr, rd, alu_out, R31IsZR); |
} else { |
UnimplementedInstruction(instr); |
} |
@@ -2156,7 +2166,7 @@ |
} |
if (instr->SFField() == 1) { |
- set_register(rd, result64, instr->RdMode()); |
+ set_register(instr, rd, result64, instr->RdMode()); |
} else { |
set_wregister(rd, result32, instr->RdMode()); |
} |
@@ -2221,7 +2231,7 @@ |
set_wregister(rd, get_vregisters(vn, idx5), R31IsZR); |
} else { |
// Format(instr, "vmovrd 'rd, 'vn'idx5"); |
- set_register(rd, get_vregisterd(vn, idx5), R31IsZR); |
+ set_register(instr, rd, get_vregisterd(vn, idx5), R31IsZR); |
} |
} else if ((Q == 1) && (op == 0) && (imm4 == 0)) { |
// Format(instr, "vdup'csz 'vd, 'vn'idx5"); |
@@ -2672,7 +2682,7 @@ |
} else if (instr->Bits(16, 5) == 6) { |
// Format(instr, "fmovrd 'rd, 'vn"); |
const int64_t vn_val = get_vregisterd(vn, 0); |
- set_register(rd, vn_val, R31IsZR); |
+ set_register(instr, rd, vn_val, R31IsZR); |
} else if (instr->Bits(16, 5) == 7) { |
// Format(instr, "fmovdr 'vd, 'rn"); |
const int64_t rn_val = get_register(rn, R31IsZR); |
@@ -2681,7 +2691,7 @@ |
} else if (instr->Bits(16, 5) == 24) { |
// Format(instr, "fcvtzds 'rd, 'vn"); |
const double vn_val = bit_cast<double, int64_t>(get_vregisterd(vn, 0)); |
- set_register(rd, static_cast<int64_t>(vn_val), instr->RdMode()); |
+ set_register(instr, rd, static_cast<int64_t>(vn_val), instr->RdMode()); |
} else { |
UnimplementedInstruction(instr); |
} |
@@ -2940,10 +2950,10 @@ |
set_vregisterd(V3, 0, parameter3); |
set_vregisterd(V3, 1, 0); |
} else { |
- set_register(R0, parameter0); |
- set_register(R1, parameter1); |
- set_register(R2, parameter2); |
- set_register(R3, parameter3); |
+ set_register(NULL, R0, parameter0); |
+ set_register(NULL, R1, parameter1); |
+ set_register(NULL, R2, parameter2); |
+ set_register(NULL, R3, parameter3); |
} |
// Make sure the activation frames are properly aligned. |
@@ -2952,14 +2962,14 @@ |
stack_pointer = |
Utils::RoundDown(stack_pointer, OS::ActivationFrameAlignment()); |
} |
- set_register(R31, stack_pointer, R31IsSP); |
+ set_register(NULL, R31, stack_pointer, R31IsSP); |
// Prepare to execute the code at entry. |
set_pc(entry); |
// Put down marker for end of simulation. The simulator will stop simulation |
// when the PC reaches this value. By saving the "end simulation" value into |
// the LR the simulation stops when returning to this call point. |
- set_register(LR, kEndSimulatingPC); |
+ set_register(NULL, LR, kEndSimulatingPC); |
// Remember the values of callee-saved registers, and set them up with a |
// known value so that we are able to check that they are preserved |
@@ -2970,7 +2980,7 @@ |
for (int i = kAbiFirstPreservedCpuReg; i <= kAbiLastPreservedCpuReg; i++) { |
const Register r = static_cast<Register>(i); |
preserved_vals[i - kAbiFirstPreservedCpuReg] = get_register(r); |
- set_register(r, callee_saved_value); |
+ set_register(NULL, r, callee_saved_value); |
} |
// Only the bottom half of the V registers must be preserved. |
@@ -2990,7 +3000,7 @@ |
for (int i = kAbiFirstPreservedCpuReg; i <= kAbiLastPreservedCpuReg; i++) { |
const Register r = static_cast<Register>(i); |
ASSERT(callee_saved_value == get_register(r)); |
- set_register(r, preserved_vals[i - kAbiFirstPreservedCpuReg]); |
+ set_register(NULL, r, preserved_vals[i - kAbiFirstPreservedCpuReg]); |
} |
for (int i = kAbiFirstPreservedFpuReg; i <= kAbiLastPreservedFpuReg; i++) { |
@@ -3001,7 +3011,7 @@ |
} |
// Restore the SP register and return R0. |
- set_register(R31, sp_before_call, R31IsSP); |
+ set_register(NULL, R31, sp_before_call, R31IsSP); |
int64_t return_value; |
if (fp_return) { |
return_value = get_vregisterd(V0, 0); |
@@ -3037,12 +3047,12 @@ |
// Unwind the C++ stack and continue simulation in the target frame. |
set_pc(static_cast<int64_t>(pc)); |
- set_register(R31, static_cast<int64_t>(sp), R31IsSP); |
- set_register(FP, static_cast<int64_t>(fp)); |
+ set_register(NULL, SP, static_cast<int64_t>(sp)); |
+ set_register(NULL, FP, static_cast<int64_t>(fp)); |
ASSERT(raw_exception != Object::null()); |
- set_register(kExceptionObjectReg, bit_cast<int64_t>(raw_exception)); |
- set_register(kStackTraceObjectReg, bit_cast<int64_t>(raw_stacktrace)); |
+ set_register(NULL, kExceptionObjectReg, bit_cast<int64_t>(raw_exception)); |
+ set_register(NULL, kStackTraceObjectReg, bit_cast<int64_t>(raw_stacktrace)); |
buf->Longjmp(); |
} |