From ba9d61ac960eb58ded51d762ae0db58ce75cc075 Mon Sep 17 00:00:00 2001 From: Vyacheslav Egorov Date: Tue, 15 Oct 2019 08:50:52 +0000 Subject: [PATCH] [vm] Allow unaligned accesses by default in SIMARM64 ARMv8 ISA supports unaligned accesses (though a strict alignment checking can be enabled). Change-Id: I1f72d5f73934ba29b8436b5ed0f56a8dcd5a56ed Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/121623 Auto-Submit: Vyacheslav Egorov Reviewed-by: Aart Bik Commit-Queue: Vyacheslav Egorov --- runtime/vm/simulator_arm64.cc | 44 +++++++++++++++++++++++------------ runtime/vm/simulator_arm64.h | 6 +++-- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc index efc5e89c5d3..235a2961921 100644 --- a/runtime/vm/simulator_arm64.cc +++ b/runtime/vm/simulator_arm64.cc @@ -31,6 +31,11 @@ DEFINE_FLAG(uint64_t, ULLONG_MAX, "Instruction address or instruction count to stop simulator at."); +DEFINE_FLAG(bool, + sim_allow_unaligned_accesses, + true, + "Allow unaligned accesses to Normal memory."); + // This macro provides a platform independent use of sscanf. The reason for // SScanF not being implemented in a platform independent way through // OS in the same way as SNPrint is that the Windows C Run-Time @@ -999,9 +1004,10 @@ void Simulator::HandleIllegalAccess(uword addr, Instr* instr) { FATAL("Cannot continue execution after illegal memory access."); } -// The ARMv8 manual advises that an unaligned access may generate a fault, -// and if not, will likely take a number of additional cycles to execute, -// so let's just not generate any. +// ARMv8 supports unaligned memory accesses to normal memory without trapping +// for all instructions except Load-Exclusive/Store-Exclusive and +// Load-Acquire/Store-Release. +// See B2.4.2 "Alignment of data accesses" for more information. void Simulator::UnalignedAccess(const char* msg, uword addr, Instr* instr) { char buffer[128]; snprintf(buffer, sizeof(buffer), "unaligned %s at 0x%" Px ", pc=%p\n", msg, @@ -1027,8 +1033,12 @@ bool Simulator::IsTracingExecution() const { return icount_ > FLAG_trace_sim_after; } -intptr_t Simulator::ReadX(uword addr, Instr* instr) { - if ((addr & 7) == 0) { +intptr_t Simulator::ReadX(uword addr, + Instr* instr, + bool must_be_aligned /* = false */) { + const bool allow_unaligned_access = + FLAG_sim_allow_unaligned_accesses && !must_be_aligned; + if (allow_unaligned_access || (addr & 7) == 0) { intptr_t* ptr = reinterpret_cast(addr); return *ptr; } @@ -1037,7 +1047,7 @@ intptr_t Simulator::ReadX(uword addr, Instr* instr) { } void Simulator::WriteX(uword addr, intptr_t value, Instr* instr) { - if ((addr & 7) == 0) { + if (FLAG_sim_allow_unaligned_accesses || (addr & 7) == 0) { intptr_t* ptr = reinterpret_cast(addr); *ptr = value; return; @@ -1045,8 +1055,12 @@ void Simulator::WriteX(uword addr, intptr_t value, Instr* instr) { UnalignedAccess("write", addr, instr); } -uint32_t Simulator::ReadWU(uword addr, Instr* instr) { - if ((addr & 3) == 0) { +uint32_t Simulator::ReadWU(uword addr, + Instr* instr, + bool must_be_aligned /* = false */) { + const bool allow_unaligned_access = + FLAG_sim_allow_unaligned_accesses && !must_be_aligned; + if (allow_unaligned_access || (addr & 3) == 0) { uint32_t* ptr = reinterpret_cast(addr); return *ptr; } @@ -1055,7 +1069,7 @@ uint32_t Simulator::ReadWU(uword addr, Instr* instr) { } int32_t Simulator::ReadW(uword addr, Instr* instr) { - if ((addr & 3) == 0) { + if (FLAG_sim_allow_unaligned_accesses || (addr & 3) == 0) { int32_t* ptr = reinterpret_cast(addr); return *ptr; } @@ -1064,7 +1078,7 @@ int32_t Simulator::ReadW(uword addr, Instr* instr) { } void Simulator::WriteW(uword addr, uint32_t value, Instr* instr) { - if ((addr & 3) == 0) { + if (FLAG_sim_allow_unaligned_accesses || (addr & 3) == 0) { uint32_t* ptr = reinterpret_cast(addr); *ptr = value; return; @@ -1073,7 +1087,7 @@ void Simulator::WriteW(uword addr, uint32_t value, Instr* instr) { } uint16_t Simulator::ReadHU(uword addr, Instr* instr) { - if ((addr & 1) == 0) { + if (FLAG_sim_allow_unaligned_accesses || (addr & 1) == 0) { uint16_t* ptr = reinterpret_cast(addr); return *ptr; } @@ -1082,7 +1096,7 @@ uint16_t Simulator::ReadHU(uword addr, Instr* instr) { } int16_t Simulator::ReadH(uword addr, Instr* instr) { - if ((addr & 1) == 0) { + if (FLAG_sim_allow_unaligned_accesses || (addr & 1) == 0) { int16_t* ptr = reinterpret_cast(addr); return *ptr; } @@ -1091,7 +1105,7 @@ int16_t Simulator::ReadH(uword addr, Instr* instr) { } void Simulator::WriteH(uword addr, uint16_t value, Instr* instr) { - if ((addr & 1) == 0) { + if (FLAG_sim_allow_unaligned_accesses || (addr & 1) == 0) { uint16_t* ptr = reinterpret_cast(addr); *ptr = value; return; @@ -1121,13 +1135,13 @@ void Simulator::ClearExclusive() { intptr_t Simulator::ReadExclusiveX(uword addr, Instr* instr) { exclusive_access_addr_ = addr; - exclusive_access_value_ = ReadX(addr, instr); + exclusive_access_value_ = ReadX(addr, instr, /*must_be_aligned=*/true); return exclusive_access_value_; } intptr_t Simulator::ReadExclusiveW(uword addr, Instr* instr) { exclusive_access_addr_ = addr; - exclusive_access_value_ = ReadWU(addr, instr); + exclusive_access_value_ = ReadWU(addr, instr, /*must_be_aligned=*/true); return exclusive_access_value_; } diff --git a/runtime/vm/simulator_arm64.h b/runtime/vm/simulator_arm64.h index 8a484511c60..6663e327dc9 100644 --- a/runtime/vm/simulator_arm64.h +++ b/runtime/vm/simulator_arm64.h @@ -170,11 +170,13 @@ class Simulator { inline int16_t ReadH(uword addr, Instr* instr); inline void WriteH(uword addr, uint16_t value, Instr* instr); - inline uint32_t ReadWU(uword addr, Instr* instr); + inline uint32_t ReadWU(uword addr, + Instr* instr, + bool must_be_aligned = false); inline int32_t ReadW(uword addr, Instr* instr); inline void WriteW(uword addr, uint32_t value, Instr* instr); - inline intptr_t ReadX(uword addr, Instr* instr); + inline intptr_t ReadX(uword addr, Instr* instr, bool must_be_aligned = false); inline void WriteX(uword addr, intptr_t value, Instr* instr); // Synchronization primitives support.