A32 global exlcusive monitor

This commit is contained in:
MerryMage 2020-06-16 15:46:47 +01:00
parent 58abdcce5b
commit 2c1a4843ad
12 changed files with 260 additions and 56 deletions

View file

@ -188,11 +188,6 @@ void IREmitter::ClearExclusive() {
Inst(Opcode::A32ClearExclusive);
}
void IREmitter::SetExclusive(const IR::U32& vaddr, size_t byte_size) {
ASSERT(byte_size == 1 || byte_size == 2 || byte_size == 4 || byte_size == 8 || byte_size == 16);
Inst(Opcode::A32SetExclusive, vaddr, Imm8(u8(byte_size)));
}
IR::UAny IREmitter::ReadMemory(size_t bitsize, const IR::U32& vaddr) {
switch (bitsize) {
case 8:
@ -226,6 +221,31 @@ IR::U64 IREmitter::ReadMemory64(const IR::U32& vaddr) {
return current_location.EFlag() ? ByteReverseDual(value) : value;
}
IR::U8 IREmitter::ExclusiveReadMemory8(const IR::U32& vaddr) {
return Inst<IR::U8>(Opcode::A32ExclusiveReadMemory8, vaddr);
}
IR::U16 IREmitter::ExclusiveReadMemory16(const IR::U32& vaddr) {
const auto value = Inst<IR::U16>(Opcode::A32ExclusiveReadMemory16, vaddr);
return current_location.EFlag() ? ByteReverseHalf(value) : value;
}
IR::U32 IREmitter::ExclusiveReadMemory32(const IR::U32& vaddr) {
const auto value = Inst<IR::U32>(Opcode::A32ExclusiveReadMemory32, vaddr);
return current_location.EFlag() ? ByteReverseWord(value) : value;
}
std::pair<IR::U32, IR::U32> IREmitter::ExclusiveReadMemory64(const IR::U32& vaddr) {
const auto value = Inst<IR::U64>(Opcode::A32ExclusiveReadMemory64, vaddr);
const auto lo = LeastSignificantWord(value);
const auto hi = MostSignificantWord(value).result;
if (current_location.EFlag()) {
// DO NOT SWAP hi AND lo IN BIG ENDIAN MODE, THIS IS CORRECT BEHAVIOUR
return std::make_pair(ByteReverseWord(lo), ByteReverseWord(hi));
}
return std::make_pair(lo, hi);
}
void IREmitter::WriteMemory(size_t bitsize, const IR::U32& vaddr, const IR::UAny& value) {
switch (bitsize) {
case 8:

View file

@ -5,6 +5,8 @@
#pragma once
#include <utility>
#include "common/common_types.h"
#include "frontend/A32/location_descriptor.h"
#include "frontend/ir/ir_emitter.h"
@ -71,12 +73,15 @@ public:
void SetFpscrNZCV(const IR::NZCV& new_fpscr_nzcv);
void ClearExclusive();
void SetExclusive(const IR::U32& vaddr, size_t byte_size);
IR::UAny ReadMemory(size_t bitsize, const IR::U32& vaddr);
IR::U8 ReadMemory8(const IR::U32& vaddr);
IR::U16 ReadMemory16(const IR::U32& vaddr);
IR::U32 ReadMemory32(const IR::U32& vaddr);
IR::U64 ReadMemory64(const IR::U32& vaddr);
IR::U8 ExclusiveReadMemory8(const IR::U32& vaddr);
IR::U16 ExclusiveReadMemory16(const IR::U32& vaddr);
IR::U32 ExclusiveReadMemory32(const IR::U32& vaddr);
std::pair<IR::U32, IR::U32> ExclusiveReadMemory64(const IR::U32& vaddr);
void WriteMemory(size_t bitsize, const IR::U32& vaddr, const IR::UAny& value);
void WriteMemory8(const IR::U32& vaddr, const IR::U8& value);
void WriteMemory16(const IR::U32& vaddr, const IR::U16& value);

View file

@ -103,8 +103,7 @@ bool ArmTranslatorVisitor::arm_LDAEX(Cond cond, Reg n, Reg t) {
}
const auto address = ir.GetRegister(n);
ir.SetExclusive(address, 4);
ir.SetRegister(t, ir.ReadMemory32(address)); // AccType::Ordered
ir.SetRegister(t, ir.ExclusiveReadMemory32(address)); // AccType::Ordered
return true;
}
@ -119,8 +118,7 @@ bool ArmTranslatorVisitor::arm_LDAEXB(Cond cond, Reg n, Reg t) {
}
const auto address = ir.GetRegister(n);
ir.SetExclusive(address, 1);
ir.SetRegister(t, ir.ZeroExtendByteToWord(ir.ReadMemory8(address))); // AccType::Ordered
ir.SetRegister(t, ir.ZeroExtendByteToWord(ir.ExclusiveReadMemory8(address))); // AccType::Ordered
return true;
}
@ -135,12 +133,9 @@ bool ArmTranslatorVisitor::arm_LDAEXD(Cond cond, Reg n, Reg t) {
}
const auto address = ir.GetRegister(n);
ir.SetExclusive(address, 8);
const auto [lo, hi] = ir.ExclusiveReadMemory64(address); // AccType::Ordered
// DO NOT SWAP hi AND lo IN BIG ENDIAN MODE, THIS IS CORRECT BEHAVIOUR
const auto lo = ir.ReadMemory32(address); // AccType::Ordered
ir.SetRegister(t, lo);
const auto hi = ir.ReadMemory32(ir.Add(address, ir.Imm32(4))); // AccType::Ordered
ir.SetRegister(t+1, hi);
return true;
}
@ -156,8 +151,7 @@ bool ArmTranslatorVisitor::arm_LDAEXH(Cond cond, Reg n, Reg t) {
}
const auto address = ir.GetRegister(n);
ir.SetExclusive(address, 2);
ir.SetRegister(t, ir.ZeroExtendHalfToWord(ir.ReadMemory16(address))); // AccType::Ordered
ir.SetRegister(t, ir.ZeroExtendHalfToWord(ir.ExclusiveReadMemory16(address))); // AccType::Ordered
return true;
}
@ -302,8 +296,7 @@ bool ArmTranslatorVisitor::arm_LDREX(Cond cond, Reg n, Reg t) {
}
const auto address = ir.GetRegister(n);
ir.SetExclusive(address, 4);
ir.SetRegister(t, ir.ReadMemory32(address));
ir.SetRegister(t, ir.ExclusiveReadMemory32(address));
return true;
}
@ -318,8 +311,7 @@ bool ArmTranslatorVisitor::arm_LDREXB(Cond cond, Reg n, Reg t) {
}
const auto address = ir.GetRegister(n);
ir.SetExclusive(address, 1);
ir.SetRegister(t, ir.ZeroExtendByteToWord(ir.ReadMemory8(address)));
ir.SetRegister(t, ir.ZeroExtendByteToWord(ir.ExclusiveReadMemory8(address)));
return true;
}
@ -334,12 +326,9 @@ bool ArmTranslatorVisitor::arm_LDREXD(Cond cond, Reg n, Reg t) {
}
const auto address = ir.GetRegister(n);
ir.SetExclusive(address, 8);
const auto [lo, hi] = ir.ExclusiveReadMemory64(address);
// DO NOT SWAP hi AND lo IN BIG ENDIAN MODE, THIS IS CORRECT BEHAVIOUR
const auto lo = ir.ReadMemory32(address);
ir.SetRegister(t, lo);
const auto hi = ir.ReadMemory32(ir.Add(address, ir.Imm32(4)));
ir.SetRegister(t+1, hi);
return true;
}
@ -355,8 +344,7 @@ bool ArmTranslatorVisitor::arm_LDREXH(Cond cond, Reg n, Reg t) {
}
const auto address = ir.GetRegister(n);
ir.SetExclusive(address, 2);
ir.SetRegister(t, ir.ZeroExtendHalfToWord(ir.ReadMemory16(address)));
ir.SetRegister(t, ir.ZeroExtendHalfToWord(ir.ExclusiveReadMemory16(address)));
return true;
}

View file

@ -101,6 +101,10 @@ bool Inst::IsSharedMemoryReadOrWrite() const {
bool Inst::IsExclusiveMemoryRead() const {
switch (op) {
case Opcode::A32ExclusiveReadMemory8:
case Opcode::A32ExclusiveReadMemory16:
case Opcode::A32ExclusiveReadMemory32:
case Opcode::A32ExclusiveReadMemory64:
case Opcode::A64ExclusiveReadMemory8:
case Opcode::A64ExclusiveReadMemory16:
case Opcode::A64ExclusiveReadMemory32:
@ -487,7 +491,6 @@ bool Inst::CausesCPUException() const {
bool Inst::AltersExclusiveState() const {
return op == Opcode::A32ClearExclusive ||
op == Opcode::A32SetExclusive ||
op == Opcode::A64ClearExclusive ||
IsExclusiveMemoryRead() ||
IsExclusiveMemoryWrite();

View file

@ -641,11 +641,14 @@ OPCODE(FPVectorToUnsignedFixed64, U128, U128
// A32 Memory access
A32OPC(ClearExclusive, Void, )
A32OPC(SetExclusive, Void, U32, U8 )
A32OPC(ReadMemory8, U8, U32 )
A32OPC(ReadMemory16, U16, U32 )
A32OPC(ReadMemory32, U32, U32 )
A32OPC(ReadMemory64, U64, U32 )
A32OPC(ExclusiveReadMemory8, U8, U32 )
A32OPC(ExclusiveReadMemory16, U16, U32 )
A32OPC(ExclusiveReadMemory32, U32, U32 )
A32OPC(ExclusiveReadMemory64, U64, U32 )
A32OPC(WriteMemory8, Void, U32, U8 )
A32OPC(WriteMemory16, Void, U32, U16 )
A32OPC(WriteMemory32, Void, U32, U32 )