changeset 1303:208803173ebc

Implemented M68K trace mode. Some edge cases/SR update paths still need work
author Michael Pavone <pavone@retrodev.com>
date Tue, 28 Mar 2017 00:13:35 -0700
parents d2cb97ab3cff
children 5b90d7669eee
files Makefile genesis.c m68k_core.h m68k_core_x86.c trans.c
diffstat 5 files changed, 59 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Mon Mar 27 09:45:40 2017 -0700
+++ b/Makefile	Tue Mar 28 00:13:35 2017 -0700
@@ -111,7 +111,7 @@
 endif
 endif
 
-TRANSOBJS=gen.o backend.o $(MEM) arena.o
+TRANSOBJS=gen.o backend.o $(MEM) arena.o tern.o
 M68KOBJS=68kinst.o m68k_core.o
 ifeq ($(CPU),x86_64)
 M68KOBJS+= m68k_core_x86.o
--- a/genesis.c	Mon Mar 27 09:45:40 2017 -0700
+++ b/genesis.c	Tue Mar 28 00:13:35 2017 -0700
@@ -82,6 +82,11 @@
 		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;
 	}*/
+	
+	if (context->status & M68K_STATUS_TRACE) {
+		context->target_cycle = context->current_cycle;
+		return;
+	}
 
 	context->target_cycle = context->int_cycle < context->sync_cycle ? context->int_cycle : context->sync_cycle;
 	if (context->should_return) {
--- a/m68k_core.h	Mon Mar 27 09:45:40 2017 -0700
+++ b/m68k_core.h	Tue Mar 28 00:13:35 2017 -0700
@@ -21,6 +21,8 @@
 #define INT_PENDING_SR_CHANGE 254
 #define INT_PENDING_NONE 255
 
+#define M68K_STATUS_TRACE 0x80
+
 typedef void (*start_fun)(uint8_t * addr, void * context);
 
 typedef struct {
@@ -78,6 +80,7 @@
 	m68k_options    *options;
 	void            *system;
 	uint8_t         int_pending;
+	uint8_t         trace_pending;
 	uint8_t         should_return;
 	uint8_t         ram_code_flags[];
 } m68k_context;
--- a/m68k_core_x86.c	Mon Mar 27 09:45:40 2017 -0700
+++ b/m68k_core_x86.c	Tue Mar 28 00:13:35 2017 -0700
@@ -2197,7 +2197,7 @@
 			swap_ssp_usp(opts);
 		}
 		if ((inst->op == M68K_ANDI_SR && (inst->src.params.immed  & 0x700) != 0x700)
-		    || (inst->op == M68K_ORI_SR && inst->src.params.immed & 0x700)) {
+		    || (inst->op == M68K_ORI_SR && inst->src.params.immed & 0x8700)) {
 			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, INT_PENDING_SR_CHANGE, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
@@ -2929,10 +2929,17 @@
 	add_ir(code, 16-sizeof(void*), RSP, SZ_PTR);
 	uint32_t adjust_size = code->cur - opts->gen.handle_cycle_limit_int;
 	code->cur = opts->gen.handle_cycle_limit_int;
-
+	bt_irdisp(code, 7, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
+	code_ptr no_trace = code->cur + 1;
+	jcc(code, CC_NC, no_trace);
+	cmp_irdisp(code, 0, opts->gen.context_reg, offsetof(m68k_context, trace_pending), SZ_B);
+	code_ptr do_trace = code->cur + 1;
+	jcc(code, CC_NZ, do_trace);
+	mov_irdisp(code, 1, opts->gen.context_reg, offsetof(m68k_context, trace_pending), SZ_B);
+	*no_trace = code->cur - (no_trace + 1);
 	cmp_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_cycle), opts->gen.cycles, SZ_D);
-	code_ptr do_int = code->cur + 1;
-	jcc(code, CC_NC, code->cur + 2);
+	code_ptr do_int = code->cur + 2; 
+	jcc(code, CC_NC, do_int+512);//force 32-bit displacement
 	cmp_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, sync_cycle), opts->gen.cycles, SZ_D);
 	skip_sync = code->cur + 1;
 	jcc(code, CC_C, code->cur + 2);
@@ -2955,7 +2962,42 @@
 	mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, resume_pc), SZ_PTR);
 	retn(code);
 	code->stack_off = tmp_stack_off;
-	*do_int = code->cur - (do_int+1);
+	*do_trace = code->cur - (do_trace + 1);
+	//clear out trace pending flag
+	mov_irdisp(code, 0, opts->gen.context_reg, offsetof(m68k_context, trace_pending), SZ_B);
+	//save PC as stored in scratch1 for later
+	push_r(code, opts->gen.scratch1);
+	//swap USP and SSP if not already in supervisor mode
+	check_user_mode_swap_ssp_usp(opts);
+	//save status register
+	subi_areg(opts, 6, 7);
+	call(code, opts->get_sr);
+	cycles(&opts->gen, 6);
+	//save SR to stack
+	areg_to_native(opts, 7, opts->gen.scratch2);
+	call(code, opts->write_16);
+	//update the status register
+	and_irdisp(code, 0x7F, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
+	or_irdisp(code, 0x20, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
+	//save PC
+	areg_to_native(opts, 7, opts->gen.scratch2);
+	add_ir(code, 2, opts->gen.scratch2, SZ_D);
+	pop_r(code, opts->gen.scratch1);
+	call(code, opts->write_32_lowfirst);
+	//read vector
+	mov_ir(code, 0x24, opts->gen.scratch1, SZ_D);
+	call(code, opts->read_32);
+	call(code, opts->native_addr_and_sync);
+	//2 prefetch bus operations + 2 idle bus cycles
+	cycles(&opts->gen, 10);
+	//discard function return address
+	pop_r(code, opts->gen.scratch2);
+	add_ir(code, 16-sizeof(void *), RSP, SZ_PTR);
+	jmp_r(code, opts->gen.scratch1);
+	
+	code->stack_off = tmp_stack_off;
+	
+	*((uint32_t *)do_int) = code->cur - (do_int+4);
 	//implement 1 instruction latency
 	cmp_irdisp(code, INT_PENDING_NONE, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
 	do_int = code->cur + 1;
--- a/trans.c	Mon Mar 27 09:45:40 2017 -0700
+++ b/trans.c	Tue Mar 28 00:13:35 2017 -0700
@@ -24,6 +24,9 @@
 	if (context->current_cycle > 0x80000000) {
 		context->current_cycle -= 0x80000000;
 	}
+	if (context->status & 0x80) {
+		context->target_cycle = context->current_cycle;
+	}
 	return context;
 }