summaryrefslogtreecommitdiff
path: root/m68k_core_x86.c
diff options
context:
space:
mode:
authorMichael Pavone <pavone@retrodev.com>2015-10-31 22:17:50 -0700
committerMichael Pavone <pavone@retrodev.com>2015-10-31 22:17:50 -0700
commit0e881e49fcf3d616c99631f56da80ec69d4f594f (patch)
treed2002e8bf49292d536026d054e23635c901786d7 /m68k_core_x86.c
parentc29cc674cf4155f3377dbdb29193db9f7456a9fe (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.c21
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