Arm64: Implements unaligned atomic loads store handler

In the case that paranoid TSO is enabled, we can force all unaligned loadstores
down this path.

Instead of backpatching, just do the unaligned loadstore in the handler
This commit is contained in:
Ryan Houdek committed 2021-07-10 23:32:18 -07:00
1 parent ee40300eb5
commit 818808c3e1
2 files changed
+137

No files matched your search

@@ -1393,6 +1393,140 @@ bool HandleAtomicMemOp(void *_ucontext, void *_info, uint32_t Instr) {
return false;
}
bool HandleAtomicLoad(void *_ucontext, void *_info, uint32_t Instr) {
mcontext_t* mcontext = &reinterpret_cast<ucontext_t*>(_ucontext)->uc_mcontext;
siginfo_t* info = reinterpret_cast<siginfo_t*>(_info);
if (info->si_code != BUS_ADRALN) {
// This only handles alignment problems
return false;
}
uint32_t Size = 1 << (Instr >> 30);
uint32_t ResultReg = Instr & 0b11111;
uint32_t AddressReg = (Instr >> 5) & 0b11111;
uint64_t Addr = mcontext->regs[AddressReg];
if (Size == 2) {
auto Res = DoLoad16(Addr);
// We set the result register if it isn't a zero register
if (ResultReg != 31) {
mcontext->regs[ResultReg] = Res;
}
return true;
}
else if (Size == 4) {
auto Res = DoLoad32(Addr);
// We set the result register if it isn't a zero register
if (ResultReg != 31) {
mcontext->regs[ResultReg] = Res;
}
return true;
}
else if (Size == 8) {
auto Res = DoLoad64(Addr);
// We set the result register if it isn't a zero register
if (ResultReg != 31) {
mcontext->regs[ResultReg] = Res;
}
return true;
}
return false;
}
bool HandleAtomicStore(void *_ucontext, void *_info, uint32_t Instr) {
mcontext_t* mcontext = &reinterpret_cast<ucontext_t*>(_ucontext)->uc_mcontext;
siginfo_t* info = reinterpret_cast<siginfo_t*>(_info);
if (info->si_code != BUS_ADRALN) {
// This only handles alignment problems
return false;
}
uint32_t Size = 1 << (Instr >> 30);
uint32_t DataReg = Instr & 0x1F;
uint32_t AddressReg = (Instr >> 5) & 0b11111;
uint64_t Addr = mcontext->regs[AddressReg];
constexpr bool DoRetry = false;
if (Size == 2) {
DoCAS16<DoRetry>(
mcontext->regs[DataReg],
0, // Unused
Addr,
[](uint16_t SrcVal, uint16_t) -> uint16_t {
// Expected is just src
return SrcVal;
},
[](uint16_t, uint16_t Desired) -> uint16_t {
// Desired is just Desired
return Desired;
});
return true;
}
else if (Size == 4) {
DoCAS32<DoRetry>(
mcontext->regs[DataReg],
0, // Unused
Addr,
[](uint32_t SrcVal, uint32_t) -> uint32_t {
// Expected is just src
return SrcVal;
},
[](uint32_t, uint32_t Desired) -> uint32_t {
// Desired is just Desired
return Desired;
});
return true;
}
else if (Size == 8) {
DoCAS64<DoRetry>(
mcontext->regs[DataReg],
0, // Unused
Addr,
[](uint64_t SrcVal, uint64_t) -> uint64_t {
// Expected is just src
return SrcVal;
},
[](uint64_t, uint64_t Desired) -> uint64_t {
// Desired is just Desired
return Desired;
});
return true;
}
return false;
}
bool HandleAtomicLoad128(void *_ucontext, void *_info, uint32_t Instr) {
mcontext_t* mcontext = &reinterpret_cast<ucontext_t*>(_ucontext)->uc_mcontext;
siginfo_t* info = reinterpret_cast<siginfo_t*>(_info);
if (info->si_code != BUS_ADRALN) {
// This only handles alignment problems
return false;
}
uint32_t ResultReg = Instr & 0b11111;
uint32_t ResultReg2 = (Instr >> 10) & 0x1F;
uint32_t AddressReg = (Instr >> 5) & 0b11111;
uint64_t Addr = mcontext->regs[AddressReg];
auto Res = DoLoad128(Addr);
// We set the result register if it isn't a zero register
if (ResultReg != 31) {
mcontext->regs[ResultReg] = std::get<0>(Res);
}
if (ResultReg2 != 31) {
mcontext->regs[ResultReg2] = std::get<1>(Res);
}
return true;
}
uint64_t HandleAtomicLoadstoreExclusive(void *_ucontext, void *_info) {
mcontext_t* mcontext = &reinterpret_cast<ucontext_t*>(_ucontext)->uc_mcontext;
siginfo_t* info = reinterpret_cast<siginfo_t*>(_info);
@@ -72,6 +72,9 @@ namespace FEXCore::ArchHelpers::Arm64 {
return (Instr >> RM_OFFSET) & REGISTER_MASK;
}
bool HandleAtomicLoad(void *_ucontext, void *_info, uint32_t Instr);
bool HandleAtomicStore(void *_ucontext, void *_info, uint32_t Instr);
bool HandleAtomicLoad128(void *_ucontext, void *_info, uint32_t Instr);
uint64_t HandleAtomicLoadstoreExclusive(void *_ucontext, void *_info);
bool HandleCASPAL(void *_ucontext, void *_info, uint32_t Instr);
bool HandleCASAL(void *_ucontext, void *_info, uint32_t Instr);