@@ -31,6 +31,11 @@ DEFINE_FLAG(uint64_t,
3131 ULLONG_MAX,
3232 " Instruction address or instruction count to stop simulator at." );
3333
34+ DEFINE_FLAG (bool ,
35+ sim_allow_unaligned_accesses,
36+ true ,
37+ " Allow unaligned accesses to Normal memory." );
38+
3439// This macro provides a platform independent use of sscanf. The reason for
3540// SScanF not being implemented in a platform independent way through
3641// 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) {
9991004 FATAL (" Cannot continue execution after illegal memory access." );
10001005}
10011006
1002- // The ARMv8 manual advises that an unaligned access may generate a fault,
1003- // and if not, will likely take a number of additional cycles to execute,
1004- // so let's just not generate any.
1007+ // ARMv8 supports unaligned memory accesses to normal memory without trapping
1008+ // for all instructions except Load-Exclusive/Store-Exclusive and
1009+ // Load-Acquire/Store-Release.
1010+ // See B2.4.2 "Alignment of data accesses" for more information.
10051011void Simulator::UnalignedAccess (const char * msg, uword addr, Instr* instr) {
10061012 char buffer[128 ];
10071013 snprintf (buffer, sizeof (buffer), " unaligned %s at 0x%" Px " , pc=%p\n " , msg,
@@ -1027,8 +1033,12 @@ bool Simulator::IsTracingExecution() const {
10271033 return icount_ > FLAG_trace_sim_after;
10281034}
10291035
1030- intptr_t Simulator::ReadX (uword addr, Instr* instr) {
1031- if ((addr & 7 ) == 0 ) {
1036+ intptr_t Simulator::ReadX (uword addr,
1037+ Instr* instr,
1038+ bool must_be_aligned /* = false */ ) {
1039+ const bool allow_unaligned_access =
1040+ FLAG_sim_allow_unaligned_accesses && !must_be_aligned;
1041+ if (allow_unaligned_access || (addr & 7 ) == 0 ) {
10321042 intptr_t * ptr = reinterpret_cast <intptr_t *>(addr);
10331043 return *ptr;
10341044 }
@@ -1037,16 +1047,20 @@ intptr_t Simulator::ReadX(uword addr, Instr* instr) {
10371047}
10381048
10391049void Simulator::WriteX (uword addr, intptr_t value, Instr* instr) {
1040- if ((addr & 7 ) == 0 ) {
1050+ if (FLAG_sim_allow_unaligned_accesses || (addr & 7 ) == 0 ) {
10411051 intptr_t * ptr = reinterpret_cast <intptr_t *>(addr);
10421052 *ptr = value;
10431053 return ;
10441054 }
10451055 UnalignedAccess (" write" , addr, instr);
10461056}
10471057
1048- uint32_t Simulator::ReadWU (uword addr, Instr* instr) {
1049- if ((addr & 3 ) == 0 ) {
1058+ uint32_t Simulator::ReadWU (uword addr,
1059+ Instr* instr,
1060+ bool must_be_aligned /* = false */ ) {
1061+ const bool allow_unaligned_access =
1062+ FLAG_sim_allow_unaligned_accesses && !must_be_aligned;
1063+ if (allow_unaligned_access || (addr & 3 ) == 0 ) {
10501064 uint32_t * ptr = reinterpret_cast <uint32_t *>(addr);
10511065 return *ptr;
10521066 }
@@ -1055,7 +1069,7 @@ uint32_t Simulator::ReadWU(uword addr, Instr* instr) {
10551069}
10561070
10571071int32_t Simulator::ReadW (uword addr, Instr* instr) {
1058- if ((addr & 3 ) == 0 ) {
1072+ if (FLAG_sim_allow_unaligned_accesses || (addr & 3 ) == 0 ) {
10591073 int32_t * ptr = reinterpret_cast <int32_t *>(addr);
10601074 return *ptr;
10611075 }
@@ -1064,7 +1078,7 @@ int32_t Simulator::ReadW(uword addr, Instr* instr) {
10641078}
10651079
10661080void Simulator::WriteW (uword addr, uint32_t value, Instr* instr) {
1067- if ((addr & 3 ) == 0 ) {
1081+ if (FLAG_sim_allow_unaligned_accesses || (addr & 3 ) == 0 ) {
10681082 uint32_t * ptr = reinterpret_cast <uint32_t *>(addr);
10691083 *ptr = value;
10701084 return ;
@@ -1073,7 +1087,7 @@ void Simulator::WriteW(uword addr, uint32_t value, Instr* instr) {
10731087}
10741088
10751089uint16_t Simulator::ReadHU (uword addr, Instr* instr) {
1076- if ((addr & 1 ) == 0 ) {
1090+ if (FLAG_sim_allow_unaligned_accesses || (addr & 1 ) == 0 ) {
10771091 uint16_t * ptr = reinterpret_cast <uint16_t *>(addr);
10781092 return *ptr;
10791093 }
@@ -1082,7 +1096,7 @@ uint16_t Simulator::ReadHU(uword addr, Instr* instr) {
10821096}
10831097
10841098int16_t Simulator::ReadH (uword addr, Instr* instr) {
1085- if ((addr & 1 ) == 0 ) {
1099+ if (FLAG_sim_allow_unaligned_accesses || (addr & 1 ) == 0 ) {
10861100 int16_t * ptr = reinterpret_cast <int16_t *>(addr);
10871101 return *ptr;
10881102 }
@@ -1091,7 +1105,7 @@ int16_t Simulator::ReadH(uword addr, Instr* instr) {
10911105}
10921106
10931107void Simulator::WriteH (uword addr, uint16_t value, Instr* instr) {
1094- if ((addr & 1 ) == 0 ) {
1108+ if (FLAG_sim_allow_unaligned_accesses || (addr & 1 ) == 0 ) {
10951109 uint16_t * ptr = reinterpret_cast <uint16_t *>(addr);
10961110 *ptr = value;
10971111 return ;
@@ -1121,13 +1135,13 @@ void Simulator::ClearExclusive() {
11211135
11221136intptr_t Simulator::ReadExclusiveX (uword addr, Instr* instr) {
11231137 exclusive_access_addr_ = addr;
1124- exclusive_access_value_ = ReadX (addr, instr);
1138+ exclusive_access_value_ = ReadX (addr, instr, /* must_be_aligned= */ true );
11251139 return exclusive_access_value_;
11261140}
11271141
11281142intptr_t Simulator::ReadExclusiveW (uword addr, Instr* instr) {
11291143 exclusive_access_addr_ = addr;
1130- exclusive_access_value_ = ReadWU (addr, instr);
1144+ exclusive_access_value_ = ReadWU (addr, instr, /* must_be_aligned= */ true );
11311145 return exclusive_access_value_;
11321146}
11331147
0 commit comments