drc: split disassembly to separate pass

allows easier analysis
This commit is contained in:
notaz 2013-07-20 20:33:44 +03:00
parent 8cc76b4886
commit bf092a3631
6 changed files with 1001 additions and 338 deletions

View file

@ -1,4 +1,5 @@
typedef unsigned char u8; typedef unsigned char u8;
typedef signed char s8;
typedef unsigned short u16; typedef unsigned short u16;
typedef unsigned int u32; typedef unsigned int u32;

View file

@ -363,6 +363,9 @@ static int emith_xbranch(int cond, void *target, int is_call)
#define emith_mvn_r_r(d, s) \ #define emith_mvn_r_r(d, s) \
EOP_MVN_REG(A_COND_AL,0,d,s,A_AM1_LSL,0) EOP_MVN_REG(A_COND_AL,0,d,s,A_AM1_LSL,0)
#define emith_add_r_r_r_lsl(d, s1, s2, lslimm) \
EOP_ADD_REG(A_COND_AL,0,d,s1,s2,A_AM1_LSL,lslimm)
#define emith_or_r_r_r_lsl(d, s1, s2, lslimm) \ #define emith_or_r_r_r_lsl(d, s1, s2, lslimm) \
EOP_ORR_REG(A_COND_AL,0,d,s1,s2,A_AM1_LSL,lslimm) EOP_ORR_REG(A_COND_AL,0,d,s1,s2,A_AM1_LSL,lslimm)
@ -378,6 +381,9 @@ static int emith_xbranch(int cond, void *target, int is_call)
#define emith_eor_r_r_lsr(d, s, lsrimm) \ #define emith_eor_r_r_lsr(d, s, lsrimm) \
emith_eor_r_r_r_lsr(d, d, s, lsrimm) emith_eor_r_r_r_lsr(d, d, s, lsrimm)
#define emith_add_r_r_r(d, s1, s2) \
emith_add_r_r_r_lsl(d, s1, s2, 0)
#define emith_or_r_r_r(d, s1, s2) \ #define emith_or_r_r_r(d, s1, s2) \
emith_or_r_r_r_lsl(d, s1, s2, 0) emith_or_r_r_r_lsl(d, s1, s2, 0)
@ -385,7 +391,7 @@ static int emith_xbranch(int cond, void *target, int is_call)
emith_eor_r_r_r_lsl(d, s1, s2, 0) emith_eor_r_r_r_lsl(d, s1, s2, 0)
#define emith_add_r_r(d, s) \ #define emith_add_r_r(d, s) \
EOP_ADD_REG(A_COND_AL,0,d,d,s,A_AM1_LSL,0) emith_add_r_r_r(d, d, s)
#define emith_sub_r_r(d, s) \ #define emith_sub_r_r(d, s) \
EOP_SUB_REG(A_COND_AL,0,d,d,s,A_AM1_LSL,0) EOP_SUB_REG(A_COND_AL,0,d,d,s,A_AM1_LSL,0)
@ -715,12 +721,7 @@ static int emith_xbranch(int cond, void *target, int is_call)
#define emith_sh2_drc_exit() \ #define emith_sh2_drc_exit() \
EOP_LDMFD_SP(A_R4M|A_R5M|A_R6M|A_R7M|A_R8M|A_R9M|A_R10M|A_R11M|A_R12M|A_R15M) EOP_LDMFD_SP(A_R4M|A_R5M|A_R6M|A_R7M|A_R8M|A_R9M|A_R10M|A_R11M|A_R12M|A_R15M)
#define emith_sh2_wcall(a, tab, ret_ptr) { \ #define emith_sh2_wcall(a, tab) { \
int val_ = (char *)(ret_ptr) - (char *)tcache_ptr - 2*4; \
if (val_ >= 0) \
emith_add_r_r_imm(14, 15, val_); \
else if (val_ < 0) \
emith_sub_r_r_imm(14, 15, -val_); \
emith_lsr(12, a, SH2_WRITE_SHIFT); \ emith_lsr(12, a, SH2_WRITE_SHIFT); \
EOP_LDR_REG_LSL(A_COND_AL,12,tab,12,2); \ EOP_LDR_REG_LSL(A_COND_AL,12,tab,12,2); \
emith_ctx_read(2, offsetof(SH2, is_slave)); \ emith_ctx_read(2, offsetof(SH2, is_slave)); \

View file

@ -145,6 +145,17 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI };
} }
// _r_r_r // _r_r_r
#define emith_add_r_r_r(d, s1, s2) { \
if (d == s1) { \
emith_add_r_r(d, s2); \
} else if (d == s2) { \
emith_add_r_r(d, s1); \
} else { \
emith_move_r_r(d, s1); \
emith_add_r_r(d, s2); \
} \
}
#define emith_eor_r_r_r(d, s1, s2) { \ #define emith_eor_r_r_r(d, s1, s2) { \
if (d == s1) { \ if (d == s1) { \
emith_eor_r_r(d, s2); \ emith_eor_r_r(d, s2); \
@ -618,14 +629,13 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI };
} }
// assumes EBX is free temporary // assumes EBX is free temporary
#define emith_sh2_wcall(a, tab, ret_ptr) { \ #define emith_sh2_wcall(a, tab) { \
int arg2_; \ int arg2_; \
host_arg2reg(arg2_, 2); \ host_arg2reg(arg2_, 2); \
emith_lsr(xBX, a, SH2_WRITE_SHIFT); \ emith_lsr(xBX, a, SH2_WRITE_SHIFT); \
EMIT_OP_MODRM(0x8b, 0, xBX, 4); \ EMIT_OP_MODRM(0x8b, 0, xBX, 4); \
EMIT_SIB(2, xBX, tab); /* mov ebx, [tab + ebx * 4] */ \ EMIT_SIB(2, xBX, tab); /* mov ebx, [tab + ebx * 4] */ \
emith_ctx_read(arg2_, offsetof(SH2, is_slave)); \ emith_ctx_read(arg2_, offsetof(SH2, is_slave)); \
emith_push_imm((long)(ret_ptr)); \
emith_jump_reg(xBX); \ emith_jump_reg(xBX); \
} }

File diff suppressed because it is too large Load diff

View file

@ -7,11 +7,12 @@ void sh2_drc_wcheck_da(unsigned int a, int val, int cpuid);
#define BLOCK_INSN_LIMIT 128 #define BLOCK_INSN_LIMIT 128
#define OP_FLAGS(pc) op_flags[((pc) - (base_pc)) / 2] /* op_flags */
#define OF_DELAY_OP (1 << 0) #define OF_DELAY_OP (1 << 0)
#define OF_BTARGET (1 << 1) #define OF_BTARGET (1 << 1)
#define OF_T_SET (1 << 2) // T is known to be set #define OF_T_SET (1 << 2) // T is known to be set
#define OF_T_CLEAR (1 << 3) // ... clear #define OF_T_CLEAR (1 << 3) // ... clear
void scan_block(unsigned int base_pc, int is_slave, void scan_block(unsigned int base_pc, int is_slave,
unsigned char *op_flags, unsigned int *end_pc); unsigned char *op_flags, unsigned int *end_pc,
unsigned int *end_literals);

View file

@ -88,12 +88,14 @@ int sh2_execute(SH2 *sh2, int cycles)
{ {
#ifdef DRC_CMP #ifdef DRC_CMP
if (!sh2->delay) { if (!sh2->delay) {
if (sh2->pc < base_pc || sh2->pc > end_pc) { if (sh2->pc < base_pc || sh2->pc >= end_pc) {
base_pc = sh2->pc; base_pc = sh2->pc;
scan_block(base_pc, sh2->is_slave, scan_block(base_pc, sh2->is_slave,
op_flags, &end_pc); op_flags, &end_pc, NULL);
} }
if ((OP_FLAGS(sh2->pc) & OF_BTARGET) || sh2->pc == base_pc) { if ((op_flags[(sh2->pc - base_pc) / 2]
& OF_BTARGET) || sh2->pc == base_pc)
{
if (sh2->icount < 0) if (sh2->icount < 0)
break; break;
} }