callbacks: Read code using MemoryReadCode callback

This commit is contained in:
MerryMage 2016-12-21 20:48:05 +00:00
parent 80b2efbea7
commit 36082087de
10 changed files with 45 additions and 23 deletions

View file

@ -16,6 +16,10 @@ class Jit;
/// These function pointers may be inserted into compiled code. /// These function pointers may be inserted into compiled code.
struct UserCallbacks { 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. // Reads through these callbacks may not be aligned.
// Memory must be interpreted as if ENDIANSTATE == 0, endianness will be corrected by the JIT. // Memory must be interpreted as if ENDIANSTATE == 0, endianness will be corrected by the JIT.
std::uint8_t (*MemoryRead8)(std::uint32_t vaddr); std::uint8_t (*MemoryRead8)(std::uint32_t vaddr);

View file

@ -103,7 +103,7 @@ private:
if (block) if (block)
return *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::GetSetElimination(ir_block);
Optimization::DeadCodeElimination(ir_block); Optimization::DeadCodeElimination(ir_block);
Optimization::VerificationPass(ir_block); Optimization::VerificationPass(ir_block);

View file

@ -11,11 +11,11 @@
namespace Dynarmic { namespace Dynarmic {
namespace Arm { namespace Arm {
IR::Block TranslateArm(IR::LocationDescriptor descriptor, MemoryRead32FuncType memory_read_32); IR::Block TranslateArm(IR::LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code);
IR::Block TranslateThumb(IR::LocationDescriptor descriptor, MemoryRead32FuncType memory_read_32); IR::Block TranslateThumb(IR::LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code);
IR::Block Translate(IR::LocationDescriptor descriptor, MemoryRead32FuncType memory_read_32) { IR::Block Translate(IR::LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code) {
return (descriptor.TFlag() ? TranslateThumb : TranslateArm)(descriptor, memory_read_32); return (descriptor.TFlag() ? TranslateThumb : TranslateArm)(descriptor, memory_read_code);
} }
} // namespace Arm } // namespace Arm

View file

@ -18,15 +18,15 @@ namespace Arm {
struct LocationDescriptor; struct LocationDescriptor;
using MemoryRead32FuncType = u32 (*)(u32 vaddr); using MemoryReadCodeFuncType = u32 (*)(u32 vaddr);
/** /**
* This function translates instructions in memory into our intermediate representation. * 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 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. * @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 Arm
} // namespace Dynarmic } // namespace Dynarmic

View file

@ -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(); }); 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}; ArmTranslatorVisitor visitor{descriptor};
bool should_continue = true; bool should_continue = true;
while (should_continue && CondCanContinue(visitor.cond_state, visitor.ir)) { while (should_continue && CondCanContinue(visitor.cond_state, visitor.ir)) {
const u32 arm_pc = visitor.ir.current_location.PC(); 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)) { if (auto vfp_decoder = DecodeVFP2<ArmTranslatorVisitor>(arm_instruction)) {
should_continue = vfp_decoder->call(visitor, arm_instruction); should_continue = vfp_decoder->call(visitor, arm_instruction);

View file

@ -836,8 +836,8 @@ enum class ThumbInstSize {
Thumb16, Thumb32 Thumb16, Thumb32
}; };
std::tuple<u32, ThumbInstSize> ReadThumbInstruction(u32 arm_pc, MemoryRead32FuncType memory_read_32) { std::tuple<u32, ThumbInstSize> ReadThumbInstruction(u32 arm_pc, MemoryReadCodeFuncType memory_read_code) {
u32 first_part = memory_read_32(arm_pc & 0xFFFFFFFC); u32 first_part = memory_read_code(arm_pc & 0xFFFFFFFC);
if ((arm_pc & 0x2) != 0) if ((arm_pc & 0x2) != 0)
first_part >>= 16; first_part >>= 16;
first_part &= 0xFFFF; first_part &= 0xFFFF;
@ -850,7 +850,7 @@ std::tuple<u32, ThumbInstSize> ReadThumbInstruction(u32 arm_pc, MemoryRead32Func
// 32-bit thumb instruction // 32-bit thumb instruction
// These always start with 0b11101, 0b11110 or 0b11111. // 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) if (((arm_pc + 2) & 0x2) != 0)
second_part >>= 16; second_part >>= 16;
second_part &= 0xFFFF; second_part &= 0xFFFF;
@ -860,7 +860,7 @@ std::tuple<u32, ThumbInstSize> ReadThumbInstruction(u32 arm_pc, MemoryRead32Func
} // local namespace } // 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}; ThumbTranslatorVisitor visitor{descriptor};
bool should_continue = true; bool should_continue = true;
@ -869,7 +869,7 @@ IR::Block TranslateThumb(IR::LocationDescriptor descriptor, MemoryRead32FuncType
u32 thumb_instruction; u32 thumb_instruction;
ThumbInstSize inst_size; 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) { if (inst_size == ThumbInstSize::Thumb16) {
auto decoder = DecodeThumb16<ThumbTranslatorVisitor>(static_cast<u16>(thumb_instruction)); auto decoder = DecodeThumb16<ThumbTranslatorVisitor>(static_cast<u16>(thumb_instruction));

View file

@ -52,6 +52,7 @@ static u8 MemoryRead8(u32 vaddr);
static u16 MemoryRead16(u32 vaddr); static u16 MemoryRead16(u32 vaddr);
static u32 MemoryRead32(u32 vaddr); static u32 MemoryRead32(u32 vaddr);
static u64 MemoryRead64(u32 vaddr); static u64 MemoryRead64(u32 vaddr);
static u32 MemoryReadCode(u32 vaddr);
static void MemoryWrite8(u32 vaddr, u8 value); static void MemoryWrite8(u32 vaddr, u8 value);
static void MemoryWrite16(u32 vaddr, u16 value); static void MemoryWrite16(u32 vaddr, u16 value);
static void MemoryWrite32(u32 vaddr, u32 value); static void MemoryWrite32(u32 vaddr, u32 value);
@ -69,15 +70,18 @@ static u16 MemoryRead16(u32 vaddr) {
return static_cast<u16>(vaddr); return static_cast<u16>(vaddr);
} }
static u32 MemoryRead32(u32 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; return vaddr;
} }
static u64 MemoryRead64(u32 vaddr) { static u64 MemoryRead64(u32 vaddr) {
return MemoryRead32(vaddr) | (u64(MemoryRead32(vaddr+4)) << 32); 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){ static void MemoryWrite8(u32 vaddr, u8 value){
write_records.push_back({8, vaddr, value}); write_records.push_back({8, vaddr, value});
@ -128,6 +132,7 @@ static Dynarmic::UserCallbacks GetUserCallbacks() {
user_callbacks.MemoryRead16 = &MemoryRead16; user_callbacks.MemoryRead16 = &MemoryRead16;
user_callbacks.MemoryRead32 = &MemoryRead32; user_callbacks.MemoryRead32 = &MemoryRead32;
user_callbacks.MemoryRead64 = &MemoryRead64; user_callbacks.MemoryRead64 = &MemoryRead64;
user_callbacks.MemoryReadCode = &MemoryReadCode;
user_callbacks.MemoryWrite8 = &MemoryWrite8; user_callbacks.MemoryWrite8 = &MemoryWrite8;
user_callbacks.MemoryWrite16 = &MemoryWrite16; user_callbacks.MemoryWrite16 = &MemoryWrite16;
user_callbacks.MemoryWrite32 = &MemoryWrite32; 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; size_t num_insts = 0;
while (num_insts < instructions_to_execute_count) { while (num_insts < instructions_to_execute_count) {
Dynarmic::IR::LocationDescriptor descriptor = {u32(num_insts * 4), Dynarmic::Arm::PSR{}, Dynarmic::Arm::FPSCR{}}; 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::GetSetElimination(ir_block);
Dynarmic::Optimization::DeadCodeElimination(ir_block); Dynarmic::Optimization::DeadCodeElimination(ir_block);
Dynarmic::Optimization::VerificationPass(ir_block); Dynarmic::Optimization::VerificationPass(ir_block);

View file

@ -70,6 +70,13 @@ static u32 MemoryRead32(u32 vaddr) {
static u64 MemoryRead64(u32 vaddr) { static u64 MemoryRead64(u32 vaddr) {
return 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){ static void MemoryWrite8(u32 vaddr, u8 value){
write_records.push_back({8, vaddr, value}); write_records.push_back({8, vaddr, value});
@ -116,6 +123,7 @@ static Dynarmic::UserCallbacks GetUserCallbacks() {
user_callbacks.MemoryRead16 = &MemoryRead16; user_callbacks.MemoryRead16 = &MemoryRead16;
user_callbacks.MemoryRead32 = &MemoryRead32; user_callbacks.MemoryRead32 = &MemoryRead32;
user_callbacks.MemoryRead64 = &MemoryRead64; user_callbacks.MemoryRead64 = &MemoryRead64;
user_callbacks.MemoryReadCode = &MemoryReadCode;
user_callbacks.MemoryWrite8 = &MemoryWrite8; user_callbacks.MemoryWrite8 = &MemoryWrite8;
user_callbacks.MemoryWrite16 = &MemoryWrite16; user_callbacks.MemoryWrite16 = &MemoryWrite16;
user_callbacks.MemoryWrite32 = &MemoryWrite32; 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; Dynarmic::Arm::PSR cpsr;
cpsr.T(true); 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::GetSetElimination(ir_block);
Dynarmic::Optimization::DeadCodeElimination(ir_block); Dynarmic::Optimization::DeadCodeElimination(ir_block);
Dynarmic::Optimization::VerificationPass(ir_block); Dynarmic::Optimization::VerificationPass(ir_block);

View file

@ -15,15 +15,19 @@
static std::array<u16, 1024> code_mem{}; static std::array<u16, 1024> code_mem{};
static u32 MemoryRead32(u32 vaddr); static u32 MemoryRead32(u32 vaddr);
static u32 MemoryReadCode(u32 vaddr);
static void InterpreterFallback(u32 pc, Dynarmic::Jit* jit, void*); static void InterpreterFallback(u32 pc, Dynarmic::Jit* jit, void*);
static Dynarmic::UserCallbacks GetUserCallbacks(); static Dynarmic::UserCallbacks GetUserCallbacks();
static u32 MemoryRead32(u32 vaddr) { static u32 MemoryRead32(u32 vaddr) {
return vaddr;
}
static u32 MemoryReadCode(u32 vaddr) {
if (vaddr < code_mem.size() * sizeof(u16)) { if (vaddr < code_mem.size() * sizeof(u16)) {
size_t index = vaddr / sizeof(u16); size_t index = vaddr / sizeof(u16);
return code_mem[index] | (code_mem[index+1] << 16); 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*) { 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() { static Dynarmic::UserCallbacks GetUserCallbacks() {
Dynarmic::UserCallbacks user_callbacks{}; Dynarmic::UserCallbacks user_callbacks{};
user_callbacks.MemoryRead32 = &MemoryRead32; user_callbacks.MemoryRead32 = &MemoryRead32;
user_callbacks.MemoryReadCode = &MemoryReadCode;
user_callbacks.InterpreterFallback = &InterpreterFallback; user_callbacks.InterpreterFallback = &InterpreterFallback;
return user_callbacks; return user_callbacks;
} }

View file

@ -803,7 +803,7 @@ enum {
static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, const u32 phys_addr, ARM_INST_PTR& inst_base) { 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_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 we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM instruction
if (cpu->TFlag) { if (cpu->TFlag) {