aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJacob Bramley <jacob.bramley@arm.com>2020-07-03 18:17:36 +0100
committerJacob Bramley <jacob.bramley@arm.com>2020-07-06 10:13:23 +0100
commit3eb24e95aabe254788d21fd8c647964ec93aca67 (patch)
tree712df05f7f27522c277c8757b9a15ee81374a30c /src
parent102e7a5edc112c3c561f7b8352619c8156d502b1 (diff)
downloadvixl-3eb24e95aabe254788d21fd8c647964ec93aca67.tar.gz
Fix numerous issues related to CAS* instructions.
1. There was no test for 64-bit CASP. 2. The tests had some faulty code for obtaining aligned pointers. The natural alignment is sufficient anyway, so this patch removes the broken alignment code, and varies the addresses used to strengthen the test slightly. For the new CASP test, this patch uses the C++11 `alignas` specifier. 3. The simulation of CASP variants accessed memory in the wrong order. With this patch, the first-specified register in each pair accesses the lowest address. 4. We now check that `rs` and `rt` have the same format. Likewise for `rs2` and `rt2` in the CASP variants. 5. Register trace is improved: the `rs` (and `rs2`) update is traced as a memory read so we should suppress the log on the register write. This is what we do for normal loads. Change-Id: I213c4b3de32305a8072fdc45357b67cbbf85ba9c
Diffstat (limited to 'src')
-rw-r--r--src/aarch64/assembler-aarch64.cc2
-rw-r--r--src/aarch64/simulator-aarch64.cc24
2 files changed, 14 insertions, 12 deletions
diff --git a/src/aarch64/assembler-aarch64.cc b/src/aarch64/assembler-aarch64.cc
index 77b94573..e98de89b 100644
--- a/src/aarch64/assembler-aarch64.cc
+++ b/src/aarch64/assembler-aarch64.cc
@@ -1653,6 +1653,7 @@ void Assembler::ldlar(const Register& rt, const MemOperand& src) {
const MemOperand& src) { \
VIXL_ASSERT(CPUHas(CPUFeatures::kAtomics)); \
VIXL_ASSERT(src.IsImmediateOffset() && (src.GetOffset() == 0)); \
+ VIXL_ASSERT(AreSameFormat(rs, rt)); \
LoadStoreExclusive op = rt.Is64Bits() ? OP##_x : OP##_w; \
Emit(op | Rs(rs) | Rt(rt) | Rt2_mask | RnSP(src.GetBaseRegister())); \
}
@@ -1703,6 +1704,7 @@ COMPARE_AND_SWAP_W_LIST(VIXL_DEFINE_ASM_FUNC)
VIXL_ASSERT(AreEven(rs, rt)); \
VIXL_ASSERT(AreConsecutive(rs, rs1)); \
VIXL_ASSERT(AreConsecutive(rt, rt1)); \
+ VIXL_ASSERT(AreSameFormat(rs, rs1, rt, rt1)); \
LoadStoreExclusive op = rt.Is64Bits() ? OP##_x : OP##_w; \
Emit(op | Rs(rs) | Rt(rt) | Rt2_mask | RnSP(src.GetBaseRegister())); \
}
diff --git a/src/aarch64/simulator-aarch64.cc b/src/aarch64/simulator-aarch64.cc
index 40e3a9fa..5326b186 100644
--- a/src/aarch64/simulator-aarch64.cc
+++ b/src/aarch64/simulator-aarch64.cc
@@ -2453,7 +2453,7 @@ void Simulator::CompareAndSwapHelper(const Instruction* instr) {
Memory::Write<T>(address, newvalue);
LogWrite(rt, GetPrintRegisterFormatForSize(element_size), address);
}
- WriteRegister<T>(rs, data);
+ WriteRegister<T>(rs, data, NoRegLog);
LogRead(rs, GetPrintRegisterFormatForSize(element_size), address);
}
@@ -2465,7 +2465,7 @@ void Simulator::CompareAndSwapPairHelper(const Instruction* instr) {
unsigned rt = instr->GetRt();
unsigned rn = instr->GetRn();
- VIXL_ASSERT((rs % 2 == 0) && (rs % 2 == 0));
+ VIXL_ASSERT((rs % 2 == 0) && (rt % 2 == 0));
unsigned element_size = sizeof(T);
uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
@@ -2486,8 +2486,8 @@ void Simulator::CompareAndSwapPairHelper(const Instruction* instr) {
// associated with that location, even if the compare subsequently fails.
local_monitor_.Clear();
- T data_high = Memory::Read<T>(address);
- T data_low = Memory::Read<T>(address2);
+ T data_low = Memory::Read<T>(address);
+ T data_high = Memory::Read<T>(address2);
if (is_acquire) {
// Approximate load-acquire by issuing a full barrier after the load.
@@ -2502,20 +2502,20 @@ void Simulator::CompareAndSwapPairHelper(const Instruction* instr) {
__sync_synchronize();
}
- Memory::Write<T>(address, newvalue_high);
- Memory::Write<T>(address2, newvalue_low);
+ Memory::Write<T>(address, newvalue_low);
+ Memory::Write<T>(address2, newvalue_high);
}
- WriteRegister<T>(rs + 1, data_high);
- WriteRegister<T>(rs, data_low);
+ WriteRegister<T>(rs + 1, data_high, NoRegLog);
+ WriteRegister<T>(rs, data_low, NoRegLog);
PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
- LogRead(rs + 1, format, address);
- LogRead(rs, format, address2);
+ LogRead(rs, format, address);
+ LogRead(rs + 1, format, address2);
if (same) {
- LogWrite(rt + 1, format, address);
- LogWrite(rt, format, address2);
+ LogWrite(rt, format, address);
+ LogWrite(rt + 1, format, address2);
}
}