diff m68k_core_x86.c @ 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 747c779fc137
children 5d41d0574863
line wrap: on
line diff
--- 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);