@@ -31,6 +31,11 @@ DEFINE_FLAG(uint64_t,
31
31
ULLONG_MAX,
32
32
" Instruction address or instruction count to stop simulator at." );
33
33
34
+ DEFINE_FLAG (bool ,
35
+ sim_allow_unaligned_accesses,
36
+ true ,
37
+ " Allow unaligned accesses to Normal memory." );
38
+
34
39
// This macro provides a platform independent use of sscanf. The reason for
35
40
// SScanF not being implemented in a platform independent way through
36
41
// 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) {
999
1004
FATAL (" Cannot continue execution after illegal memory access." );
1000
1005
}
1001
1006
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.
1005
1011
void Simulator::UnalignedAccess (const char * msg, uword addr, Instr* instr) {
1006
1012
char buffer[128 ];
1007
1013
snprintf (buffer, sizeof (buffer), " unaligned %s at 0x%" Px " , pc=%p\n " , msg,
@@ -1027,8 +1033,12 @@ bool Simulator::IsTracingExecution() const {
1027
1033
return icount_ > FLAG_trace_sim_after;
1028
1034
}
1029
1035
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 ) {
1032
1042
intptr_t * ptr = reinterpret_cast <intptr_t *>(addr);
1033
1043
return *ptr;
1034
1044
}
@@ -1037,16 +1047,20 @@ intptr_t Simulator::ReadX(uword addr, Instr* instr) {
1037
1047
}
1038
1048
1039
1049
void Simulator::WriteX (uword addr, intptr_t value, Instr* instr) {
1040
- if ((addr & 7 ) == 0 ) {
1050
+ if (FLAG_sim_allow_unaligned_accesses || (addr & 7 ) == 0 ) {
1041
1051
intptr_t * ptr = reinterpret_cast <intptr_t *>(addr);
1042
1052
*ptr = value;
1043
1053
return ;
1044
1054
}
1045
1055
UnalignedAccess (" write" , addr, instr);
1046
1056
}
1047
1057
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 ) {
1050
1064
uint32_t * ptr = reinterpret_cast <uint32_t *>(addr);
1051
1065
return *ptr;
1052
1066
}
@@ -1055,7 +1069,7 @@ uint32_t Simulator::ReadWU(uword addr, Instr* instr) {
1055
1069
}
1056
1070
1057
1071
int32_t Simulator::ReadW (uword addr, Instr* instr) {
1058
- if ((addr & 3 ) == 0 ) {
1072
+ if (FLAG_sim_allow_unaligned_accesses || (addr & 3 ) == 0 ) {
1059
1073
int32_t * ptr = reinterpret_cast <int32_t *>(addr);
1060
1074
return *ptr;
1061
1075
}
@@ -1064,7 +1078,7 @@ int32_t Simulator::ReadW(uword addr, Instr* instr) {
1064
1078
}
1065
1079
1066
1080
void Simulator::WriteW (uword addr, uint32_t value, Instr* instr) {
1067
- if ((addr & 3 ) == 0 ) {
1081
+ if (FLAG_sim_allow_unaligned_accesses || (addr & 3 ) == 0 ) {
1068
1082
uint32_t * ptr = reinterpret_cast <uint32_t *>(addr);
1069
1083
*ptr = value;
1070
1084
return ;
@@ -1073,7 +1087,7 @@ void Simulator::WriteW(uword addr, uint32_t value, Instr* instr) {
1073
1087
}
1074
1088
1075
1089
uint16_t Simulator::ReadHU (uword addr, Instr* instr) {
1076
- if ((addr & 1 ) == 0 ) {
1090
+ if (FLAG_sim_allow_unaligned_accesses || (addr & 1 ) == 0 ) {
1077
1091
uint16_t * ptr = reinterpret_cast <uint16_t *>(addr);
1078
1092
return *ptr;
1079
1093
}
@@ -1082,7 +1096,7 @@ uint16_t Simulator::ReadHU(uword addr, Instr* instr) {
1082
1096
}
1083
1097
1084
1098
int16_t Simulator::ReadH (uword addr, Instr* instr) {
1085
- if ((addr & 1 ) == 0 ) {
1099
+ if (FLAG_sim_allow_unaligned_accesses || (addr & 1 ) == 0 ) {
1086
1100
int16_t * ptr = reinterpret_cast <int16_t *>(addr);
1087
1101
return *ptr;
1088
1102
}
@@ -1091,7 +1105,7 @@ int16_t Simulator::ReadH(uword addr, Instr* instr) {
1091
1105
}
1092
1106
1093
1107
void Simulator::WriteH (uword addr, uint16_t value, Instr* instr) {
1094
- if ((addr & 1 ) == 0 ) {
1108
+ if (FLAG_sim_allow_unaligned_accesses || (addr & 1 ) == 0 ) {
1095
1109
uint16_t * ptr = reinterpret_cast <uint16_t *>(addr);
1096
1110
*ptr = value;
1097
1111
return ;
@@ -1121,13 +1135,13 @@ void Simulator::ClearExclusive() {
1121
1135
1122
1136
intptr_t Simulator::ReadExclusiveX (uword addr, Instr* instr) {
1123
1137
exclusive_access_addr_ = addr;
1124
- exclusive_access_value_ = ReadX (addr, instr);
1138
+ exclusive_access_value_ = ReadX (addr, instr, /* must_be_aligned= */ true );
1125
1139
return exclusive_access_value_;
1126
1140
}
1127
1141
1128
1142
intptr_t Simulator::ReadExclusiveW (uword addr, Instr* instr) {
1129
1143
exclusive_access_addr_ = addr;
1130
- exclusive_access_value_ = ReadWU (addr, instr);
1144
+ exclusive_access_value_ = ReadWU (addr, instr, /* must_be_aligned= */ true );
1131
1145
return exclusive_access_value_;
1132
1146
}
1133
1147
0 commit comments