callbacks: Factorize memory callbacks into inner structure
This commit is contained in:
parent
642ccb0f66
commit
2447f2f360
9 changed files with 74 additions and 72 deletions
|
@ -18,29 +18,31 @@ class Jit;
|
|||
|
||||
/// These function pointers may be inserted into compiled code.
|
||||
struct UserCallbacks {
|
||||
// All reads through this callback are 4-byte aligned.
|
||||
// Memory must be interpreted as little endian.
|
||||
std::uint32_t (*MemoryReadCode)(std::uint32_t vaddr);
|
||||
struct Memory {
|
||||
// All reads through this callback are 4-byte aligned.
|
||||
// Memory must be interpreted as little endian.
|
||||
std::uint32_t (*ReadCode)(std::uint32_t vaddr);
|
||||
|
||||
// Reads through these callbacks may not be aligned.
|
||||
// Memory must be interpreted as if ENDIANSTATE == 0, endianness will be corrected by the JIT.
|
||||
std::uint8_t (*MemoryRead8)(std::uint32_t vaddr);
|
||||
std::uint16_t (*MemoryRead16)(std::uint32_t vaddr);
|
||||
std::uint32_t (*MemoryRead32)(std::uint32_t vaddr);
|
||||
std::uint64_t (*MemoryRead64)(std::uint32_t vaddr);
|
||||
// Reads through these callbacks may not be aligned.
|
||||
// Memory must be interpreted as if ENDIANSTATE == 0, endianness will be corrected by the JIT.
|
||||
std::uint8_t (*Read8)(std::uint32_t vaddr);
|
||||
std::uint16_t (*Read16)(std::uint32_t vaddr);
|
||||
std::uint32_t (*Read32)(std::uint32_t vaddr);
|
||||
std::uint64_t (*Read64)(std::uint32_t vaddr);
|
||||
|
||||
// Writes through these callbacks may not be aligned.
|
||||
// Memory must be interpreted as if ENDIANSTATE == 0, endianness will be corrected by the JIT.
|
||||
void (*MemoryWrite8)(std::uint32_t vaddr, std::uint8_t value);
|
||||
void (*MemoryWrite16)(std::uint32_t vaddr, std::uint16_t value);
|
||||
void (*MemoryWrite32)(std::uint32_t vaddr, std::uint32_t value);
|
||||
void (*MemoryWrite64)(std::uint32_t vaddr, std::uint64_t value);
|
||||
// Writes through these callbacks may not be aligned.
|
||||
// Memory must be interpreted as if ENDIANSTATE == 0, endianness will be corrected by the JIT.
|
||||
void (*Write8)(std::uint32_t vaddr, std::uint8_t value);
|
||||
void (*Write16)(std::uint32_t vaddr, std::uint16_t value);
|
||||
void (*Write32)(std::uint32_t vaddr, std::uint32_t value);
|
||||
void (*Write64)(std::uint32_t vaddr, std::uint64_t value);
|
||||
|
||||
// If this callback returns true, the JIT will assume MemoryRead* callbacks will always
|
||||
// return the same value at any point in time for this vaddr. The JIT may use this information
|
||||
// in optimizations.
|
||||
// An conservative implementation that always returns false is safe.
|
||||
bool (*IsReadOnlyMemory)(std::uint32_t vaddr);
|
||||
// If this callback returns true, the JIT will assume MemoryRead* callbacks will always
|
||||
// return the same value at any point in time for this vaddr. The JIT may use this information
|
||||
// in optimizations.
|
||||
// An conservative implementation that always returns false is safe.
|
||||
bool (*IsReadOnlyMemory)(std::uint32_t vaddr);
|
||||
} memory = {};
|
||||
|
||||
/// The intrepreter must execute only one instruction at PC.
|
||||
void (*InterpreterFallback)(std::uint32_t pc, Jit* jit, void* user_arg);
|
||||
|
|
|
@ -124,56 +124,56 @@ void BlockOfCode::GenMemoryAccessors() {
|
|||
align();
|
||||
read_memory_8 = getCurr<const void*>();
|
||||
ABI_PushCallerSaveRegistersAndAdjustStack(this);
|
||||
CallFunction(cb.MemoryRead8);
|
||||
CallFunction(cb.memory.Read8);
|
||||
ABI_PopCallerSaveRegistersAndAdjustStack(this);
|
||||
ret();
|
||||
|
||||
align();
|
||||
read_memory_16 = getCurr<const void*>();
|
||||
ABI_PushCallerSaveRegistersAndAdjustStack(this);
|
||||
CallFunction(cb.MemoryRead16);
|
||||
CallFunction(cb.memory.Read16);
|
||||
ABI_PopCallerSaveRegistersAndAdjustStack(this);
|
||||
ret();
|
||||
|
||||
align();
|
||||
read_memory_32 = getCurr<const void*>();
|
||||
ABI_PushCallerSaveRegistersAndAdjustStack(this);
|
||||
CallFunction(cb.MemoryRead32);
|
||||
CallFunction(cb.memory.Read32);
|
||||
ABI_PopCallerSaveRegistersAndAdjustStack(this);
|
||||
ret();
|
||||
|
||||
align();
|
||||
read_memory_64 = getCurr<const void*>();
|
||||
ABI_PushCallerSaveRegistersAndAdjustStack(this);
|
||||
CallFunction(cb.MemoryRead64);
|
||||
CallFunction(cb.memory.Read64);
|
||||
ABI_PopCallerSaveRegistersAndAdjustStack(this);
|
||||
ret();
|
||||
|
||||
align();
|
||||
write_memory_8 = getCurr<const void*>();
|
||||
ABI_PushCallerSaveRegistersAndAdjustStack(this);
|
||||
CallFunction(cb.MemoryWrite8);
|
||||
CallFunction(cb.memory.Write8);
|
||||
ABI_PopCallerSaveRegistersAndAdjustStack(this);
|
||||
ret();
|
||||
|
||||
align();
|
||||
write_memory_16 = getCurr<const void*>();
|
||||
ABI_PushCallerSaveRegistersAndAdjustStack(this);
|
||||
CallFunction(cb.MemoryWrite16);
|
||||
CallFunction(cb.memory.Write16);
|
||||
ABI_PopCallerSaveRegistersAndAdjustStack(this);
|
||||
ret();
|
||||
|
||||
align();
|
||||
write_memory_32 = getCurr<const void*>();
|
||||
ABI_PushCallerSaveRegistersAndAdjustStack(this);
|
||||
CallFunction(cb.MemoryWrite32);
|
||||
CallFunction(cb.memory.Write32);
|
||||
ABI_PopCallerSaveRegistersAndAdjustStack(this);
|
||||
ret();
|
||||
|
||||
align();
|
||||
write_memory_64 = getCurr<const void*>();
|
||||
ABI_PushCallerSaveRegistersAndAdjustStack(this);
|
||||
CallFunction(cb.MemoryWrite64);
|
||||
CallFunction(cb.memory.Write64);
|
||||
ABI_PopCallerSaveRegistersAndAdjustStack(this);
|
||||
ret();
|
||||
}
|
||||
|
|
|
@ -2866,35 +2866,35 @@ static void WriteMemory(BlockOfCode* code, RegAlloc& reg_alloc, IR::Inst* inst,
|
|||
}
|
||||
|
||||
void EmitX64::EmitReadMemory8(IR::Block&, IR::Inst* inst) {
|
||||
ReadMemory(code, reg_alloc, inst, cb, 8, cb.MemoryRead8);
|
||||
ReadMemory(code, reg_alloc, inst, cb, 8, cb.memory.Read8);
|
||||
}
|
||||
|
||||
void EmitX64::EmitReadMemory16(IR::Block&, IR::Inst* inst) {
|
||||
ReadMemory(code, reg_alloc, inst, cb, 16, cb.MemoryRead16);
|
||||
ReadMemory(code, reg_alloc, inst, cb, 16, cb.memory.Read16);
|
||||
}
|
||||
|
||||
void EmitX64::EmitReadMemory32(IR::Block&, IR::Inst* inst) {
|
||||
ReadMemory(code, reg_alloc, inst, cb, 32, cb.MemoryRead32);
|
||||
ReadMemory(code, reg_alloc, inst, cb, 32, cb.memory.Read32);
|
||||
}
|
||||
|
||||
void EmitX64::EmitReadMemory64(IR::Block&, IR::Inst* inst) {
|
||||
ReadMemory(code, reg_alloc, inst, cb, 64, cb.MemoryRead64);
|
||||
ReadMemory(code, reg_alloc, inst, cb, 64, cb.memory.Read64);
|
||||
}
|
||||
|
||||
void EmitX64::EmitWriteMemory8(IR::Block&, IR::Inst* inst) {
|
||||
WriteMemory(code, reg_alloc, inst, cb, 8, cb.MemoryWrite8);
|
||||
WriteMemory(code, reg_alloc, inst, cb, 8, cb.memory.Write8);
|
||||
}
|
||||
|
||||
void EmitX64::EmitWriteMemory16(IR::Block&, IR::Inst* inst) {
|
||||
WriteMemory(code, reg_alloc, inst, cb, 16, cb.MemoryWrite16);
|
||||
WriteMemory(code, reg_alloc, inst, cb, 16, cb.memory.Write16);
|
||||
}
|
||||
|
||||
void EmitX64::EmitWriteMemory32(IR::Block&, IR::Inst* inst) {
|
||||
WriteMemory(code, reg_alloc, inst, cb, 32, cb.MemoryWrite32);
|
||||
WriteMemory(code, reg_alloc, inst, cb, 32, cb.memory.Write32);
|
||||
}
|
||||
|
||||
void EmitX64::EmitWriteMemory64(IR::Block&, IR::Inst* inst) {
|
||||
WriteMemory(code, reg_alloc, inst, cb, 64, cb.MemoryWrite64);
|
||||
WriteMemory(code, reg_alloc, inst, cb, 64, cb.memory.Write64);
|
||||
}
|
||||
|
||||
template <typename FunctionPointer>
|
||||
|
@ -2920,15 +2920,15 @@ static void ExclusiveWrite(BlockOfCode* code, RegAlloc& reg_alloc, IR::Inst* ins
|
|||
}
|
||||
|
||||
void EmitX64::EmitExclusiveWriteMemory8(IR::Block&, IR::Inst* inst) {
|
||||
ExclusiveWrite(code, reg_alloc, inst, cb.MemoryWrite8);
|
||||
ExclusiveWrite(code, reg_alloc, inst, cb.memory.Write8);
|
||||
}
|
||||
|
||||
void EmitX64::EmitExclusiveWriteMemory16(IR::Block&, IR::Inst* inst) {
|
||||
ExclusiveWrite(code, reg_alloc, inst, cb.MemoryWrite16);
|
||||
ExclusiveWrite(code, reg_alloc, inst, cb.memory.Write16);
|
||||
}
|
||||
|
||||
void EmitX64::EmitExclusiveWriteMemory32(IR::Block&, IR::Inst* inst) {
|
||||
ExclusiveWrite(code, reg_alloc, inst, cb.MemoryWrite32);
|
||||
ExclusiveWrite(code, reg_alloc, inst, cb.memory.Write32);
|
||||
}
|
||||
|
||||
void EmitX64::EmitExclusiveWriteMemory64(IR::Block&, IR::Inst* inst) {
|
||||
|
@ -2952,7 +2952,7 @@ void EmitX64::EmitExclusiveWriteMemory64(IR::Block&, IR::Inst* inst) {
|
|||
code->mov(value.cvt32(), value.cvt32()); // zero extend to 64-bits
|
||||
code->shl(value_hi, 32);
|
||||
code->or_(value, value_hi);
|
||||
code->CallFunction(cb.MemoryWrite64);
|
||||
code->CallFunction(cb.memory.Write64);
|
||||
code->xor_(passed, passed);
|
||||
code->L(end);
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ private:
|
|||
if (block)
|
||||
return *block;
|
||||
|
||||
IR::Block ir_block = Arm::Translate(descriptor, callbacks.MemoryReadCode);
|
||||
IR::Block ir_block = Arm::Translate(descriptor, callbacks.memory.ReadCode);
|
||||
Optimization::GetSetElimination(ir_block);
|
||||
Optimization::DeadCodeElimination(ir_block);
|
||||
Optimization::VerificationPass(ir_block);
|
||||
|
|
|
@ -127,16 +127,16 @@ static Dynarmic::UserCallbacks GetUserCallbacks() {
|
|||
Dynarmic::UserCallbacks user_callbacks{};
|
||||
user_callbacks.InterpreterFallback = &InterpreterFallback;
|
||||
user_callbacks.CallSVC = (void (*)(u32)) &Fail;
|
||||
user_callbacks.IsReadOnlyMemory = &IsReadOnlyMemory;
|
||||
user_callbacks.MemoryRead8 = &MemoryRead8;
|
||||
user_callbacks.MemoryRead16 = &MemoryRead16;
|
||||
user_callbacks.MemoryRead32 = &MemoryRead32;
|
||||
user_callbacks.MemoryRead64 = &MemoryRead64;
|
||||
user_callbacks.MemoryReadCode = &MemoryReadCode;
|
||||
user_callbacks.MemoryWrite8 = &MemoryWrite8;
|
||||
user_callbacks.MemoryWrite16 = &MemoryWrite16;
|
||||
user_callbacks.MemoryWrite32 = &MemoryWrite32;
|
||||
user_callbacks.MemoryWrite64 = &MemoryWrite64;
|
||||
user_callbacks.memory.IsReadOnlyMemory = &IsReadOnlyMemory;
|
||||
user_callbacks.memory.Read8 = &MemoryRead8;
|
||||
user_callbacks.memory.Read16 = &MemoryRead16;
|
||||
user_callbacks.memory.Read32 = &MemoryRead32;
|
||||
user_callbacks.memory.Read64 = &MemoryRead64;
|
||||
user_callbacks.memory.ReadCode = &MemoryReadCode;
|
||||
user_callbacks.memory.Write8 = &MemoryWrite8;
|
||||
user_callbacks.memory.Write16 = &MemoryWrite16;
|
||||
user_callbacks.memory.Write32 = &MemoryWrite32;
|
||||
user_callbacks.memory.Write64 = &MemoryWrite64;
|
||||
return user_callbacks;
|
||||
}
|
||||
|
||||
|
|
|
@ -118,16 +118,16 @@ static Dynarmic::UserCallbacks GetUserCallbacks() {
|
|||
Dynarmic::UserCallbacks user_callbacks{};
|
||||
user_callbacks.InterpreterFallback = &InterpreterFallback;
|
||||
user_callbacks.CallSVC = (void (*)(u32)) &Fail;
|
||||
user_callbacks.IsReadOnlyMemory = &IsReadOnlyMemory;
|
||||
user_callbacks.MemoryRead8 = &MemoryRead8;
|
||||
user_callbacks.MemoryRead16 = &MemoryRead16;
|
||||
user_callbacks.MemoryRead32 = &MemoryRead32;
|
||||
user_callbacks.MemoryRead64 = &MemoryRead64;
|
||||
user_callbacks.MemoryReadCode = &MemoryReadCode;
|
||||
user_callbacks.MemoryWrite8 = &MemoryWrite8;
|
||||
user_callbacks.MemoryWrite16 = &MemoryWrite16;
|
||||
user_callbacks.MemoryWrite32 = &MemoryWrite32;
|
||||
user_callbacks.MemoryWrite64 = &MemoryWrite64;
|
||||
user_callbacks.memory.IsReadOnlyMemory = &IsReadOnlyMemory;
|
||||
user_callbacks.memory.Read8 = &MemoryRead8;
|
||||
user_callbacks.memory.Read16 = &MemoryRead16;
|
||||
user_callbacks.memory.Read32 = &MemoryRead32;
|
||||
user_callbacks.memory.Read64 = &MemoryRead64;
|
||||
user_callbacks.memory.ReadCode = &MemoryReadCode;
|
||||
user_callbacks.memory.Write8 = &MemoryWrite8;
|
||||
user_callbacks.memory.Write16 = &MemoryWrite16;
|
||||
user_callbacks.memory.Write32 = &MemoryWrite32;
|
||||
user_callbacks.memory.Write64 = &MemoryWrite64;
|
||||
return user_callbacks;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,8 +48,8 @@ static void InterpreterFallback(u32 pc, Dynarmic::Jit* jit, void*) {
|
|||
|
||||
static Dynarmic::UserCallbacks GetUserCallbacks() {
|
||||
Dynarmic::UserCallbacks user_callbacks{};
|
||||
user_callbacks.MemoryRead32 = &MemoryRead32;
|
||||
user_callbacks.MemoryReadCode = &MemoryReadCode;
|
||||
user_callbacks.memory.Read32 = &MemoryRead32;
|
||||
user_callbacks.memory.ReadCode = &MemoryReadCode;
|
||||
user_callbacks.InterpreterFallback = &InterpreterFallback;
|
||||
return user_callbacks;
|
||||
}
|
||||
|
|
|
@ -803,7 +803,7 @@ enum {
|
|||
|
||||
static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, const u32 phys_addr, ARM_INST_PTR& inst_base) {
|
||||
unsigned int inst_size = 4;
|
||||
unsigned int inst = (*cpu->user_callbacks.MemoryReadCode)(phys_addr & 0xFFFFFFFC);
|
||||
unsigned int inst = (*cpu->user_callbacks.memory.ReadCode)(phys_addr & 0xFFFFFFFC);
|
||||
|
||||
// If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM instruction
|
||||
if (cpu->TFlag) {
|
||||
|
|
|
@ -204,14 +204,14 @@ u8 ARMul_State::ReadMemory8(u32 address) const
|
|||
{
|
||||
// CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read);
|
||||
|
||||
return (*user_callbacks.MemoryRead8)(address);
|
||||
return (*user_callbacks.memory.Read8)(address);
|
||||
}
|
||||
|
||||
u16 ARMul_State::ReadMemory16(u32 address) const
|
||||
{
|
||||
// CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read);
|
||||
|
||||
u16 data = (*user_callbacks.MemoryRead16)(address);
|
||||
u16 data = (*user_callbacks.memory.Read16)(address);
|
||||
|
||||
if (InBigEndianMode())
|
||||
data = Common::swap16(data);
|
||||
|
@ -223,7 +223,7 @@ u32 ARMul_State::ReadMemory32(u32 address) const
|
|||
{
|
||||
// CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read);
|
||||
|
||||
u32 data = (*user_callbacks.MemoryRead32)(address);
|
||||
u32 data = (*user_callbacks.memory.Read32)(address);
|
||||
|
||||
if (InBigEndianMode())
|
||||
data = Common::swap32(data);
|
||||
|
@ -235,7 +235,7 @@ u64 ARMul_State::ReadMemory64(u32 address) const
|
|||
{
|
||||
// CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read);
|
||||
|
||||
u64 data = (*user_callbacks.MemoryRead64)(address);
|
||||
u64 data = (*user_callbacks.memory.Read64)(address);
|
||||
|
||||
if (InBigEndianMode())
|
||||
data = Common::swap64(data);
|
||||
|
@ -247,7 +247,7 @@ void ARMul_State::WriteMemory8(u32 address, u8 data)
|
|||
{
|
||||
// CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write);
|
||||
|
||||
(*user_callbacks.MemoryWrite8)(address, data);
|
||||
(*user_callbacks.memory.Write8)(address, data);
|
||||
}
|
||||
|
||||
void ARMul_State::WriteMemory16(u32 address, u16 data)
|
||||
|
@ -257,7 +257,7 @@ void ARMul_State::WriteMemory16(u32 address, u16 data)
|
|||
if (InBigEndianMode())
|
||||
data = Common::swap16(data);
|
||||
|
||||
(*user_callbacks.MemoryWrite16)(address, data);
|
||||
(*user_callbacks.memory.Write16)(address, data);
|
||||
}
|
||||
|
||||
void ARMul_State::WriteMemory32(u32 address, u32 data)
|
||||
|
@ -267,7 +267,7 @@ void ARMul_State::WriteMemory32(u32 address, u32 data)
|
|||
if (InBigEndianMode())
|
||||
data = Common::swap32(data);
|
||||
|
||||
(*user_callbacks.MemoryWrite32)(address, data);
|
||||
(*user_callbacks.memory.Write32)(address, data);
|
||||
}
|
||||
|
||||
void ARMul_State::WriteMemory64(u32 address, u64 data)
|
||||
|
@ -277,7 +277,7 @@ void ARMul_State::WriteMemory64(u32 address, u64 data)
|
|||
if (InBigEndianMode())
|
||||
data = Common::swap64(data);
|
||||
|
||||
(*user_callbacks.MemoryWrite64)(address, data);
|
||||
(*user_callbacks.memory.Write64)(address, data);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue