changeset 1461:aa945f1bdd71

Properly clear trace mode on interrupt or other exception. Fix NBCD with memory destination
author Michael Pavone <pavone@retrodev.com>
date Wed, 06 Sep 2017 23:10:11 -0700
parents 4929325c3ce0
children d276ec2fff11
files m68k_core.c m68k_core_x86.c
diffstat 2 files changed, 17 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/m68k_core.c	Wed Sep 06 22:16:02 2017 -0700
+++ b/m68k_core.c	Wed Sep 06 23:10:11 2017 -0700
@@ -94,7 +94,9 @@
 void m68k_save_result(m68kinst * inst, m68k_options * opts)
 {
 	if (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode != MODE_AREG && inst->dst.addr_mode != MODE_UNUSED) {
-		if (inst->dst.addr_mode == MODE_AREG_PREDEC && inst->src.addr_mode == MODE_AREG_PREDEC && inst->op != M68K_MOVE) {
+		if (inst->dst.addr_mode == MODE_AREG_PREDEC && 
+			((inst->src.addr_mode == MODE_AREG_PREDEC && inst->op != M68K_MOVE) || (inst->op == M68K_NBCD))
+		) {
 			areg_to_native(opts, inst->dst.params.regs.pri, opts->gen.scratch2);
 		}
 		m68k_write_size(opts, inst->extra.size, 1);
--- a/m68k_core_x86.c	Wed Sep 06 22:16:02 2017 -0700
+++ b/m68k_core_x86.c	Wed Sep 06 23:10:11 2017 -0700
@@ -1504,6 +1504,10 @@
 			}
 		}
 	}
+	if (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode != MODE_AREG && inst->dst.addr_mode != MODE_AREG_PREDEC) {
+		//destination is in memory so we need to preserve scratch2 for the write at the end
+		push_r(code, opts->gen.scratch2);
+	}
 	uint8_t other_reg;
 	//WARNING: This may need adjustment if register assignments change
 	if (opts->gen.scratch2 > RBX) {
@@ -1592,6 +1596,10 @@
 			mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, SZ_B);
 		}
 	}
+	if (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode != MODE_AREG && inst->dst.addr_mode != MODE_AREG_PREDEC) {
+		//destination is in memory so we need to restore scratch2 for the write at the end
+		pop_r(code, opts->gen.scratch2);
+	}
 	m68k_save_result(inst, opts);
 }
 
@@ -3089,8 +3097,10 @@
 	add_rr(code, opts->gen.scratch1, RAX, SZ_D);
 
 	//update status register
-	and_irdisp(code, 0xF8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
+	and_irdisp(code, 0x78, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
 	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_num), opts->gen.scratch1, SZ_B);
+	//clear trace pending flag
+	mov_irdisp(code, 0, opts->gen.context_reg, offsetof(m68k_context, trace_pending), SZ_B);
 	//need to separate int priority and interrupt vector, but for now mask out large interrupt numbers
 	and_ir(code, 0x7, opts->gen.scratch1, SZ_B);
 	or_ir(code, 0x20, opts->gen.scratch1, SZ_B);
@@ -3158,6 +3168,9 @@
 	call(code, opts->write_16);
 	//set supervisor bit
 	or_irdisp(code, 0x20, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
+	//clear trace bit
+	and_irdisp(code, 0x7F, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
+	mov_irdisp(code, 0, opts->gen.context_reg, offsetof(m68k_context, trace_pending), SZ_B);
 	//calculate vector address
 	pop_r(code, opts->gen.scratch1);
 	shl_ir(code, 2, opts->gen.scratch1, SZ_D);