From 9bd6706dca2fb8d15c9f3ae2035f4d670d07ee03 Mon Sep 17 00:00:00 2001 From: kub Date: Sat, 9 Nov 2019 10:24:52 +0100 Subject: [PATCH] sh2 drc: moved host register assignment to code emitters, minor bugfixing --- cpu/drc/emit_arm.c | 18 ++- cpu/drc/emit_arm64.c | 16 +- cpu/drc/emit_mips.c | 32 ++-- cpu/drc/emit_x86.c | 29 +++- cpu/sh2/compiler.c | 287 +++++++++--------------------------- cpu/sh2/compiler.h | 4 +- cpu/sh2/sh2.h | 1 + platform/common/disarm.c | 8 +- platform/common/disarm.h | 2 +- platform/common/dismips.c | 12 +- platform/common/dismips.h | 2 +- platform/common/host_dasm.c | 7 +- 12 files changed, 171 insertions(+), 247 deletions(-) diff --git a/cpu/drc/emit_arm.c b/cpu/drc/emit_arm.c index ec2958b1..e35d3471 100644 --- a/cpu/drc/emit_arm.c +++ b/cpu/drc/emit_arm.c @@ -6,9 +6,21 @@ * This work is licensed under the terms of MAME license. * See COPYING file in the top-level directory. */ -#define HOST_REGS 16 -#define CONTEXT_REG 11 -#define RET_REG 0 +#define HOST_REGS 16 + +// OABI/EABI: params: r0-r3, return: r0-r1, temp: r12,r14, saved: r4-r8,r10,r11 +// SP,PC: r13,r15 must not be used. saved: r9 (for platform use, e.g. on ios) +#define RET_REG 0 +#define PARAM_REGS { 0, 1, 2, 3 } +#ifndef __MACH__ +#define PRESERVED_REGS { 4, 5, 6, 7, 8, 9, 10, 11 } +#else +#define PRESERVED_REGS { 4, 5, 6, 7, 8, 10, 11 } // no r9.. +#endif +#define TEMPORARY_REGS { 12, 14 } + +#define CONTEXT_REG 11 +#define STATIC_SH2_REGS { SHR_SR,10 , SHR_R0,8 , SHR_R0+1,9 } // XXX: tcache_ptr type for SVP and SH2 compilers differs.. #define EMIT_PTR(ptr, x) \ diff --git a/cpu/drc/emit_arm64.c b/cpu/drc/emit_arm64.c index 4bad6469..0c36b2bc 100644 --- a/cpu/drc/emit_arm64.c +++ b/cpu/drc/emit_arm64.c @@ -6,8 +6,16 @@ * See COPYING file in the top-level directory. */ #define HOST_REGS 32 -#define CONTEXT_REG 19 + +// AAPCS64: params: r0-r7, return: r0-r1, temp: r8-r17, saved: r19-r29 +// reserved: r18 (for platform use) #define RET_REG 0 +#define PARAM_REGS { 0, 1, 2, 3, 4, 5, 6, 7 } +#define PRESERVED_REGS { 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 } +#define TEMPORARY_REGS { 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 } + +#define CONTEXT_REG 29 +#define STATIC_SH2_REGS { SHR_SR,28 , SHR_R0,27 , SHR_R0+1,26 } // R31 doesn't exist, it aliases either with zero or SP #define SP 31 // stack pointer @@ -100,9 +108,9 @@ enum { XT_UXTW=0x4, XT_UXTX=0x6, XT_LSL=0x7, XT_SXTW=0xc, XT_SXTX=0xe }; #define A64_NEGS_REG(rd, rm, stype, simm) \ A64_SUBS_REG(rd,Z0,rm,stype,simm) #define A64_NEGC_REG(rd, rm) \ - A64_SBC_REG(rd,Z0,rm,stype,simm) + A64_SBC_REG(rd,Z0,rm) #define A64_NEGCS_REG(rd, rm) \ - A64_SBCS_REG(rd,Z0,rm,stype,simm) + A64_SBCS_REG(rd,Z0,rm) #define A64_CMP_REG(rn, rm, stype, simm) \ A64_SUBS_REG(Z0, rn, rm, stype, simm) #define A64_CMN_REG(rn, rm, stype, simm) \ @@ -145,7 +153,7 @@ enum { XT_UXTW=0x4, XT_UXTX=0x6, XT_LSL=0x7, XT_SXTW=0xc, XT_SXTX=0xe }; A64_INSN(0xd,OP_ADD &3,0x0,_,rm,_,_,rn,rd) #define A64_ADCS_REG(rd, rn, rm) \ A64_INSN(0xd,OP_ADDS&3,0x0,_,rm,_,_,rn,rd) -#define A64_SBC_REG(rd, rn, rm, s) \ +#define A64_SBC_REG(rd, rn, rm) \ A64_INSN(0xd,OP_SUB &3,0x0,_,rm,_,_,rn,rd) #define A64_SBCS_REG(rd, rn, rm) \ A64_INSN(0xd,OP_SUBS&3,0x0,_,rm,_,_,rn,rd) diff --git a/cpu/drc/emit_mips.c b/cpu/drc/emit_mips.c index 38d68f40..832364e9 100644 --- a/cpu/drc/emit_mips.c +++ b/cpu/drc/emit_mips.c @@ -6,8 +6,17 @@ * See COPYING file in the top-level directory. */ #define HOST_REGS 32 + +// MIPS ABI: params: r4-r7, return: r2-r3, temp: r1(at),r8-r15,r24-r25,r31(ra), +// saved: r16-r23,r30, reserved: r0(zero), r26-r27(irq), r28(gp), r29(sp) +// r1,r15,r24,r25(at,t7-t9) are used internally by the code emitter +#define RET_REG 2 // v0 +#define PARAM_REGS { 4, 5, 6, 7 } // a0-a3 +#define PRESERVED_REGS { 16, 17, 18, 19, 20, 21, 22, 23 } // s0-s7 +#define TEMPORARY_REGS { 2, 3, 8, 9, 10, 11, 12, 13, 14 } // v0-v1,t0-t6 + #define CONTEXT_REG 23 // s7 -#define RET_REG 2 // v0 +#define STATIC_SH2_REGS { SHR_SR,22 , SHR_R0,21 , SHR_R0+1,20 } // NB: the ubiquitous JZ74[46]0 uses MIPS32 Release 1, a slight MIPS II superset @@ -73,7 +82,7 @@ enum { RT_BLTZ=000, RT_BGEZ, RT_BLTZAL=020, RT_BGEZAL, RT_SYNCI=037 }; #define MIPS_OP_IMM(op, rt, rs, imm) \ MIPS_INSN(op, rs, rt, _, _, (u16)(imm)) // I-type -// rd = rt OP rs +// rd = rs OP rt #define MIPS_ADD_REG(rd, rs, rt) \ MIPS_OP_REG(FN_ADDU, rd, rs, rt) #define MIPS_SUB_REG(rd, rs, rt) \ @@ -334,7 +343,7 @@ static void *emith_branch(u32 op) #define JMP_EMIT(cond, ptr) { \ u32 val_ = (u8 *)tcache_ptr - (u8 *)(ptr) - 4; \ - emith_flush(); /* NO delay slot handling across jump targets */ \ + emith_flush(); /* prohibit delay slot switching across jump targets */ \ EMIT_PTR(ptr, MIPS_BCONDZ(cond_m, cond_r, val_ & 0x0003ffff)); \ } @@ -658,14 +667,19 @@ static void emith_move_imm(int r, uintptr_t imm) EMIT_PTR(ptr_, (*ptr_ & 0xffff0000) | (u16)(s8)(imm)); \ } while (0) -// arithmetic, immediate +// arithmetic, immediate - can only be ADDI[U], since SUBI[U] doesn't exist static void emith_arith_imm(int op, int rd, int rs, u32 imm) { - if ((s16)imm != imm) { + if ((s16)imm == imm) { + if (imm || rd != rs) + EMIT(MIPS_OP_IMM(op, rd, rs, imm)); + } else if ((s32)imm < 0) { + emith_move_r_imm(AT, -imm); + EMIT(MIPS_OP_REG(FN_SUB + (op-OP_ADDI), rd, rs, AT)); + } else { emith_move_r_imm(AT, imm); EMIT(MIPS_OP_REG(FN_ADD + (op-OP_ADDI), rd, rs, AT)); - } else if (imm || rd != rs) - EMIT(MIPS_OP_IMM(op, rd, rs, imm)); + } } #define emith_add_r_imm(r, imm) \ @@ -1137,7 +1151,7 @@ static int emith_cond_check(int cond, int *r) // conditions using CZ case DCOND_LS: // C || Z case DCOND_HI: // !C && !Z - EMIT(MIPS_ADD_IMM(AT, FC, (u16)-1)); // !C && !Z + EMIT(MIPS_ADD_IMM(AT, FC, -1)); // !C && !Z EMIT(MIPS_AND_REG(AT, FNZ, AT)); *r = AT, b = (cond == DCOND_HI ? MIPS_BNE : MIPS_BEQ); break; @@ -1161,7 +1175,7 @@ static int emith_cond_check(int cond, int *r) case DCOND_GT: // !(N^V) && !Z EMIT(MIPS_LSR_IMM(AT, FV, 31)); // Nd^V = Nt^Ns^C EMIT(MIPS_XOR_REG(AT, FC, AT)); - EMIT(MIPS_ADD_IMM(AT, AT, (u16)-1)); // !(Nd^V) && !Z + EMIT(MIPS_ADD_IMM(AT, AT, -1)); // !(Nd^V) && !Z EMIT(MIPS_AND_REG(AT, FNZ, AT)); *r = AT, b = (cond == DCOND_GT ? MIPS_BNE : MIPS_BEQ); break; diff --git a/cpu/drc/emit_x86.c b/cpu/drc/emit_x86.c index 212a12c5..39f3a1d7 100644 --- a/cpu/drc/emit_x86.c +++ b/cpu/drc/emit_x86.c @@ -17,8 +17,8 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI, // x86-64,i386 common xR8, xR9, xR10, xR11, xR12, xR13, xR14, xR15 }; // x86-64 only -#define CONTEXT_REG xBP -#define RET_REG xAX +#define CONTEXT_REG xBP +#define RET_REG xAX #define ICOND_JO 0x00 #define ICOND_JNO 0x01 @@ -935,6 +935,7 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI, // x86-64,i386 common emith_ret(); \ } while (0) + #define EMITH_JMP_START(cond) { \ u8 *cond_ptr; \ JMP8_POS(cond_ptr) @@ -1006,6 +1007,14 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI, // x86-64,i386 common #ifndef _WIN32 +// SystemV ABI conventions: +// rbx,rbp,r12-r15 are preserved, rax,rcx,rdx,rsi,rdi,r8-r11 are temporaries +// parameters in rdi,rsi,rdx,rcx,r8,r9, return values in rax,rdx +#define PARAM_REGS { xDI, xSI, xDX, xCX, xR8, xR9 } +#define PRESERVED_REGS { xR12, xR13, xR14, xR15, xBX, xBP } +#define TEMPORARY_REGS { xAX, xR10, xR11 } +#define STATIC_SH2_REGS { SHR_SR,xBX , SHR_R0,xR15 } + #define host_arg2reg(rd, arg) \ switch (arg) { \ case 0: rd = xDI; break; \ @@ -1037,6 +1046,14 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI, // x86-64,i386 common #else // _WIN32 +// M$ ABI conventions: +// rbx,rbp,rsi,rdi,r12-r15 are preserved, rcx,rdx,rax,r8,r9,r10,r11 temporaries +// parameters in rcx,rdx,r8,r9, return values in rax,rdx +#define PARAM_REGS { xCX, xDX, xR8, xR9 } +#define PRESERVED_REGS { xSI, xDI, xR12, xR13, xR14, xR15, xBX, xBP } +#define TEMPORARY_REGS { xAX, xR10, xR11 } +#define STATIC_SH2_REGS { SHR_SR,xBX , SHR_R0,xR15 , SH2_R0+1,xR14 } + #define host_arg2reg(rd, arg) \ switch (arg) { \ case 0: rd = xCX; break; \ @@ -1087,6 +1104,14 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI, // x86-64,i386 common assert((u32)(rm) < 8u); \ } while (0) +// MS/SystemV ABI: ebx,esi,edi,ebp are preserved, eax,ecx,edx are temporaries +// DRC uses REGPARM to pass upto 3 parameters in registers eax,ecx,edx. +// To avoid conflicts with param passing ebx must be declared temp here. +#define PARAM_REGS { xAX, xDX, xCX } +#define PRESERVED_REGS { xSI, xDI, xBP } +#define TEMPORARY_REGS { xBX } +#define STATIC_SH2_REGS { SHR_SR,xDI , SHR_R0,xSI } + #define host_arg2reg(rd, arg) \ switch (arg) { \ case 0: rd = xAX; break; \ diff --git a/cpu/sh2/compiler.c b/cpu/sh2/compiler.c index e9173c4c..3cf7a0d9 100644 --- a/cpu/sh2/compiler.c +++ b/cpu/sh2/compiler.c @@ -427,213 +427,42 @@ typedef struct { static int rcache_get_tmp(void); static void rcache_free_tmp(int hr); -// Note: cache_regs[] must have at least the amount of REG/TEMP registers used -// by handlers in worst case (currently 4). -// Register assignment goes by ABI convention. Caller save registers are TEMP, -// the others are either static or REG. SR must be static, R0 very recommended. +// Note: Register assignment goes by ABI convention. Caller save registers are +// TEMPORARY, the others are PRESERVED. Unusable regs are omitted. +// there must be at least the free (not context or statically mapped) amount of +// PRESERVED/TEMPORARY registers used by handlers in worst case (currently 4). +// there must be at least 3 PARAM, and PARAM+TEMPORARY must be at least 4. +// SR and R0 should by all means be statically mapped. // XXX the static definition of SR MUST match that in compiler.h -// VBR, PC, PR must not be static (read from context in utils). -// RET_REG/params should be first TEMPs to avoid allocation conflicts in calls. -// There MUST be at least 3 params and one non-RET_REG/param TEMP. -// XXX shouldn't this be somehow defined in the code emitters? +// PC and PR must not be statically mapped (accessed in context by utils). + #ifdef __arm__ #include "../drc/emit_arm.c" - -static guest_reg_t guest_regs[] = { - // SHR_R0 .. SHR_SP -#ifndef __MACH__ // no r9.. - { GRF_STATIC, 8 }, { GRF_STATIC, 9 }, { 0 } , { 0 } , -#else - { GRF_STATIC, 8 }, { 0 } , { 0 } , { 0 } , -#endif - { 0 } , { 0 } , { 0 } , { 0 } , - { 0 } , { 0 } , { 0 } , { 0 } , - { 0 } , { 0 } , { 0 } , { 0 } , - // SHR_PC, SHR_PPC, SHR_PR, SHR_SR, - // SHR_GBR, SHR_VBR, SHR_MACH, SHR_MACL, - { 0 } , { 0 } , { 0 } , { GRF_STATIC, 10 }, - { 0 } , { 0 } , { 0 } , { 0 } , -}; - -// OABI/EABI: params: r0-r3, return: r0-r1, temp: r12,r14, saved: r4-r8,r10,r11 -// SP,PC: r13,r15 must not be used. saved: r9 (for platform use, e.g. on ios) -static cache_reg_t cache_regs[] = { - { 0, HRT_TEMP }, // RET_REG, params - { 1, HRT_TEMP }, - { 2, HRT_TEMP }, // params - { 3, HRT_TEMP }, - { 12, HRT_TEMP }, // temps - { 14, HRT_TEMP }, - { 8, HRT_STATIC }, // statics -#ifndef __MACH__ // no r9.. - { 9, HRT_STATIC }, -#endif - { 10, HRT_STATIC }, - { 4, HRT_REG }, // other regs - { 5, HRT_REG }, - { 6, HRT_REG }, - { 7, HRT_REG }, -}; - #elif defined(__aarch64__) #include "../drc/emit_arm64.c" - -static guest_reg_t guest_regs[] = { - // SHR_R0 .. SHR_SP - { GRF_STATIC,20 }, { GRF_STATIC,21 }, { 0 } , { 0 } , - { 0 } , { 0 } , { 0 } , { 0 } , - { 0 } , { 0 } , { 0 } , { 0 } , - { 0 } , { 0 } , { 0 } , { 0 } , - // SHR_PC, SHR_PPC, SHR_PR, SHR_SR, - // SHR_GBR, SHR_VBR, SHR_MACH, SHR_MACL, - { 0 } , { 0 } , { 0 } , { GRF_STATIC, 22 }, - { 0 } , { 0 } , { 0 } , { 0 } , -}; - -// AAPCS64: params: r0-r7, return: r0-r1, temp: r8-r17, saved: r19-r29 -// saved: r18 (for platform use) -// since drc never needs more than 4 parameters, r4-r7 are treated as temp. -static cache_reg_t cache_regs[] = { - { 0, HRT_TEMP }, // RET_REG, params - { 1, HRT_TEMP }, - { 2, HRT_TEMP }, // params - { 3, HRT_TEMP }, - { 4, HRT_TEMP }, // temps - { 5, HRT_TEMP }, - { 6, HRT_TEMP }, - { 7, HRT_TEMP }, - { 8, HRT_TEMP }, - { 9, HRT_TEMP }, - { 10, HRT_TEMP }, - { 11, HRT_TEMP }, - { 12, HRT_TEMP }, - { 13, HRT_TEMP }, - { 14, HRT_TEMP }, - { 15, HRT_TEMP }, - { 16, HRT_TEMP }, - { 17, HRT_TEMP }, - { 20, HRT_STATIC }, // statics - { 21, HRT_STATIC }, - { 22, HRT_STATIC }, - { 23, HRT_REG }, // other regs - { 24, HRT_REG }, - { 25, HRT_REG }, - { 26, HRT_REG }, - { 27, HRT_REG }, - { 28, HRT_REG }, - { 29, HRT_REG }, -}; - #elif defined(__mips__) #include "../drc/emit_mips.c" - -static guest_reg_t guest_regs[] = { - // SHR_R0 .. SHR_SP - {GRF_STATIC, 16} , {GRF_STATIC, 17} , { 0 } , { 0 } , - { 0 } , { 0 } , { 0 } , { 0 } , - { 0 } , { 0 } , { 0 } , { 0 } , - { 0 } , { 0 } , { 0 } , { 0 } , - // SHR_PC, SHR_PPC, SHR_PR, SHR_SR, - // SHR_GBR, SHR_VBR, SHR_MACH, SHR_MACL, - { 0 } , { 0 } , { 0 } , {GRF_STATIC, 18} , - { 0 } , { 0 } , { 0 } , { 0 } , -}; - -// MIPS ABI: params: r4-r7, return: r2-r3, temp: r1(at),r8-r15,r24-r25,r31(ra), -// saved: r16-r23,r30, reserved: r0(zero), r26-r27(irq), r28(gp), r29(sp) -// r1,r15,r24,r25 are used internally by the code emitter -static cache_reg_t cache_regs[] = { - { 2, HRT_TEMP }, // RET_REG (v0-v1) - { 3, HRT_TEMP }, - { 4, HRT_TEMP }, // params (a0-a3) - { 5, HRT_TEMP }, - { 6, HRT_TEMP }, - { 7, HRT_TEMP }, - { 8, HRT_TEMP }, // temps (t0-t6) - { 9, HRT_TEMP }, - { 10, HRT_TEMP }, - { 11, HRT_TEMP }, - { 12, HRT_TEMP }, - { 13, HRT_TEMP }, - { 14, HRT_TEMP }, - { 16, HRT_STATIC }, // statics (s0-s2) - { 17, HRT_STATIC }, - { 18, HRT_STATIC }, - { 19, HRT_REG }, // other regs (s3-s6) - { 20, HRT_REG }, - { 21, HRT_REG }, - { 22, HRT_REG }, -}; - #elif defined(__i386__) #include "../drc/emit_x86.c" - -static guest_reg_t guest_regs[] = { - // SHR_R0 .. SHR_SP - {GRF_STATIC, xSI}, { 0 } , { 0 } , { 0 } , - { 0 } , { 0 } , { 0 } , { 0 } , - { 0 } , { 0 } , { 0 } , { 0 } , - { 0 } , { 0 } , { 0 } , { 0 } , - // SHR_PC, SHR_PPC, SHR_PR, SHR_SR, - // SHR_GBR, SHR_VBR, SHR_MACH, SHR_MACL, - { 0 } , { 0 } , { 0 } , {GRF_STATIC, xDI}, - { 0 } , { 0 } , { 0 } , { 0 } , -}; - -// MS/SystemV ABI: ebx,esi,edi,ebp are preserved, eax,ecx,edx are temporaries -// DRC uses REGPARM to pass upto 3 parameters in registers eax,ecx,edx. -// To avoid conflicts with param passing ebx must be declared temp here. -static cache_reg_t cache_regs[] = { - { xAX, HRT_TEMP }, // RET_REG, param - { xDX, HRT_TEMP }, // params - { xCX, HRT_TEMP }, - { xBX, HRT_TEMP }, // temp - { xSI, HRT_STATIC }, // statics - { xDI, HRT_STATIC }, -}; - #elif defined(__x86_64__) #include "../drc/emit_x86.c" - -static guest_reg_t guest_regs[] = { - // SHR_R0 .. SHR_SP - {GRF_STATIC,xR12}, { 0 } , { 0 } , { 0 } , - { 0 } , { 0 } , { 0 } , { 0 } , - { 0 } , { 0 } , { 0 } , { 0 } , - { 0 } , { 0 } , { 0 } , { 0 } , - // SHR_PC, SHR_PPC, SHR_PR, SHR_SR, - // SHR_GBR, SHR_VBR, SHR_MACH, SHR_MACL, - { 0 } , { 0 } , { 0 } , {GRF_STATIC, xBX}, - { 0 } , { 0 } , { 0 } , { 0 } , -}; - -// M$/SystemV ABI conventions: -// rbx,rbp,r12-r15 are preserved, rcx,rdx,rax,r8,r9,r10,r11 are temporaries -// rsi,rdi are preserved in M$ ABI, temporary in SystemV ABI -// parameters in rcx,rdx,r8,r9, SystemV ABI additionally uses rsi,rdi -static cache_reg_t cache_regs[] = { - { xAX, HRT_TEMP }, // RET_REG - { xDX, HRT_TEMP }, // params - { xCX, HRT_TEMP }, - { xDI, HRT_TEMP }, - { xSI, HRT_TEMP }, - { xR8, HRT_TEMP }, - { xR9, HRT_TEMP }, - { xR10,HRT_TEMP }, // temps - { xR11,HRT_TEMP }, - { xBX, HRT_STATIC }, // statics - { xR12,HRT_STATIC }, - { xR13,HRT_REG }, // other regs - { xR14,HRT_REG }, - { xR15,HRT_REG }, -}; - #else #error unsupported arch #endif +static const signed char hregs_param[] = PARAM_REGS; +static const signed char hregs_temp [] = TEMPORARY_REGS; +static const signed char hregs_saved[] = PRESERVED_REGS; +static const signed char regs_static[] = STATIC_SH2_REGS; + +#define CACHE_REGS \ + (ARRAY_SIZE(hregs_param)+ARRAY_SIZE(hregs_temp)+ARRAY_SIZE(hregs_saved)-1) +static cache_reg_t cache_regs[CACHE_REGS]; + static signed char reg_map_host[HOST_REGS]; +static guest_reg_t guest_regs[SH2_REGS]; + static void REGPARM(1) (*sh2_drc_entry)(SH2 *sh2); static void REGPARM(1) (*sh2_drc_dispatcher)(u32 pc); #if CALL_STACK @@ -884,15 +713,15 @@ static void dr_block_link(struct block_entry *be, struct block_link *bl, int emi // via blx: @jump near jumpcc to blx; @blx far jump emith_jump_patch(jump, bl->blx, &jump); emith_jump_at(bl->blx, be->tcache_ptr); - if ((((uintptr_t)bl->blx & 0xf) + emith_jump_at_size()-1) > 0xf) + if ((((uintptr_t)bl->blx & 0x1f) + emith_jump_at_size()-1) > 0x1f) host_instructions_updated(bl->blx, bl->blx + emith_jump_at_size()-1); } } else { printf("unknown BL type %d\n", bl->type); exit(1); } - // only needs sync if patch is possibly crossing cacheline (assume 16 byte) - if ((((uintptr_t)jump & 0xf) + jsz-1) > 0xf) + // only needs sync if patch is possibly crossing cacheline (assume 32 byte) + if ((((uintptr_t)jump & 0x1f) + jsz-1) > 0x1f) host_instructions_updated(jump, jump + jsz-1); } @@ -1653,7 +1482,7 @@ static void gconst_invalidate(void) static u16 rcache_counter; // SH2 register usage bitmasks -static u32 rcache_hregs_reg; // regs of type HRT_REG (for pinning) +static u32 rcache_vregs_reg; // regs of type HRT_REG (for pinning) static u32 rcache_regs_static; // statically allocated regs static u32 rcache_regs_pinned; // pinned regs static u32 rcache_regs_now; // regs used in current insn @@ -2548,30 +2377,60 @@ static void rcache_flush(void) rcache_invalidate(); } -static void rcache_init(void) +static void rcache_create(void) { - static int once = 1; - int i; + int x = 0, i; + + // create cache_regs as host register representation + // RET_REG/params should be first TEMPs to avoid allocation conflicts in calls + cache_regs[x++] = (cache_reg_t) {.hreg = RET_REG, .htype = HRT_TEMP}; + for (i = 0; i < ARRAY_SIZE(hregs_param); i++) + if (hregs_param[i] != RET_REG) + cache_regs[x++] = (cache_reg_t){.hreg = hregs_param[i],.htype = HRT_TEMP}; + + for (i = 0; i < ARRAY_SIZE(hregs_temp); i++) + if (hregs_temp[i] != RET_REG) + cache_regs[x++] = (cache_reg_t){.hreg = hregs_temp[i], .htype = HRT_TEMP}; + + for (i = ARRAY_SIZE(hregs_saved)-1; i >= 0; i--) + if (hregs_saved[i] != CONTEXT_REG) + cache_regs[x++] = (cache_reg_t){.hreg = hregs_saved[i], .htype = HRT_REG}; - // init is executed on every rom load, but this must only be executed once... - if (once) { - memset(reg_map_host, -1, sizeof(reg_map_host)); - for (i = 0; i < ARRAY_SIZE(cache_regs); i++) { + if (x != ARRAY_SIZE(cache_regs)) { + printf("rcache_create failed (conflicting register count)\n"); + exit(1); + } + + // mapping from host_register to cache regs index + memset(reg_map_host, -1, sizeof(reg_map_host)); + for (i = 0; i < ARRAY_SIZE(cache_regs); i++) { + if (cache_regs[i].htype) reg_map_host[cache_regs[i].hreg] = i; - if (cache_regs[i].htype == HRT_REG) - rcache_hregs_reg |= (1 << i); - } + if (cache_regs[i].htype == HRT_REG) + rcache_vregs_reg |= (1 << i); + } - for (i = 0; i < ARRAY_SIZE(guest_regs); i++) - if (guest_regs[i].flags & GRF_STATIC) { - rcache_regs_static |= (1 << i); - guest_regs[i].sreg = reg_map_host[guest_regs[i].sreg]; - rcache_hregs_reg &= ~(1 << guest_regs[i].sreg); - } else - guest_regs[i].sreg = -1; - once = 0; + // create static host register mapping for SH2 regs + for (i = 0; i < ARRAY_SIZE(regs_static); i += 2) { + for (x = ARRAY_SIZE(cache_regs)-1; x >= 0; x--) + if (cache_regs[x].hreg == regs_static[i+1]) break; + if (x >= 0) { + guest_regs[regs_static[i]] = (guest_reg_t){.flags = GRF_STATIC,.sreg = x}; + rcache_regs_static |= (1 << regs_static[i]); + rcache_vregs_reg &= ~(1 << x); + } else + guest_regs[regs_static[i]] = (guest_reg_t){.sreg = -1}; } + printf("DRC registers created, %ld host regs (%d REG, %d STATIC, 1 CTX)\n", + CACHE_REGS+1L, count_bits(rcache_vregs_reg),count_bits(rcache_regs_static)); +} + +static void rcache_init(void) +{ + // create DRC data structures + rcache_create(); + rcache_invalidate(); #if DRC_DEBUG & 64 RCACHE_CHECK("after init"); @@ -5038,8 +4897,8 @@ static void sh2_generate_utils(void) emith_move_r_r_ptr(arg0, CONTEXT_REG); emith_call_ctx(offsetof(SH2, irq_callback)); // vector = sh2->irq_callback(sh2, level); // obtain new PC - emith_ctx_read(arg1, SHR_VBR * 4); - emith_add_r_r_r_lsl(arg0, arg1, RET_REG, 2); + tmp = rcache_get_reg_arg(1, SHR_VBR, &tmp2); + emith_add_r_r_r_lsl(arg0, tmp2, RET_REG, 2); emith_call(sh2_drc_read32); if (arg0 != RET_REG) emith_move_r_r(arg0, RET_REG); diff --git a/cpu/sh2/compiler.h b/cpu/sh2/compiler.h index 5f374c8c..415f01ba 100644 --- a/cpu/sh2/compiler.h +++ b/cpu/sh2/compiler.h @@ -38,9 +38,9 @@ unsigned short scan_block(unsigned int base_pc, int is_slave, #if defined(__arm__) #define DRC_SR_REG "r10" #elif defined(__aarch64__) -#define DRC_SR_REG "r22" +#define DRC_SR_REG "r28" #elif defined(__mips__) -#define DRC_SR_REG "s2" +#define DRC_SR_REG "s6" #elif defined(__i386__) #define DRC_SR_REG "edi" #elif defined(__x86_64__) diff --git a/cpu/sh2/sh2.h b/cpu/sh2/sh2.h index 05ae7052..5f1a8841 100644 --- a/cpu/sh2/sh2.h +++ b/cpu/sh2/sh2.h @@ -8,6 +8,7 @@ typedef enum { SHR_R0 = 0, SHR_SP = 15, SHR_PC, SHR_PPC, SHR_PR, SHR_SR, SHR_GBR, SHR_VBR, SHR_MACH, SHR_MACL, + SH2_REGS // register set size } sh2_reg_e; typedef struct SH2_ diff --git a/platform/common/disarm.c b/platform/common/disarm.c index 80655877..37fd810e 100644 --- a/platform/common/disarm.c +++ b/platform/common/disarm.c @@ -435,8 +435,10 @@ static int software_interrupt(unsigned int pc, unsigned int insn, char *buf, siz return 1; } -int disarm(uintptr_t pc, uint32_t insn, char *buf, size_t buf_len) +int disarm(uintptr_t pc, uint32_t insn, char *buf, size_t buf_len, uintptr_t *addr) { + *addr = 0; + if ((insn & 0x0fffffd0) == 0x012fff10) return branch_and_exchange(pc, insn, buf, buf_len); @@ -464,8 +466,10 @@ int disarm(uintptr_t pc, uint32_t insn, char *buf, size_t buf_len) if ((insn & 0x0e000000) == 0x08000000) return block_data_transfer(pc, insn, buf, buf_len); - if ((insn & 0x0e000000) == 0x0a000000) + if ((insn & 0x0e000000) == 0x0a000000) { + *addr = (long)pc + 8 + ((long)(insn << 8) >> 6); return branch(pc, insn, buf, buf_len); + } if ((insn & 0x0e000000) == 0x0c000000) return coprocessor_data_transfer(pc, insn, buf, buf_len); diff --git a/platform/common/disarm.h b/platform/common/disarm.h index b8634f68..f1170894 100644 --- a/platform/common/disarm.h +++ b/platform/common/disarm.h @@ -23,6 +23,6 @@ #ifndef DISARM_H #define DISARM_H -int disarm(uintptr_t long pc, uint32_t, char *buf, unsigned int buf_len); +int disarm(uintptr_t pc, uint32_t insn, char *buf, size_t buf_len, uintptr_t *sym); #endif /* DISARM_H */ diff --git a/platform/common/dismips.c b/platform/common/dismips.c index af71b095..41c0f7a5 100644 --- a/platform/common/dismips.c +++ b/platform/common/dismips.c @@ -274,7 +274,7 @@ static unsigned long j_target(unsigned long pc, uint32_t insn) } // main disassembler function -int dismips(uintptr_t pc, uint32_t insn, char *buf, unsigned int buflen) +int dismips(uintptr_t pc, uint32_t insn, char *buf, size_t buflen, uintptr_t *sym) { const struct insn *pi = decode_insn(insn); char *rs = register_names[(insn >> 21) & 0x1f]; @@ -283,6 +283,7 @@ int dismips(uintptr_t pc, uint32_t insn, char *buf, unsigned int buflen) int sa = (insn >> 6) & 0x1f; int imm = (int16_t) insn; + *sym = 0; if (pi == NULL) { snprintf(buf, buflen, "0x%x", insn); return 0; @@ -314,13 +315,16 @@ int dismips(uintptr_t pc, uint32_t insn, char *buf, unsigned int buflen) snprintf(buf, buflen, "%s %s, %s, %d", pi->name, rd, rt, sa); break; case B_IMM_S: - snprintf(buf, buflen, "%s %s, 0x%lx", pi->name, rs, b_target(pc, insn)); + *sym = b_target(pc, insn); + snprintf(buf, buflen, "%s %s, 0x%lx", pi->name, rs, *sym); break; case B_IMM_TS: - snprintf(buf, buflen, "%s %s, %s, 0x%lx", pi->name, rs, rt, b_target(pc, insn)); + *sym = b_target(pc, insn); + snprintf(buf, buflen, "%s %s, %s, 0x%lx", pi->name, rs, rt, *sym); break; case J_IMM: - snprintf(buf, buflen, "%s 0x%lx", pi->name, j_target(pc, insn)); + *sym = j_target(pc, insn); + snprintf(buf, buflen, "%s 0x%lx", pi->name, *sym); break; case A_IMM_TS: if (abs(imm) < 1000) diff --git a/platform/common/dismips.h b/platform/common/dismips.h index e6338def..b547003b 100644 --- a/platform/common/dismips.h +++ b/platform/common/dismips.h @@ -1,6 +1,6 @@ #ifndef DISMIPS_H #define DISMIPS_H -int dismips(uintptr_t pc, uint32_t insn, char *buf, unsigned int buf_len); +int dismips(uintptr_t pc, uint32_t insn, char *buf, size_t buf_len, uintptr_t *sym); #endif /* DISMIPS_H */ diff --git a/platform/common/host_dasm.c b/platform/common/host_dasm.c index d0537ef6..fc3cbe67 100644 --- a/platform/common/host_dasm.c +++ b/platform/common/host_dasm.c @@ -46,13 +46,10 @@ void host_dasm(void *addr, int len) insn = *(long *)addr; printf(" %08lx %08lx ", (long)addr, insn); - if(disasm((unsigned)addr, insn, buf, sizeof(buf))) + if(disasm((unsigned)addr, insn, buf, sizeof(buf), &symaddr)) { - symaddr = 0; - if ((insn & 0xe000000) == 0xa000000) { - symaddr = (long)addr + 8 + ((long)(insn << 8) >> 6); + if (symaddr) name = lookup_name((void *)symaddr); - } if (symaddr && name) printf("%s <%s>\n", buf, name); else if (symaddr && !name) -- 2.39.5