mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 15:27:46 -04:00
debug stuff, bug fixing
This commit is contained in:
parent
ff0eaa11d9
commit
e267031a50
4 changed files with 185 additions and 62 deletions
|
@ -510,12 +510,12 @@ static int emith_xbranch(int cond, void *target, int is_call)
|
||||||
emith_top_imm(A_COND_AL, A_OP_TST, r, imm)
|
emith_top_imm(A_COND_AL, A_OP_TST, r, imm)
|
||||||
|
|
||||||
#define emith_cmp_r_imm(r, imm) { \
|
#define emith_cmp_r_imm(r, imm) { \
|
||||||
u32 op = A_OP_CMP, imm_ = imm; \
|
u32 op_ = A_OP_CMP, imm_ = (u8)imm; \
|
||||||
if (~imm_ < 0x100) { \
|
if ((s8)imm_ < 0) { \
|
||||||
imm_ = -imm_; \
|
imm_ = (u8)-imm_; \
|
||||||
op = A_OP_CMN; \
|
op_ = A_OP_CMN; \
|
||||||
} \
|
} \
|
||||||
emith_top_imm(A_COND_AL, op, r, imm); \
|
emith_top_imm(A_COND_AL, op_, r, imm_); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define emith_subf_r_imm(r, imm) \
|
#define emith_subf_r_imm(r, imm) \
|
||||||
|
|
|
@ -53,6 +53,9 @@
|
||||||
// 04 - asm
|
// 04 - asm
|
||||||
// 08 - runtime block entry log
|
// 08 - runtime block entry log
|
||||||
// 10 - smc self-check
|
// 10 - smc self-check
|
||||||
|
// 100 - write trace
|
||||||
|
// 200 - compare trace
|
||||||
|
// 400 - print block entry backtrace
|
||||||
// {
|
// {
|
||||||
#ifndef DRC_DEBUG
|
#ifndef DRC_DEBUG
|
||||||
#define DRC_DEBUG 0
|
#define DRC_DEBUG 0
|
||||||
|
@ -73,6 +76,7 @@ static int insns_compiled, hash_collisions, host_insn_count;
|
||||||
#define dbg(...)
|
#define dbg(...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
#define FETCH_OP(pc) \
|
#define FETCH_OP(pc) \
|
||||||
dr_pc_base[(pc) / 2]
|
dr_pc_base[(pc) / 2]
|
||||||
|
@ -147,13 +151,86 @@ static char sh2dasm_buff[64];
|
||||||
#define do_host_disasm(x)
|
#define do_host_disasm(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (DRC_DEBUG & 8) || defined(PDB)
|
#if (DRC_DEBUG & (8|256|512|1024)) || defined(PDB)
|
||||||
|
|
||||||
|
#define SH2_DUMP(sh2, reason) { \
|
||||||
|
char ms = (sh2)->is_slave ? 's' : 'm'; \
|
||||||
|
printf("%csh2 %s %08x\n", ms, reason, (sh2)->pc); \
|
||||||
|
printf("%csh2 r0-7 %08x %08x %08x %08x %08x %08x %08x %08x\n", ms, \
|
||||||
|
(sh2)->r[0], (sh2)->r[1], (sh2)->r[2], (sh2)->r[3], \
|
||||||
|
(sh2)->r[4], (sh2)->r[5], (sh2)->r[6], (sh2)->r[7]); \
|
||||||
|
printf("%csh2 r8-15 %08x %08x %08x %08x %08x %08x %08x %08x\n", ms, \
|
||||||
|
(sh2)->r[8], (sh2)->r[9], (sh2)->r[10], (sh2)->r[11], \
|
||||||
|
(sh2)->r[12], (sh2)->r[13], (sh2)->r[14], (sh2)->r[15]); \
|
||||||
|
printf("%csh2 pc-ml %08x %08x %08x %08x %08x %08x %08x %08x\n", ms, \
|
||||||
|
(sh2)->pc, (sh2)->ppc, (sh2)->pr, (sh2)->sr&0x3ff, \
|
||||||
|
(sh2)->gbr, (sh2)->vbr, (sh2)->mach, (sh2)->macl); \
|
||||||
|
printf("%csh2 tmp-p %08x %08x %08x %08x %08x %08x %08x %08x\n", ms, \
|
||||||
|
(sh2)->drc_tmp, (sh2)->irq_cycles, \
|
||||||
|
(sh2)->pdb_io_csum[0], (sh2)->pdb_io_csum[1], (sh2)->state, \
|
||||||
|
(sh2)->poll_addr, (sh2)->poll_cycles, (sh2)->poll_cnt); \
|
||||||
|
}
|
||||||
|
static SH2 csh2[2][4];
|
||||||
static void REGPARM(3) *sh2_drc_log_entry(void *block, SH2 *sh2, u32 sr)
|
static void REGPARM(3) *sh2_drc_log_entry(void *block, SH2 *sh2, u32 sr)
|
||||||
{
|
{
|
||||||
if (block != NULL) {
|
if (block != NULL) {
|
||||||
dbg(8, "= %csh2 enter %08x %p, c=%d", sh2->is_slave ? 's' : 'm',
|
dbg(8, "= %csh2 enter %08x %p, c=%d", sh2->is_slave ? 's' : 'm',
|
||||||
sh2->pc, block, (signed int)sr >> 12);
|
sh2->pc, block, (signed int)sr >> 12);
|
||||||
|
#if defined PDB
|
||||||
pdb_step(sh2, sh2->pc);
|
pdb_step(sh2, sh2->pc);
|
||||||
|
#elif (DRC_DEBUG & 256)
|
||||||
|
{
|
||||||
|
static FILE *trace[2];
|
||||||
|
int idx = sh2->is_slave;
|
||||||
|
if (sh2 != &sh2s[0] && sh2 != &sh2s[1]) printf("sh2 %p?\n",sh2);
|
||||||
|
if (!trace[0]) {
|
||||||
|
truncate("pico.trace", 0);
|
||||||
|
trace[0] = fopen("pico.trace0", "wb");
|
||||||
|
trace[1] = fopen("pico.trace1", "wb");
|
||||||
|
}
|
||||||
|
if (csh2[idx][0].pc != sh2->pc) {
|
||||||
|
fwrite(sh2, offsetof(SH2, read8_map), 1, trace[idx]);
|
||||||
|
fwrite(&sh2->pdb_io_csum, sizeof(sh2->pdb_io_csum), 1, trace[idx]);
|
||||||
|
memcpy(&csh2[idx][0], sh2, offsetof(SH2, icount));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#elif (DRC_DEBUG & 512)
|
||||||
|
{
|
||||||
|
static FILE *trace[2];
|
||||||
|
static SH2 fsh2;
|
||||||
|
int idx = sh2->is_slave;
|
||||||
|
if (!trace[0]) {
|
||||||
|
trace[0] = fopen("pico.trace0", "rb");
|
||||||
|
trace[1] = fopen("pico.trace1", "rb");
|
||||||
|
}
|
||||||
|
if (csh2[idx][0].pc != sh2->pc) {
|
||||||
|
if (!fread(&fsh2, offsetof(SH2, read8_map), 1, trace[idx]) ||
|
||||||
|
!fread(&fsh2.pdb_io_csum, sizeof(sh2->pdb_io_csum), 1, trace[idx])) {
|
||||||
|
printf("trace eof at %08lx\n",ftell(trace[idx]));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
fsh2.sr = (fsh2.sr & 0xfff) | (sh2->sr & ~0xfff);
|
||||||
|
fsh2.is_slave = idx;
|
||||||
|
if (memcmp(&fsh2, sh2, offsetof(SH2, read8_map)) ||
|
||||||
|
0)//memcmp(&fsh2.pdb_io_csum, &sh2->pdb_io_csum, sizeof(sh2->pdb_io_csum)))
|
||||||
|
{
|
||||||
|
printf("difference at %08lx!\n",ftell(trace[idx]));
|
||||||
|
SH2_DUMP(&fsh2, "file");
|
||||||
|
SH2_DUMP(sh2, "current");
|
||||||
|
SH2_DUMP(&csh2[idx][0], "previous");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
csh2[idx][0] = fsh2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#elif (DRC_DEBUG & 1024)
|
||||||
|
{
|
||||||
|
int x = sh2->is_slave, i;
|
||||||
|
for (i = 0; i < ARRAY_SIZE(csh2[x]); i++)
|
||||||
|
memcpy(&csh2[x][i], &csh2[x][i+1], offsetof(SH2, icount));
|
||||||
|
memcpy(&csh2[x][3], sh2, offsetof(SH2, icount));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
@ -759,13 +836,18 @@ static u32 dr_gcregs_mask;
|
||||||
static u32 dr_gcregs_dirty;
|
static u32 dr_gcregs_dirty;
|
||||||
|
|
||||||
#if PROPAGATE_CONSTANTS
|
#if PROPAGATE_CONSTANTS
|
||||||
|
static void gconst_set(sh2_reg_e r, u32 val)
|
||||||
|
{
|
||||||
|
dr_gcregs_mask |= 1 << r;
|
||||||
|
dr_gcregs[r] = val;
|
||||||
|
}
|
||||||
|
|
||||||
static void gconst_new(sh2_reg_e r, u32 val)
|
static void gconst_new(sh2_reg_e r, u32 val)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
dr_gcregs_mask |= 1 << r;
|
gconst_set(r, val);
|
||||||
dr_gcregs_dirty |= 1 << r;
|
dr_gcregs_dirty |= 1 << r;
|
||||||
dr_gcregs[r] = val;
|
|
||||||
|
|
||||||
// throw away old r that we might have cached
|
// throw away old r that we might have cached
|
||||||
for (i = ARRAY_SIZE(reg_temp) - 1; i >= 0; i--) {
|
for (i = ARRAY_SIZE(reg_temp) - 1; i >= 0; i--) {
|
||||||
|
@ -818,6 +900,17 @@ static void gconst_kill(sh2_reg_e r)
|
||||||
dr_gcregs_dirty &= ~(1 << r);
|
dr_gcregs_dirty &= ~(1 << r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if PROPAGATE_CONSTANTS
|
||||||
|
static void gconst_copy(sh2_reg_e rd, sh2_reg_e rs)
|
||||||
|
{
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
gconst_kill(rd);
|
||||||
|
if (gconst_get(rs, &val))
|
||||||
|
gconst_set(rd, val);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void gconst_clean(void)
|
static void gconst_clean(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -1104,7 +1197,7 @@ static void rcache_unlock_all(void)
|
||||||
reg_temp[i].flags &= ~HRF_LOCKED;
|
reg_temp[i].flags &= ~HRF_LOCKED;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DRC_CMP
|
#if (DRC_DEBUG & (8|256|512|1024)) || defined(DRC_CMP)
|
||||||
static u32 rcache_used_hreg_mask(void)
|
static u32 rcache_used_hreg_mask(void)
|
||||||
{
|
{
|
||||||
u32 mask = 0;
|
u32 mask = 0;
|
||||||
|
@ -1202,18 +1295,13 @@ static void emit_move_r_imm32(sh2_reg_e dst, u32 imm)
|
||||||
static void emit_move_r_r(sh2_reg_e dst, sh2_reg_e src)
|
static void emit_move_r_r(sh2_reg_e dst, sh2_reg_e src)
|
||||||
{
|
{
|
||||||
int hr_d, hr_s;
|
int hr_d, hr_s;
|
||||||
u32 val;
|
|
||||||
|
|
||||||
|
hr_s = rcache_get_reg(src, RC_GR_READ);
|
||||||
|
hr_d = rcache_get_reg(dst, RC_GR_WRITE);
|
||||||
|
emith_move_r_r(hr_d, hr_s);
|
||||||
#if PROPAGATE_CONSTANTS
|
#if PROPAGATE_CONSTANTS
|
||||||
if (gconst_get(src, &val))
|
gconst_copy(dst, src);
|
||||||
gconst_new(dst, val);
|
|
||||||
else
|
|
||||||
#endif
|
#endif
|
||||||
{
|
|
||||||
hr_s = rcache_get_reg(src, RC_GR_READ);
|
|
||||||
hr_d = rcache_get_reg(dst, RC_GR_WRITE);
|
|
||||||
emith_move_r_r(hr_d, hr_s);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// T must be clear, and comparison done just before this
|
// T must be clear, and comparison done just before this
|
||||||
|
@ -1231,7 +1319,7 @@ static int emit_memhandler_read(int size)
|
||||||
|
|
||||||
rcache_clean();
|
rcache_clean();
|
||||||
|
|
||||||
#ifndef DCR_SR_REG
|
#ifndef DRC_SR_REG
|
||||||
// must writeback cycles for poll detection stuff
|
// must writeback cycles for poll detection stuff
|
||||||
if (reg_map_g2h[SHR_SR] != -1)
|
if (reg_map_g2h[SHR_SR] != -1)
|
||||||
emith_ctx_write(reg_map_g2h[SHR_SR], SHR_SR * 4);
|
emith_ctx_write(reg_map_g2h[SHR_SR], SHR_SR * 4);
|
||||||
|
@ -1244,7 +1332,7 @@ static int emit_memhandler_read(int size)
|
||||||
case 2: emith_call(sh2_drc_read32); break; // 32
|
case 2: emith_call(sh2_drc_read32); break; // 32
|
||||||
}
|
}
|
||||||
rcache_invalidate();
|
rcache_invalidate();
|
||||||
#ifndef DCR_SR_REG
|
#ifndef DRC_SR_REG
|
||||||
if (reg_map_g2h[SHR_SR] != -1)
|
if (reg_map_g2h[SHR_SR] != -1)
|
||||||
emith_ctx_read(reg_map_g2h[SHR_SR], SHR_SR * 4);
|
emith_ctx_read(reg_map_g2h[SHR_SR], SHR_SR * 4);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1255,7 +1343,7 @@ static int emit_memhandler_read(int size)
|
||||||
static void emit_memhandler_write(int size)
|
static void emit_memhandler_write(int size)
|
||||||
{
|
{
|
||||||
int arg2;
|
int arg2;
|
||||||
#ifndef DCR_SR_REG
|
#ifndef DRC_SR_REG
|
||||||
if (reg_map_g2h[SHR_SR] != -1)
|
if (reg_map_g2h[SHR_SR] != -1)
|
||||||
emith_ctx_write(reg_map_g2h[SHR_SR], SHR_SR * 4);
|
emith_ctx_write(reg_map_g2h[SHR_SR], SHR_SR * 4);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1270,7 +1358,7 @@ static void emit_memhandler_write(int size)
|
||||||
}
|
}
|
||||||
|
|
||||||
rcache_invalidate();
|
rcache_invalidate();
|
||||||
#ifndef DCR_SR_REG
|
#ifndef DRC_SR_REG
|
||||||
if (reg_map_g2h[SHR_SR] != -1)
|
if (reg_map_g2h[SHR_SR] != -1)
|
||||||
emith_ctx_read(reg_map_g2h[SHR_SR], SHR_SR * 4);
|
emith_ctx_read(reg_map_g2h[SHR_SR], SHR_SR * 4);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1287,8 +1375,8 @@ static int emit_memhandler_read_rr(sh2_reg_e rd, sh2_reg_e rs, u32 offs, int siz
|
||||||
hr2 = rcache_get_tmp();
|
hr2 = rcache_get_tmp();
|
||||||
emith_move_r_imm(hr2, val);
|
emith_move_r_imm(hr2, val);
|
||||||
} else {
|
} else {
|
||||||
gconst_new(rd, val);
|
emit_move_r_imm32(rd, val);
|
||||||
hr2 = rcache_get_reg(rd, RC_GR_RMW);
|
hr2 = rcache_get_reg(rd, RC_GR_READ);
|
||||||
}
|
}
|
||||||
return hr2;
|
return hr2;
|
||||||
}
|
}
|
||||||
|
@ -1296,7 +1384,10 @@ static int emit_memhandler_read_rr(sh2_reg_e rd, sh2_reg_e rs, u32 offs, int siz
|
||||||
if (gconst_get(rs, &val)) {
|
if (gconst_get(rs, &val)) {
|
||||||
hr = emit_get_rbase_and_offs(val + offs, &offs2);
|
hr = emit_get_rbase_and_offs(val + offs, &offs2);
|
||||||
if (hr != -1) {
|
if (hr != -1) {
|
||||||
hr2 = rcache_get_reg(rd, RC_GR_WRITE);
|
if (rd == SHR_TMP)
|
||||||
|
hr2 = rcache_get_tmp();
|
||||||
|
else
|
||||||
|
hr2 = rcache_get_reg(rd, RC_GR_WRITE);
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case 0: // 8
|
case 0: // 8
|
||||||
emith_read8s_r_r_offs(hr2, hr, offs2 ^ 1);
|
emith_read8s_r_r_offs(hr2, hr, offs2 ^ 1);
|
||||||
|
@ -1323,13 +1414,18 @@ static int emit_memhandler_read_rr(sh2_reg_e rd, sh2_reg_e rs, u32 offs, int siz
|
||||||
emith_add_r_imm(hr, offs);
|
emith_add_r_imm(hr, offs);
|
||||||
}
|
}
|
||||||
hr = emit_memhandler_read(size);
|
hr = emit_memhandler_read(size);
|
||||||
hr2 = rcache_get_reg(rd, RC_GR_WRITE);
|
if (rd == SHR_TMP)
|
||||||
if (size != 2) {
|
hr2 = hr;
|
||||||
emith_sext(hr2, hr, (size == 1) ? 16 : 8);
|
else
|
||||||
} else
|
hr2 = rcache_get_reg(rd, RC_GR_WRITE);
|
||||||
emith_move_r_r(hr2, hr);
|
|
||||||
rcache_free_tmp(hr);
|
|
||||||
|
|
||||||
|
if (rd != SHR_TMP && size != 2) {
|
||||||
|
emith_sext(hr2, hr, (size == 1) ? 16 : 8);
|
||||||
|
} else if (hr != hr2)
|
||||||
|
emith_move_r_r(hr2, hr);
|
||||||
|
|
||||||
|
if (hr != hr2)
|
||||||
|
rcache_free_tmp(hr);
|
||||||
return hr2;
|
return hr2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1339,6 +1435,7 @@ static void emit_memhandler_write_rr(sh2_reg_e rd, sh2_reg_e rs, u32 offs, int s
|
||||||
int hr;
|
int hr;
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
|
rcache_clean(); // XXX
|
||||||
rcache_get_reg_arg(1, rd);
|
rcache_get_reg_arg(1, rd);
|
||||||
|
|
||||||
if (gconst_get(rs, &val)) {
|
if (gconst_get(rs, &val)) {
|
||||||
|
@ -1375,7 +1472,7 @@ static int emit_indirect_indexed_read(sh2_reg_e rd, sh2_reg_e rx, sh2_reg_e ry,
|
||||||
else
|
else
|
||||||
hr2 = hr;
|
hr2 = hr;
|
||||||
|
|
||||||
if (size != 2) { // 16, 8
|
if (rd != SHR_TMP && size != 2) { // 16, 8
|
||||||
emith_sext(hr2, hr, size ? 16 : 8);
|
emith_sext(hr2, hr, size ? 16 : 8);
|
||||||
} else if (hr != hr2) // 32
|
} else if (hr != hr2) // 32
|
||||||
emith_move_r_r(hr2, hr);
|
emith_move_r_r(hr2, hr);
|
||||||
|
@ -1397,6 +1494,7 @@ static void emit_indirect_indexed_write(sh2_reg_e rd, sh2_reg_e rx, sh2_reg_e ry
|
||||||
if (gconst_get(rx, &offs))
|
if (gconst_get(rx, &offs))
|
||||||
return emit_memhandler_write_rr(rd, ry, offs, size);
|
return emit_memhandler_write_rr(rd, ry, offs, size);
|
||||||
#endif
|
#endif
|
||||||
|
rcache_clean(); // XXX
|
||||||
rcache_get_reg_arg(1, rd);
|
rcache_get_reg_arg(1, rd);
|
||||||
a0 = rcache_get_reg_arg(0, rx);
|
a0 = rcache_get_reg_arg(0, rx);
|
||||||
t = rcache_get_reg(ry, RC_GR_READ);
|
t = rcache_get_reg(ry, RC_GR_READ);
|
||||||
|
@ -1459,17 +1557,6 @@ static void emit_do_static_regs(int is_write, int tmpr)
|
||||||
/* just after lookup function, jump to address returned */
|
/* just after lookup function, jump to address returned */
|
||||||
static void emit_block_entry(void)
|
static void emit_block_entry(void)
|
||||||
{
|
{
|
||||||
#if (DRC_DEBUG & 8) || defined(PDB)
|
|
||||||
int arg1, arg2;
|
|
||||||
host_arg2reg(arg1, 1);
|
|
||||||
host_arg2reg(arg2, 2);
|
|
||||||
|
|
||||||
emit_do_static_regs(1, arg2);
|
|
||||||
emith_move_r_r_ptr(arg1, CONTEXT_REG);
|
|
||||||
emith_move_r_r(arg2, rcache_get_reg(SHR_SR, RC_GR_READ));
|
|
||||||
emith_call(sh2_drc_log_entry);
|
|
||||||
rcache_invalidate();
|
|
||||||
#endif
|
|
||||||
emith_tst_r_r_ptr(RET_REG, RET_REG);
|
emith_tst_r_r_ptr(RET_REG, RET_REG);
|
||||||
EMITH_SJMP_START(DCOND_EQ);
|
EMITH_SJMP_START(DCOND_EQ);
|
||||||
emith_jump_reg_c(DCOND_NE, RET_REG);
|
emith_jump_reg_c(DCOND_NE, RET_REG);
|
||||||
|
@ -1675,6 +1762,24 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
|
||||||
emith_jump_cond(DCOND_LE, sh2_drc_exit);
|
emith_jump_cond(DCOND_LE, sh2_drc_exit);
|
||||||
do_host_disasm(tcache_id);
|
do_host_disasm(tcache_id);
|
||||||
rcache_unlock_all();
|
rcache_unlock_all();
|
||||||
|
|
||||||
|
#if (DRC_DEBUG & (8|256|512|1024))
|
||||||
|
emit_move_r_imm32(SHR_PC, pc);
|
||||||
|
sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
|
||||||
|
FLUSH_CYCLES(sr);
|
||||||
|
rcache_clean();
|
||||||
|
tmp = rcache_used_hreg_mask();
|
||||||
|
emith_save_caller_regs(tmp);
|
||||||
|
emit_do_static_regs(1, 0);
|
||||||
|
rcache_get_reg_arg(2, SHR_SR);
|
||||||
|
tmp2 = rcache_get_tmp_arg(0);
|
||||||
|
tmp3 = rcache_get_tmp_arg(1);
|
||||||
|
emith_move_r_imm(tmp2, (u32)tcache_ptr);
|
||||||
|
emith_move_r_r_ptr(tmp3,CONTEXT_REG);
|
||||||
|
emith_call(sh2_drc_log_entry);
|
||||||
|
emith_restore_caller_regs(tmp);
|
||||||
|
rcache_invalidate();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DRC_CMP
|
#ifdef DRC_CMP
|
||||||
|
@ -1729,7 +1834,10 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
|
||||||
emith_move_r_imm(tmp, pc);
|
emith_move_r_imm(tmp, pc);
|
||||||
emith_tst_r_imm(sr, T);
|
emith_tst_r_imm(sr, T);
|
||||||
tmp2 = ops[i-1].op == OP_BRANCH_CT ? DCOND_NE : DCOND_EQ;
|
tmp2 = ops[i-1].op == OP_BRANCH_CT ? DCOND_NE : DCOND_EQ;
|
||||||
|
tmp3 = ops[i-1].op == OP_BRANCH_CT ? DCOND_EQ : DCOND_NE;
|
||||||
|
EMITH_SJMP_START(tmp3);
|
||||||
emith_move_r_imm_c(tmp2, tmp, ops[i-1].imm);
|
emith_move_r_imm_c(tmp2, tmp, ops[i-1].imm);
|
||||||
|
EMITH_SJMP_END(tmp3);
|
||||||
break;
|
break;
|
||||||
case OP_BRANCH_N:
|
case OP_BRANCH_N:
|
||||||
emit_move_r_imm32(SHR_PC, pc);
|
emit_move_r_imm32(SHR_PC, pc);
|
||||||
|
@ -1765,7 +1873,6 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
|
||||||
drcf.pending_branch_direct = 1;
|
drcf.pending_branch_direct = 1;
|
||||||
} else {
|
} else {
|
||||||
emit_move_r_r(SHR_PC, opd->rm);
|
emit_move_r_r(SHR_PC, opd->rm);
|
||||||
ops[i+1].source |= SHR_PC; // need PC for jump after delay slot
|
|
||||||
drcf.pending_branch_indirect = 1;
|
drcf.pending_branch_indirect = 1;
|
||||||
}
|
}
|
||||||
goto end_op;
|
goto end_op;
|
||||||
|
@ -1785,7 +1892,6 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
|
||||||
emith_move_r_r(tmp3, tmp);
|
emith_move_r_r(tmp3, tmp);
|
||||||
}
|
}
|
||||||
emith_add_r_r(tmp, tmp2);
|
emith_add_r_r(tmp, tmp2);
|
||||||
ops[i+1].source |= SHR_PC; // need PC for jump after delay slot
|
|
||||||
drcf.pending_branch_indirect = 1;
|
drcf.pending_branch_indirect = 1;
|
||||||
}
|
}
|
||||||
goto end_op;
|
goto end_op;
|
||||||
|
@ -1813,7 +1919,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
|
||||||
case OP_UNDEFINED:
|
case OP_UNDEFINED:
|
||||||
elprintf_sh2(sh2, EL_ANOMALY,
|
elprintf_sh2(sh2, EL_ANOMALY,
|
||||||
"drc: illegal op %04x @ %08x", op, pc - 2);
|
"drc: illegal op %04x @ %08x", op, pc - 2);
|
||||||
opd->imm = 4;
|
opd->imm = (op_flags[i] & OF_B_IN_DS) ? 6 : 4;
|
||||||
// fallthrough
|
// fallthrough
|
||||||
case OP_TRAPA:
|
case OP_TRAPA:
|
||||||
tmp = rcache_get_reg(SHR_SP, RC_GR_RMW);
|
tmp = rcache_get_reg(SHR_SP, RC_GR_RMW);
|
||||||
|
@ -1827,7 +1933,13 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
|
||||||
// push PC
|
// push PC
|
||||||
rcache_get_reg_arg(0, SHR_SP);
|
rcache_get_reg_arg(0, SHR_SP);
|
||||||
tmp = rcache_get_tmp_arg(1);
|
tmp = rcache_get_tmp_arg(1);
|
||||||
emith_move_r_imm(tmp, pc);
|
if (op == OP_TRAPA)
|
||||||
|
emith_move_r_imm(tmp, pc);
|
||||||
|
else if (drcf.pending_branch_indirect) {
|
||||||
|
tmp2 = rcache_get_reg(SHR_PC, RC_GR_READ);
|
||||||
|
emith_move_r_r(tmp, tmp2);
|
||||||
|
} else
|
||||||
|
emith_move_r_imm(tmp, pc - 2);
|
||||||
emit_memhandler_write(2);
|
emit_memhandler_write(2);
|
||||||
// obtain new PC
|
// obtain new PC
|
||||||
emit_memhandler_read_rr(SHR_PC, SHR_VBR, opd->imm * 4, 2);
|
emit_memhandler_read_rr(SHR_PC, SHR_VBR, opd->imm * 4, 2);
|
||||||
|
@ -1988,7 +2100,6 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
|
||||||
goto end_op;
|
goto end_op;
|
||||||
case 0x0f: // MAC.L @Rm+,@Rn+ 0000nnnnmmmm1111
|
case 0x0f: // MAC.L @Rm+,@Rn+ 0000nnnnmmmm1111
|
||||||
emit_indirect_read_double(&tmp, &tmp2, GET_Rn(), GET_Rm(), 2);
|
emit_indirect_read_double(&tmp, &tmp2, GET_Rn(), GET_Rm(), 2);
|
||||||
|
|
||||||
sr = rcache_get_reg(SHR_SR, RC_GR_READ);
|
sr = rcache_get_reg(SHR_SR, RC_GR_READ);
|
||||||
tmp3 = rcache_get_reg(SHR_MACL, RC_GR_RMW);
|
tmp3 = rcache_get_reg(SHR_MACL, RC_GR_RMW);
|
||||||
tmp4 = rcache_get_reg(SHR_MACH, RC_GR_RMW);
|
tmp4 = rcache_get_reg(SHR_MACH, RC_GR_RMW);
|
||||||
|
@ -2087,12 +2198,12 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
|
||||||
case 0x0e: // MULU.W Rm,Rn 0010nnnnmmmm1110
|
case 0x0e: // MULU.W Rm,Rn 0010nnnnmmmm1110
|
||||||
case 0x0f: // MULS.W Rm,Rn 0010nnnnmmmm1111
|
case 0x0f: // MULS.W Rm,Rn 0010nnnnmmmm1111
|
||||||
tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
|
tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ);
|
||||||
|
tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
|
||||||
tmp = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
|
tmp = rcache_get_reg(SHR_MACL, RC_GR_WRITE);
|
||||||
if (op & 1) {
|
if (op & 1) {
|
||||||
emith_sext(tmp, tmp2, 16);
|
emith_sext(tmp, tmp2, 16);
|
||||||
} else
|
} else
|
||||||
emith_clear_msb(tmp, tmp2, 16);
|
emith_clear_msb(tmp, tmp2, 16);
|
||||||
tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ);
|
|
||||||
tmp2 = rcache_get_tmp();
|
tmp2 = rcache_get_tmp();
|
||||||
if (op & 1) {
|
if (op & 1) {
|
||||||
emith_sext(tmp2, tmp3, 16);
|
emith_sext(tmp2, tmp3, 16);
|
||||||
|
@ -2308,7 +2419,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
|
||||||
}
|
}
|
||||||
tmp2 = rcache_get_reg(GET_Rn(), RC_GR_RMW);
|
tmp2 = rcache_get_reg(GET_Rn(), RC_GR_RMW);
|
||||||
emith_sub_r_imm(tmp2, 4);
|
emith_sub_r_imm(tmp2, 4);
|
||||||
rcache_clean();
|
rcache_clean(); // XXX
|
||||||
rcache_get_reg_arg(0, GET_Rn());
|
rcache_get_reg_arg(0, GET_Rn());
|
||||||
tmp3 = rcache_get_reg_arg(1, tmp);
|
tmp3 = rcache_get_reg_arg(1, tmp);
|
||||||
if (tmp == SHR_SR)
|
if (tmp == SHR_SR)
|
||||||
|
@ -2444,6 +2555,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
|
||||||
emith_bic_r_imm(sr, T);
|
emith_bic_r_imm(sr, T);
|
||||||
emith_cmp_r_imm(tmp, 0);
|
emith_cmp_r_imm(tmp, 0);
|
||||||
emit_or_t_if_eq(sr);
|
emit_or_t_if_eq(sr);
|
||||||
|
rcache_clean(); // XXX
|
||||||
emith_or_r_imm(tmp, 0x80);
|
emith_or_r_imm(tmp, 0x80);
|
||||||
tmp2 = rcache_get_tmp_arg(1); // assuming it differs to tmp
|
tmp2 = rcache_get_tmp_arg(1); // assuming it differs to tmp
|
||||||
emith_move_r_r(tmp2, tmp);
|
emith_move_r_r(tmp2, tmp);
|
||||||
|
@ -2596,7 +2708,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
|
||||||
goto end_op;
|
goto end_op;
|
||||||
case 0x0800: // CMP/EQ #imm,R0 10001000iiiiiiii
|
case 0x0800: // CMP/EQ #imm,R0 10001000iiiiiiii
|
||||||
// XXX: could use cmn
|
// XXX: could use cmn
|
||||||
tmp2 = rcache_get_reg(0, RC_GR_READ);
|
tmp2 = rcache_get_reg(SHR_R0, RC_GR_READ);
|
||||||
sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
|
sr = rcache_get_reg(SHR_SR, RC_GR_RMW);
|
||||||
emith_bic_r_imm(sr, T);
|
emith_bic_r_imm(sr, T);
|
||||||
emith_cmp_r_imm(tmp2, (s8)(op & 0xff));
|
emith_cmp_r_imm(tmp2, (s8)(op & 0xff));
|
||||||
|
@ -2679,10 +2791,11 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
default_:
|
default_:
|
||||||
if (!(op_flags[i] & OF_B_IN_DS))
|
if (!(op_flags[i] & OF_B_IN_DS)) {
|
||||||
elprintf_sh2(sh2, EL_ANOMALY,
|
elprintf_sh2(sh2, EL_ANOMALY,
|
||||||
"drc: illegal op %04x @ %08x", op, pc - 2);
|
"drc: illegal op %04x @ %08x", op, pc - 2);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
end_op:
|
end_op:
|
||||||
|
@ -3268,6 +3381,15 @@ void block_stats(void)
|
||||||
|
|
||||||
void sh2_drc_flush_all(void)
|
void sh2_drc_flush_all(void)
|
||||||
{
|
{
|
||||||
|
#if (DRC_DEBUG & 1024)
|
||||||
|
int i;
|
||||||
|
printf("backtrace master:\n");
|
||||||
|
for (i = 0; i < ARRAY_SIZE(csh2[0]); i++)
|
||||||
|
SH2_DUMP(&csh2[0][i], "bt msh2");
|
||||||
|
printf("backtrace slave:\n");
|
||||||
|
for (i = 0; i < ARRAY_SIZE(csh2[1]); i++)
|
||||||
|
SH2_DUMP(&csh2[1][i], "bt ssh2");
|
||||||
|
#endif
|
||||||
block_stats();
|
block_stats();
|
||||||
flush_tcache(0);
|
flush_tcache(0);
|
||||||
flush_tcache(1);
|
flush_tcache(1);
|
||||||
|
@ -4200,13 +4322,14 @@ void scan_block(u32 base_pc, int is_slave, u8 *op_flags, u32 *end_pc_out,
|
||||||
if (op_flags[i] & OF_DELAY_OP) {
|
if (op_flags[i] & OF_DELAY_OP) {
|
||||||
switch (opd->op) {
|
switch (opd->op) {
|
||||||
case OP_BRANCH:
|
case OP_BRANCH:
|
||||||
|
case OP_BRANCH_N:
|
||||||
case OP_BRANCH_CT:
|
case OP_BRANCH_CT:
|
||||||
case OP_BRANCH_CF:
|
case OP_BRANCH_CF:
|
||||||
case OP_BRANCH_R:
|
case OP_BRANCH_R:
|
||||||
case OP_BRANCH_RF:
|
case OP_BRANCH_RF:
|
||||||
elprintf(EL_ANOMALY, "%csh2 drc: branch in DS @ %08x",
|
elprintf(EL_ANOMALY, "%csh2 drc: branch in DS @ %08x",
|
||||||
is_slave ? 's' : 'm', pc);
|
is_slave ? 's' : 'm', pc);
|
||||||
opd->op = OP_UNHANDLED;
|
opd->op = OP_UNDEFINED;
|
||||||
op_flags[i] |= OF_B_IN_DS;
|
op_flags[i] |= OF_B_IN_DS;
|
||||||
next_is_delay = 0;
|
next_is_delay = 0;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -29,9 +29,9 @@ void scan_block(unsigned int base_pc, int is_slave,
|
||||||
#if defined(DRC_SH2)
|
#if defined(DRC_SH2)
|
||||||
// direct access to some host CPU registers used by the DRC
|
// direct access to some host CPU registers used by the DRC
|
||||||
// XXX MUST match definitions in cpu/sh2/compiler.c
|
// XXX MUST match definitions in cpu/sh2/compiler.c
|
||||||
#if defined(_arm__)
|
#if defined(__arm__)
|
||||||
#define DRC_SR_REG r10
|
#define DRC_SR_REG r10
|
||||||
#elif defined(__i386__)
|
#elif defined(__i386__) || defined(__x86_64__)
|
||||||
#define DRC_SR_REG edi
|
#define DRC_SR_REG edi
|
||||||
#else
|
#else
|
||||||
#warning "direct DRC register access not available for this host"
|
#warning "direct DRC register access not available for this host"
|
||||||
|
|
|
@ -1344,7 +1344,7 @@ out_noprint:
|
||||||
|
|
||||||
static u32 sh2_read16_da(u32 a, SH2 *sh2)
|
static u32 sh2_read16_da(u32 a, SH2 *sh2)
|
||||||
{
|
{
|
||||||
return ((u16 *)sh2->data_array)[(a & 0xfff) / 2];
|
return ((u16 *)sh2->data_array)[(a & 0xffe) / 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 sh2_read16_rom(u32 a, SH2 *sh2)
|
static u32 sh2_read16_rom(u32 a, SH2 *sh2)
|
||||||
|
@ -1367,7 +1367,7 @@ static u32 sh2_read32_cs0(u32 a, SH2 *sh2)
|
||||||
|
|
||||||
static u32 sh2_read32_da(u32 a, SH2 *sh2)
|
static u32 sh2_read32_da(u32 a, SH2 *sh2)
|
||||||
{
|
{
|
||||||
u32 d = *(u32 *)(sh2->data_array + (a & 0xfff));
|
u32 d = *((u32 *)sh2->data_array + (a & 0xffc)/4);
|
||||||
return (d << 16) | (d >> 16);
|
return (d << 16) | (d >> 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1587,28 +1587,28 @@ static void REGPARM(3) sh2_write32_dram1(u32 a, u32 d, SH2 *sh2)
|
||||||
|
|
||||||
static void REGPARM(3) sh2_write32_sdram(u32 a, u32 d, SH2 *sh2)
|
static void REGPARM(3) sh2_write32_sdram(u32 a, u32 d, SH2 *sh2)
|
||||||
{
|
{
|
||||||
u32 a1 = a & 0x3ffff;
|
u32 a1 = a & 0x3fffc;
|
||||||
*(u32 *)(sh2->p_sdram + a1) = (d << 16) | (d >> 16);
|
*(u32 *)(sh2->p_sdram + a1) = (d << 16) | (d >> 16);
|
||||||
#ifdef DRC_SH2
|
#ifdef DRC_SH2
|
||||||
unsigned short *p = &Pico32xMem->drcblk_ram[a1 >> SH2_DRCBLK_RAM_SHIFT];
|
unsigned short *p = &Pico32xMem->drcblk_ram[a1 >> SH2_DRCBLK_RAM_SHIFT];
|
||||||
if (p[0])
|
if (p[0])
|
||||||
sh2_drc_wcheck_ram(a, p[0], sh2->is_slave);
|
sh2_drc_wcheck_ram(a, p[0], sh2->is_slave);
|
||||||
if (p[1])
|
if (p[1])
|
||||||
sh2_drc_wcheck_ram(a, p[1], sh2->is_slave);
|
sh2_drc_wcheck_ram(a+2, p[1], sh2->is_slave);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void REGPARM(3) sh2_write32_da(u32 a, u32 d, SH2 *sh2)
|
static void REGPARM(3) sh2_write32_da(u32 a, u32 d, SH2 *sh2)
|
||||||
{
|
{
|
||||||
u32 a1 = a & 0xfff;
|
u32 a1 = a & 0xffc;
|
||||||
*(u32 *)(sh2->data_array + a1) = (d << 16) | (d >> 16);
|
*((u32 *)sh2->data_array + a1/4) = (d << 16) | (d >> 16);
|
||||||
#ifdef DRC_SH2
|
#ifdef DRC_SH2
|
||||||
int id = sh2->is_slave;
|
int id = sh2->is_slave;
|
||||||
unsigned short *p = &Pico32xMem->drcblk_da[id][a1 >> SH2_DRCBLK_DA_SHIFT];
|
unsigned short *p = &Pico32xMem->drcblk_da[id][a1 >> SH2_DRCBLK_DA_SHIFT];
|
||||||
if (p[0])
|
if (p[0])
|
||||||
sh2_drc_wcheck_da(a, p[0], id);
|
sh2_drc_wcheck_da(a, p[0], id);
|
||||||
if (p[1])
|
if (p[1])
|
||||||
sh2_drc_wcheck_da(a, p[1], id);
|
sh2_drc_wcheck_da(a+2, p[1], id);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue