From 05d7cf2c72164fed4f40e4fa53287198e37bfaee Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Wed, 16 Jan 2019 13:39:52 +0100 Subject: [PATCH] x64 dynarec: implement immediate address ram read. OSX fix --- core/rec-x64/rec_x64.cpp | 172 ++++++++++++++++++++++++++++++--------- 1 file changed, 132 insertions(+), 40 deletions(-) diff --git a/core/rec-x64/rec_x64.cpp b/core/rec-x64/rec_x64.cpp index bf77ec31c..fabecfbff 100644 --- a/core/rec-x64/rec_x64.cpp +++ b/core/rec-x64/rec_x64.cpp @@ -50,18 +50,51 @@ static __attribute((used)) void end_slice() } #endif +#ifdef __MACH__ +#define _U "_" +#else +#define _U +#endif + void ngen_mainloop(void* v_cntx) { __asm__ volatile ( "pushq %%rbx \n\t" "pushq %%rbp \n\t" +#ifdef _WIN32 "pushq %%rdi \n\t" "pushq %%rsi \n\t" +#endif "pushq %%r12 \n\t" "pushq %%r13 \n\t" "pushq %%r14 \n\t" "pushq %%r15 \n\t" "subq $8, %%rsp \n\t" // 8 for stack 16-byte alignment +#if defined(__MACH__) || defined(_ANDROID) + "movl %[_SH4_TIMESLICE], " _U "cycle_counter(%%rip) \n" + + "1: \n\t" + "movq " _U "p_sh4rcb(%%rip), %%rax \n\t" + "movl %c[CpuRunning](%%rax), %%edx \n\t" + "testl %%edx, %%edx \n\t" + "je 3f \n" + + "2: \n\t" + "movq " _U "p_sh4rcb(%%rip), %%rax \n\t" + "movl %c[pc](%%rax), %%edi \n\t" + "call " _U "bm_GetCode2 \n\t" + "call *%%rax \n\t" + "movl " _U "cycle_counter(%%rip), %%ecx \n\t" + "testl %%ecx, %%ecx \n\t" + "jg 2b \n\t" + + "addl %[_SH4_TIMESLICE], %%ecx \n\t" + "movl %%ecx, " _U "cycle_counter(%%rip) \n\t" + "call " _U "UpdateSystem_INTC \n\t" + "jmp 1b \n" + + "3: \n\t" +#else "movl %[_SH4_TIMESLICE], cycle_counter(%%rip) \n" "run_loop: \n\t" @@ -95,13 +128,16 @@ void ngen_mainloop(void* v_cntx) "jmp run_loop \n" "end_run_loop: \n\t" +#endif // !__MACH__ "addq $8, %%rsp \n\t" "popq %%r15 \n\t" "popq %%r14 \n\t" "popq %%r13 \n\t" "popq %%r12 \n\t" +#ifdef _WIN32 "popq %%rsi \n\t" "popq %%rdi \n\t" +#endif "popq %%rbp \n\t" "popq %%rbx \n\t" : @@ -255,52 +291,105 @@ public: case shop_readm: { - shil_param_to_host_reg(op.rs1, call_regs[0]); - if (!op.rs3.is_null()) - { - if (op.rs3.is_imm()) - add(call_regs[0], op.rs3._imm); - else - { - shil_param_to_host_reg(op.rs3, edx); - add(call_regs[0], edx); - } - } - u32 size = op.flags & 0x7f; - if (size == 1) { - GenCall(ReadMem8); - movsx(rcx, al); - } - else if (size == 2) { - GenCall(ReadMem16); - movsx(rcx, ax); - } - else if (size == 4) { - GenCall(ReadMem32); - mov(rcx, rax); - } - else if (size == 8) { - GenCall(ReadMem64); - mov(rcx, rax); - } - else { - die("1..8 bytes"); - } + if (op.rs1.is_imm()) + { + bool isram = false; + void* ptr = _vmem_read_const(op.rs1._imm, isram, size); - if (size != 8) - host_reg_to_shil_param(op.rd, ecx); - else { + if (isram) + { + // Immediate pointer to RAM: super-duper fast access + mov(rax, reinterpret_cast(ptr)); + switch (size) + { + case 2: + movsx(regalloc.MapRegister(op.rd), word[rax]); + break; + + case 4: + if (regalloc.IsAllocg(op.rd)) + mov(regalloc.MapRegister(op.rd), dword[rax]); + else + movd(regalloc.MapXRegister(op.rd), dword[rax]); + break; + + default: + die("Invalid immediate size"); + } + } + else + { + // Not RAM: the returned pointer is a memory handler + mov(call_regs[0], op.rs1._imm); + + switch(size) + { + case 2: + GenCall((void (*)())ptr); + movsx(ecx, ax); + break; + + case 4: + GenCall((void (*)())ptr); + mov(ecx, eax); + break; + + default: + die("Invalid immediate size"); + } + host_reg_to_shil_param(op.rd, ecx); + } + } + else + { + // Not an immediate address + shil_param_to_host_reg(op.rs1, call_regs[0]); + if (!op.rs3.is_null()) + { + if (op.rs3.is_imm()) + add(call_regs[0], op.rs3._imm); + else + { + shil_param_to_host_reg(op.rs3, edx); + add(call_regs[0], edx); + } + } + + if (size == 1) { + GenCall(ReadMem8); + movsx(ecx, al); + } + else if (size == 2) { + GenCall(ReadMem16); + movsx(ecx, ax); + } + else if (size == 4) { + GenCall(ReadMem32); + mov(ecx, eax); + } + else if (size == 8) { + GenCall(ReadMem64); + mov(rcx, rax); + } + else { + die("1..8 bytes"); + } + + if (size != 8) + host_reg_to_shil_param(op.rd, ecx); + else { #ifdef EXPLODE_SPANS - verify(op.rd.count() == 2 && regalloc.IsAllocf(op.rd, 0) && regalloc.IsAllocf(op.rd, 1)); - movd(regalloc.MapXRegister(op.rd, 0), ecx); - shr(rcx, 32); - movd(regalloc.MapXRegister(op.rd, 1), ecx); + verify(op.rd.count() == 2 && regalloc.IsAllocf(op.rd, 0) && regalloc.IsAllocf(op.rd, 1)); + movd(regalloc.MapXRegister(op.rd, 0), ecx); + shr(rcx, 32); + movd(regalloc.MapXRegister(op.rd, 1), ecx); #else - mov(rax, (uintptr_t)op.rd.reg_ptr()); - mov(qword[rax], rcx); + mov(rax, (uintptr_t)op.rd.reg_ptr()); + mov(qword[rax], rcx); #endif + } } } break; @@ -861,6 +950,9 @@ public: mov(call_regs64[regused++], (size_t)prm.reg_ptr()); break; + default: + // Other cases handled in ngen_CC_param + break; } } GenCall((void (*)())function);