# HG changeset patch # User Michael Pavone # Date 1446355070 25200 # Node ID 98d7b6073163b1d7b739a7a16c86dc8a276a184c # Parent 3a18b5f63afcf3552d439fb7cef41aca47d9e333 Implement interrupt latency. Fixes Sesame Street: Counting Cafe and gives accurate results in my test ROM diff -r 3a18b5f63afc -r 98d7b6073163 blastem.c --- a/blastem.c Sat Oct 31 21:11:40 2015 -0700 +++ b/blastem.c Sat Oct 31 22:17:50 2015 -0700 @@ -156,6 +156,9 @@ } } } + if (context->int_cycle > context->current_cycle) { + context->int_pending = 0; + } /*if (context->int_cycle != old_int_cycle) { printf("int cycle changed to: %d, level: %d @ %d(%d), frame: %d, vcounter: %d, hslot: %d, mask: %d, hint_counter: %d\n", context->int_cycle, context->int_num, v_context->cycles, context->current_cycle, v_context->frame, v_context->vcounter, v_context->hslot, context->status & 0x7, v_context->hint_counter); old_int_cycle = context->int_cycle; diff -r 3a18b5f63afc -r 98d7b6073163 m68k_core.h --- a/m68k_core.h Sat Oct 31 21:11:40 2015 -0700 +++ b/m68k_core.h Sat Oct 31 22:17:50 2015 -0700 @@ -59,11 +59,11 @@ uint32_t int_num; uint16_t *mem_pointers[NUM_MEM_AREAS]; void *video_context; - uint16_t reserved; native_map_slot *native_code_map; m68k_options *options; void *system; + uint8_t int_pending; uint8_t ram_code_flags[]; } m68k_context; diff -r 3a18b5f63afc -r 98d7b6073163 m68k_core_x86.c --- a/m68k_core_x86.c Sat Oct 31 21:11:40 2015 -0700 +++ b/m68k_core_x86.c Sat Oct 31 22:17:50 2015 -0700 @@ -2010,6 +2010,10 @@ } 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 @@ 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 @@ //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 @@ } 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 @@ *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