changeset 846:98d7b6073163

Implement interrupt latency. Fixes Sesame Street: Counting Cafe and gives accurate results in my test ROM
author Michael Pavone <pavone@retrodev.com>
date Sat, 31 Oct 2015 22:17:50 -0700
parents 3a18b5f63afc
children 7decd421cdc8
files blastem.c m68k_core.h m68k_core_x86.c
diffstat 3 files changed, 24 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- 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;
--- 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;
 
--- 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