callbacks: Read code using MemoryReadCode callback
This commit is contained in:
parent
80b2efbea7
commit
36082087de
10 changed files with 45 additions and 23 deletions
|
@ -16,6 +16,10 @@ 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);
|
||||
|
||||
// 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);
|
||||
|
|
|
@ -103,7 +103,7 @@ private:
|
|||
if (block)
|
||||
return *block;
|
||||
|
||||
IR::Block ir_block = Arm::Translate(descriptor, callbacks.MemoryRead32);
|
||||
IR::Block ir_block = Arm::Translate(descriptor, callbacks.MemoryReadCode);
|
||||
Optimization::GetSetElimination(ir_block);
|
||||
Optimization::DeadCodeElimination(ir_block);
|
||||
Optimization::VerificationPass(ir_block);
|
||||
|
|
|
@ -11,11 +11,11 @@
|
|||
namespace Dynarmic {
|
||||
namespace Arm {
|
||||
|
||||
IR::Block TranslateArm(IR::LocationDescriptor descriptor, MemoryRead32FuncType memory_read_32);
|
||||
IR::Block TranslateThumb(IR::LocationDescriptor descriptor, MemoryRead32FuncType memory_read_32);
|
||||
IR::Block TranslateArm(IR::LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code);
|
||||
IR::Block TranslateThumb(IR::LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code);
|
||||
|
||||
IR::Block Translate(IR::LocationDescriptor descriptor, MemoryRead32FuncType memory_read_32) {
|
||||
return (descriptor.TFlag() ? TranslateThumb : TranslateArm)(descriptor, memory_read_32);
|
||||
IR::Block Translate(IR::LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code) {
|
||||
return (descriptor.TFlag() ? TranslateThumb : TranslateArm)(descriptor, memory_read_code);
|
||||
}
|
||||
|
||||
} // namespace Arm
|
||||
|
|
|
@ -18,15 +18,15 @@ namespace Arm {
|
|||
|
||||
struct LocationDescriptor;
|
||||
|
||||
using MemoryRead32FuncType = u32 (*)(u32 vaddr);
|
||||
using MemoryReadCodeFuncType = u32 (*)(u32 vaddr);
|
||||
|
||||
/**
|
||||
* This function translates instructions in memory into our intermediate representation.
|
||||
* @param descriptor The starting location of the basic block. Includes information like PC, Thumb state, &c.
|
||||
* @param memory_read_32 The function we should use to read emulated memory.
|
||||
* @param memory_read_code The function we should use to read emulated memory.
|
||||
* @return A translated basic block in the intermediate representation.
|
||||
*/
|
||||
IR::Block Translate(IR::LocationDescriptor descriptor, MemoryRead32FuncType memory_read_32);
|
||||
IR::Block Translate(IR::LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code);
|
||||
|
||||
} // namespace Arm
|
||||
} // namespace Dynarmic
|
||||
|
|
|
@ -28,13 +28,13 @@ static bool CondCanContinue(ConditionalState cond_state, const IR::IREmitter& ir
|
|||
return std::all_of(ir.block.begin(), ir.block.end(), [](const IR::Inst& inst) { return !inst.WritesToCPSR(); });
|
||||
}
|
||||
|
||||
IR::Block TranslateArm(IR::LocationDescriptor descriptor, MemoryRead32FuncType memory_read_32) {
|
||||
IR::Block TranslateArm(IR::LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code) {
|
||||
ArmTranslatorVisitor visitor{descriptor};
|
||||
|
||||
bool should_continue = true;
|
||||
while (should_continue && CondCanContinue(visitor.cond_state, visitor.ir)) {
|
||||
const u32 arm_pc = visitor.ir.current_location.PC();
|
||||
const u32 arm_instruction = memory_read_32(arm_pc);
|
||||
const u32 arm_instruction = memory_read_code(arm_pc);
|
||||
|
||||
if (auto vfp_decoder = DecodeVFP2<ArmTranslatorVisitor>(arm_instruction)) {
|
||||
should_continue = vfp_decoder->call(visitor, arm_instruction);
|
||||
|
|
|
@ -836,8 +836,8 @@ enum class ThumbInstSize {
|
|||
Thumb16, Thumb32
|
||||
};
|
||||
|
||||
std::tuple<u32, ThumbInstSize> ReadThumbInstruction(u32 arm_pc, MemoryRead32FuncType memory_read_32) {
|
||||
u32 first_part = memory_read_32(arm_pc & 0xFFFFFFFC);
|
||||
std::tuple<u32, ThumbInstSize> ReadThumbInstruction(u32 arm_pc, MemoryReadCodeFuncType memory_read_code) {
|
||||
u32 first_part = memory_read_code(arm_pc & 0xFFFFFFFC);
|
||||
if ((arm_pc & 0x2) != 0)
|
||||
first_part >>= 16;
|
||||
first_part &= 0xFFFF;
|
||||
|
@ -850,7 +850,7 @@ std::tuple<u32, ThumbInstSize> ReadThumbInstruction(u32 arm_pc, MemoryRead32Func
|
|||
// 32-bit thumb instruction
|
||||
// These always start with 0b11101, 0b11110 or 0b11111.
|
||||
|
||||
u32 second_part = memory_read_32((arm_pc + 2) & 0xFFFFFFFC);
|
||||
u32 second_part = memory_read_code((arm_pc + 2) & 0xFFFFFFFC);
|
||||
if (((arm_pc + 2) & 0x2) != 0)
|
||||
second_part >>= 16;
|
||||
second_part &= 0xFFFF;
|
||||
|
@ -860,7 +860,7 @@ std::tuple<u32, ThumbInstSize> ReadThumbInstruction(u32 arm_pc, MemoryRead32Func
|
|||
|
||||
} // local namespace
|
||||
|
||||
IR::Block TranslateThumb(IR::LocationDescriptor descriptor, MemoryRead32FuncType memory_read_32) {
|
||||
IR::Block TranslateThumb(IR::LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code) {
|
||||
ThumbTranslatorVisitor visitor{descriptor};
|
||||
|
||||
bool should_continue = true;
|
||||
|
@ -869,7 +869,7 @@ IR::Block TranslateThumb(IR::LocationDescriptor descriptor, MemoryRead32FuncType
|
|||
|
||||
u32 thumb_instruction;
|
||||
ThumbInstSize inst_size;
|
||||
std::tie(thumb_instruction, inst_size) = ReadThumbInstruction(arm_pc, memory_read_32);
|
||||
std::tie(thumb_instruction, inst_size) = ReadThumbInstruction(arm_pc, memory_read_code);
|
||||
|
||||
if (inst_size == ThumbInstSize::Thumb16) {
|
||||
auto decoder = DecodeThumb16<ThumbTranslatorVisitor>(static_cast<u16>(thumb_instruction));
|
||||
|
|
|
@ -52,6 +52,7 @@ static u8 MemoryRead8(u32 vaddr);
|
|||
static u16 MemoryRead16(u32 vaddr);
|
||||
static u32 MemoryRead32(u32 vaddr);
|
||||
static u64 MemoryRead64(u32 vaddr);
|
||||
static u32 MemoryReadCode(u32 vaddr);
|
||||
static void MemoryWrite8(u32 vaddr, u8 value);
|
||||
static void MemoryWrite16(u32 vaddr, u16 value);
|
||||
static void MemoryWrite32(u32 vaddr, u32 value);
|
||||
|
@ -69,15 +70,18 @@ static u16 MemoryRead16(u32 vaddr) {
|
|||
return static_cast<u16>(vaddr);
|
||||
}
|
||||
static u32 MemoryRead32(u32 vaddr) {
|
||||
if (vaddr < code_mem.size() * sizeof(u32)) {
|
||||
size_t index = vaddr / sizeof(u32);
|
||||
return code_mem[index];
|
||||
}
|
||||
return vaddr;
|
||||
}
|
||||
static u64 MemoryRead64(u32 vaddr) {
|
||||
return MemoryRead32(vaddr) | (u64(MemoryRead32(vaddr+4)) << 32);
|
||||
}
|
||||
static u32 MemoryReadCode(u32 vaddr) {
|
||||
if (vaddr < code_mem.size() * sizeof(u32)) {
|
||||
size_t index = vaddr / sizeof(u32);
|
||||
return code_mem[index];
|
||||
}
|
||||
return 0xeafffffe; // b +#0
|
||||
}
|
||||
|
||||
static void MemoryWrite8(u32 vaddr, u8 value){
|
||||
write_records.push_back({8, vaddr, value});
|
||||
|
@ -128,6 +132,7 @@ static Dynarmic::UserCallbacks GetUserCallbacks() {
|
|||
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;
|
||||
|
@ -292,7 +297,7 @@ void FuzzJitArm(const size_t instruction_count, const size_t instructions_to_exe
|
|||
size_t num_insts = 0;
|
||||
while (num_insts < instructions_to_execute_count) {
|
||||
Dynarmic::IR::LocationDescriptor descriptor = {u32(num_insts * 4), Dynarmic::Arm::PSR{}, Dynarmic::Arm::FPSCR{}};
|
||||
Dynarmic::IR::Block ir_block = Dynarmic::Arm::Translate(descriptor, &MemoryRead32);
|
||||
Dynarmic::IR::Block ir_block = Dynarmic::Arm::Translate(descriptor, &MemoryReadCode);
|
||||
Dynarmic::Optimization::GetSetElimination(ir_block);
|
||||
Dynarmic::Optimization::DeadCodeElimination(ir_block);
|
||||
Dynarmic::Optimization::VerificationPass(ir_block);
|
||||
|
|
|
@ -70,6 +70,13 @@ static u32 MemoryRead32(u32 vaddr) {
|
|||
static u64 MemoryRead64(u32 vaddr) {
|
||||
return vaddr;
|
||||
}
|
||||
static u32 MemoryReadCode(u32 vaddr) {
|
||||
if (vaddr < code_mem.size() * sizeof(u16)) {
|
||||
size_t index = vaddr / sizeof(u16);
|
||||
return code_mem[index] | (code_mem[index + 1] << 16);
|
||||
}
|
||||
return 0xE7FEE7FE; // b +#0, b +#0
|
||||
}
|
||||
|
||||
static void MemoryWrite8(u32 vaddr, u8 value){
|
||||
write_records.push_back({8, vaddr, value});
|
||||
|
@ -116,6 +123,7 @@ static Dynarmic::UserCallbacks GetUserCallbacks() {
|
|||
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;
|
||||
|
@ -247,7 +255,7 @@ void FuzzJitThumb(const size_t instruction_count, const size_t instructions_to_e
|
|||
Dynarmic::Arm::PSR cpsr;
|
||||
cpsr.T(true);
|
||||
|
||||
Dynarmic::IR::Block ir_block = Dynarmic::Arm::Translate({0, cpsr, Dynarmic::Arm::FPSCR{}}, MemoryRead32);
|
||||
Dynarmic::IR::Block ir_block = Dynarmic::Arm::Translate({0, cpsr, Dynarmic::Arm::FPSCR{}}, MemoryReadCode);
|
||||
Dynarmic::Optimization::GetSetElimination(ir_block);
|
||||
Dynarmic::Optimization::DeadCodeElimination(ir_block);
|
||||
Dynarmic::Optimization::VerificationPass(ir_block);
|
||||
|
|
|
@ -15,15 +15,19 @@
|
|||
static std::array<u16, 1024> code_mem{};
|
||||
|
||||
static u32 MemoryRead32(u32 vaddr);
|
||||
static u32 MemoryReadCode(u32 vaddr);
|
||||
static void InterpreterFallback(u32 pc, Dynarmic::Jit* jit, void*);
|
||||
static Dynarmic::UserCallbacks GetUserCallbacks();
|
||||
|
||||
static u32 MemoryRead32(u32 vaddr) {
|
||||
return vaddr;
|
||||
}
|
||||
static u32 MemoryReadCode(u32 vaddr) {
|
||||
if (vaddr < code_mem.size() * sizeof(u16)) {
|
||||
size_t index = vaddr / sizeof(u16);
|
||||
return code_mem[index] | (code_mem[index+1] << 16);
|
||||
}
|
||||
return vaddr;
|
||||
return 0xE7FEE7FE; //b +#0, b +#0
|
||||
}
|
||||
|
||||
static void InterpreterFallback(u32 pc, Dynarmic::Jit* jit, void*) {
|
||||
|
@ -45,6 +49,7 @@ 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.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.MemoryRead32)(phys_addr & 0xFFFFFFFC);
|
||||
unsigned int inst = (*cpu->user_callbacks.MemoryReadCode)(phys_addr & 0xFFFFFFFC);
|
||||
|
||||
// If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM instruction
|
||||
if (cpu->TFlag) {
|
||||
|
|
Loading…
Reference in a new issue