diff options
author | Michael Pavone <pavone@retrodev.com> | 2015-10-31 22:17:50 -0700 |
---|---|---|
committer | Michael Pavone <pavone@retrodev.com> | 2015-10-31 22:17:50 -0700 |
commit | 0e881e49fcf3d616c99631f56da80ec69d4f594f (patch) | |
tree | d2002e8bf49292d536026d054e23635c901786d7 /m68k_core_x86.c | |
parent | c29cc674cf4155f3377dbdb29193db9f7456a9fe (diff) |
Implement interrupt latency. Fixes Sesame Street: Counting Cafe and gives accurate results in my test ROM
Diffstat (limited to 'm68k_core_x86.c')
-rw-r--r-- | m68k_core_x86.c | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/m68k_core_x86.c b/m68k_core_x86.c index fff5855..e584190 100644 --- a/m68k_core_x86.c +++ b/m68k_core_x86.c @@ -2010,6 +2010,10 @@ void translate_m68k_andi_ori_ccr_sr(m68k_options *opts, m68kinst *inst) } if ((inst->op == M68K_ANDI_SR && (inst->src.params.immed & 0x700) != 0x700) || (inst->op == M68K_ORI_SR && inst->src.params.immed & 0x700)) { + if (inst->op == M68K_ANDI_SR) { + //set int pending flag in case we trigger an interrupt as a result of the mask change + mov_irdisp(code, 1, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B); + } call(code, opts->do_sync); } } @@ -2035,9 +2039,11 @@ void translate_m68k_eori_ccr_sr(m68k_options *opts, m68kinst *inst) if (inst->src.params.immed & 0x10) { xor_flag(opts, 1, FLAG_X); } - if (inst->op == M68K_ORI_SR) { + if (inst->op == M68K_EORI_SR) { xor_irdisp(code, inst->src.params.immed >> 8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); if (inst->src.params.immed & 0x700) { + //set int pending flag in case we trigger an interrupt as a result of the mask change + mov_irdisp(code, 1, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B); call(code, opts->do_sync); } } @@ -2065,6 +2071,10 @@ void translate_m68k_move_ccr_sr(m68k_options *opts, m68kinst *inst, host_ea *src //leave supervisor mode swap_ssp_usp(opts); } + if (((src_op->disp >> 8) & 7) < 7) { + //set int pending flag in case we trigger an interrupt as a result of the mask change + mov_irdisp(code, 1, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B); + } call(code, opts->do_sync); } cycles(&opts->gen, 12); @@ -2466,6 +2476,8 @@ void init_m68k_opts(m68k_options * opts, memmap_chunk * memmap, uint32_t num_chu } shr_ir(code, 8, opts->gen.scratch1, SZ_W); mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); + //set int pending flag in case we trigger an interrupt as a result of the mask change + mov_irdisp(code, 1, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B); retn(code); opts->set_ccr = code->cur; @@ -2499,6 +2511,13 @@ void init_m68k_opts(m68k_options * opts, memmap_chunk * memmap, uint32_t num_chu *skip_sync = code->cur - (skip_sync+1); retn(code); *do_int = code->cur - (do_int+1); + //implement 1 instruction latency + cmp_irdisp(code, 0, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B); + do_int = code->cur + 1; + jcc(code, CC_NZ, do_int); + mov_irdisp(code, 1, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B); + retn(code); + *do_int = code->cur - (do_int + 1); //set target cycle to sync cycle mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, sync_cycle), opts->gen.limit, SZ_D); //swap USP and SSP if not already in supervisor mode |