Преглед изворни кода

sh2 drc: moved host register assignment to code emitters, minor bugfixing

kub пре 4 година
родитељ
комит
9bd6706dca

+ 15 - 3
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) \

+ 12 - 4
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)

+ 23 - 9
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;

+ 27 - 2
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; \

+ 73 - 214
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);

+ 2 - 2
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__)

+ 1 - 0
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_

+ 6 - 2
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);

+ 1 - 1
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 */

+ 8 - 4
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)

+ 1 - 1
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 */

+ 2 - 5
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)