changeset 1363:df6af7187b36

Fix to M68K interrupt latency for most instructions. Still needs some work for RAW_IMPL instructions besides move
author Michael Pavone <pavone@retrodev.com>
date Fri, 19 May 2017 20:27:35 -0700
parents 83bdd358f3a7
children 30123ca5856c
files m68k_core.c m68k_core.h m68k_core_x86.c m68k_internal.h
diffstat 4 files changed, 54 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/m68k_core.c	Sun May 14 12:07:39 2017 -0700
+++ b/m68k_core.c	Fri May 19 20:27:35 2017 -0700
@@ -969,11 +969,15 @@
 	}
 
 	host_ea src_op, dst_op;
+	uint8_t needs_int_latch = 0;
 	if (inst->src.addr_mode != MODE_UNUSED) {
-		translate_m68k_op(inst, &src_op, opts, 0);
+		needs_int_latch |= translate_m68k_op(inst, &src_op, opts, 0);
 	}
 	if (inst->dst.addr_mode != MODE_UNUSED) {
-		translate_m68k_op(inst, &dst_op, opts, 1);
+		needs_int_latch |= translate_m68k_op(inst, &dst_op, opts, 1);
+	}
+	if (needs_int_latch) {
+		m68k_check_cycles_int_latch(opts);
 	}
 	if (info->itype == OP_FUNC) {
 		info->impl.op(opts, inst, &src_op, &dst_op);
--- a/m68k_core.h	Sun May 14 12:07:39 2017 -0700
+++ b/m68k_core.h	Fri May 19 20:27:35 2017 -0700
@@ -48,6 +48,7 @@
 	code_ptr        write_32_lowfirst;
 	code_ptr        write_32_highfirst;
 	code_ptr        do_sync;
+	code_ptr        handle_int_latch;
 	code_ptr        trap;
 	start_fun       start_context;
 	code_ptr        retrans_stub;
--- a/m68k_core_x86.c	Sun May 14 12:07:39 2017 -0700
+++ b/m68k_core_x86.c	Fri May 19 20:27:35 2017 -0700
@@ -350,12 +350,30 @@
 	calc_index_disp8(opts, op, native_reg);
 }
 
-void translate_m68k_op(m68kinst * inst, host_ea * ea, m68k_options * opts, uint8_t dst)
+void m68k_check_cycles_int_latch(m68k_options *opts)
+{
+	code_info *code = &opts->gen.code;
+	uint8_t cc;
+	if (opts->gen.limit < 0) {
+		cmp_ir(code, 1, opts->gen.cycles, SZ_D);
+		cc = CC_NS;
+	} else {
+		cmp_rr(code, opts->gen.cycles, opts->gen.limit, SZ_D);
+		cc = CC_A;
+	}
+	code_ptr jmp_off = code->cur+1;
+	jcc(code, cc, jmp_off+1);
+	call(code, opts->handle_int_latch);
+	*jmp_off = code->cur - (jmp_off+1);
+}
+
+uint8_t translate_m68k_op(m68kinst * inst, host_ea * ea, m68k_options * opts, uint8_t dst)
 {
 	code_info *code = &opts->gen.code;
 	m68k_op_info *op = dst ? &inst->dst : &inst->src;
 	int8_t reg = native_reg(op, opts);
 	uint8_t sec_reg;
+	uint8_t ret = 1;
 	int32_t dec_amount, inc_amount;
 	if (reg >= 0) {
 		ea->mode = MODE_REG_DIRECT;
@@ -365,7 +383,7 @@
 		} else {
 			ea->base = reg;
 		}
-		return;
+		return 0;
 	}
 	switch (op->addr_mode)
 	{
@@ -388,8 +406,9 @@
 			ea->mode = MODE_REG_DIRECT;
 			ea->base = opts->gen.scratch1;
 			//we're explicitly handling the areg dest here, so we exit immediately
-			return;
+			return 0;
 		}
+		ret = 0;
 		break;
 	case MODE_AREG_PREDEC:
 		if (dst && inst->src.addr_mode == MODE_AREG_PREDEC) {
@@ -505,7 +524,7 @@
 		if (inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD && ea->disp & 0x8000) {
 			ea->disp |= 0xFFFF0000;
 		}
-		return;
+		return inst->variant != VAR_QUICK;
 	default:
 		m68k_disasm(inst, disasm_buf);
 		fatal_error("%X: %s\naddress mode %d not implemented (%s)\n", inst->address, disasm_buf, op->addr_mode, dst ? "dst" : "src");
@@ -519,6 +538,7 @@
 		}
 		ea->base = opts->gen.scratch1;
 	}
+	return ret;
 }
 
 void check_user_mode_swap_ssp_usp(m68k_options *opts)
@@ -540,7 +560,9 @@
 	int32_t offset;
 	int32_t inc_amount, dec_amount;
 	host_ea src;
-	translate_m68k_op(inst, &src, opts, 0);
+	if (translate_m68k_op(inst, &src, opts, 0)) {
+		m68k_check_cycles_int_latch(opts);
+	}
 	reg = native_reg(&(inst->dst), opts);
 
 	if (inst->dst.addr_mode != MODE_AREG) {
@@ -3085,6 +3107,24 @@
 	add_ir(code, 16-sizeof(void *), RSP, SZ_PTR);
 	jmp_r(code, opts->gen.scratch1);
 	code->stack_off = tmp_stack_off;
+	
+	opts->handle_int_latch = code->cur;
+	cmp_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_cycle), opts->gen.cycles, SZ_D);
+	code_ptr do_latch = code->cur + 1; 
+	jcc(code, CC_NC, do_latch);
+	retn(code);
+	*do_latch = code->cur - (do_latch + 1);
+	cmp_irdisp(code, INT_PENDING_NONE, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
+	do_latch = code->cur + 1;
+	jcc(code, CC_Z, do_latch);
+	retn(code);
+	*do_latch = code->cur - (do_latch + 1);
+	//store current interrupt number so it doesn't change before we start processing the vector
+	push_r(code, opts->gen.scratch1);
+	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_num), opts->gen.scratch1, SZ_B);
+	mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
+	pop_r(code, opts->gen.scratch1);
+	retn(code);
 
 	opts->trap = code->cur;
 	push_r(code, opts->gen.scratch2);
--- a/m68k_internal.h	Sun May 14 12:07:39 2017 -0700
+++ b/m68k_internal.h	Fri May 19 20:27:35 2017 -0700
@@ -36,13 +36,14 @@
 void translate_m68k_odd(m68k_options *opts, m68kinst *inst);
 void m68k_trap_if_not_supervisor(m68k_options *opts, m68kinst *inst);
 void m68k_breakpoint_patch(m68k_context *context, uint32_t address, m68k_debug_handler bp_handler, code_ptr native_addr);
+void m68k_check_cycles_int_latch(m68k_options *opts);
+uint8_t translate_m68k_op(m68kinst * inst, host_ea * ea, m68k_options * opts, uint8_t dst);
 
 //functions implemented in m68k_core.c
 int8_t native_reg(m68k_op_info * op, m68k_options * opts);
 size_t dreg_offset(uint8_t reg);
 size_t areg_offset(uint8_t reg);
 size_t reg_offset(m68k_op_info *op);
-void translate_m68k_op(m68kinst * inst, host_ea * ea, m68k_options * opts, uint8_t dst);
 void m68k_read_size(m68k_options *opts, uint8_t size);
 void m68k_write_size(m68k_options *opts, uint8_t size, uint8_t lowfirst);
 void m68k_save_result(m68kinst * inst, m68k_options * opts);