changeset 990:33a46d35b913

Implement privelege violation exceptions
author Michael Pavone <pavone@retrodev.com>
date Wed, 27 Apr 2016 23:11:24 -0700
parents d70000fdff0b
children f9ee6f746cb4
files m68k_core.c m68k_core_x86.c m68k_internal.h
diffstat 3 files changed, 29 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/m68k_core.c	Wed Apr 27 21:39:17 2016 -0700
+++ b/m68k_core.c	Wed Apr 27 23:11:24 2016 -0700
@@ -350,6 +350,7 @@
 
 void translate_m68k_move_usp(m68k_options *opts, m68kinst *inst)
 {
+	m68k_trap_if_not_supervisor(opts, inst);
 	cycles(&opts->gen, BUS);
 	int8_t reg;
 	if (inst->src.addr_mode == MODE_UNUSED) {
@@ -532,8 +533,9 @@
 
 void translate_m68k_rte(m68k_options *opts, m68kinst *inst)
 {
+	m68k_trap_if_not_supervisor(opts, inst);
+	
 	code_info *code = &opts->gen.code;
-	//TODO: Trap if not in system mode
 	//Read saved SR
 	areg_to_native(opts, 7, opts->gen.scratch1);
 	call(code, opts->read_16);
--- a/m68k_core_x86.c	Wed Apr 27 21:39:17 2016 -0700
+++ b/m68k_core_x86.c	Wed Apr 27 23:11:24 2016 -0700
@@ -1970,11 +1970,28 @@
 
 #define BIT_SUPERVISOR 5
 
+void m68k_trap_if_not_supervisor(m68k_options *opts, m68kinst *inst)
+{
+	code_info *code = &opts->gen.code;
+	//check supervisor bit in SR and trap if not in supervisor mode
+	bt_irdisp(code, BIT_SUPERVISOR, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
+	code_ptr in_sup_mode = code->cur + 1;
+	jcc(code, CC_C, code->cur + 2);
+	
+	ldi_native(opts, VECTOR_PRIV_VIOLATION, opts->gen.scratch2);
+	ldi_native(opts, inst->address, opts->gen.scratch1);
+	jmp(code, opts->trap);
+	
+	*in_sup_mode = code->cur - (in_sup_mode + 1);
+}
+
 void translate_m68k_andi_ori_ccr_sr(m68k_options *opts, m68kinst *inst)
 {
 	code_info *code = &opts->gen.code;
+	if (inst->op == M68K_ANDI_SR || inst->op == M68K_ORI_SR) {
+		m68k_trap_if_not_supervisor(opts, inst);
+	}
 	cycles(&opts->gen, 20);
-	//TODO: If ANDI to SR, trap if not in supervisor mode
 	uint32_t flag_mask = 0;
 	uint32_t base_flag = inst->op == M68K_ANDI_SR || inst->op == M68K_ANDI_CCR ? X0 : X1;
 	for (int i = 0; i < 5; i++)
@@ -2009,8 +2026,10 @@
 void translate_m68k_eori_ccr_sr(m68k_options *opts, m68kinst *inst)
 {
 	code_info *code = &opts->gen.code;
+	if (inst->op == M68K_EORI_SR) {
+		m68k_trap_if_not_supervisor(opts, inst);
+	}
 	cycles(&opts->gen, 20);
-	//TODO: If ANDI to SR, trap if not in supervisor mode
 	if (inst->src.params.immed & 0x1) {
 		xor_flag(opts, 1, FLAG_C);
 	}
@@ -2049,7 +2068,9 @@
 void translate_m68k_move_ccr_sr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
 {
 	code_info *code = &opts->gen.code;
-	//TODO: Privilege check for MOVE to SR
+	if (inst->op == M68K_MOVE_SR) {
+		m68k_trap_if_not_supervisor(opts, inst);
+	}
 	if (src_op->mode == MODE_IMMED) {
 		set_all_flags(opts, src_op->disp);
 		if (inst->op == M68K_MOVE_SR) {
@@ -2085,7 +2106,7 @@
 
 void translate_m68k_stop(m68k_options *opts, m68kinst *inst)
 {
-	//TODO: Trap if not in system mode
+	m68k_trap_if_not_supervisor(opts, inst);
 	//manual says 4 cycles, but it has to be at least 8 since it's a 2-word instruction
 	//possibly even 12 since that's how long MOVE to SR takes
 	//On further thought prefetch + the fact that this stops the CPU may make
@@ -2189,7 +2210,6 @@
 void translate_m68k_move_from_sr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
 {
 	code_info *code = &opts->gen.code;
-	//TODO: Trap if not in system mode
 	call(code, opts->get_sr);
 	if (dst_op->mode == MODE_REG_DIRECT) {
 		mov_rr(code, opts->gen.scratch1, dst_op->base, SZ_W);
--- a/m68k_internal.h	Wed Apr 27 21:39:17 2016 -0700
+++ b/m68k_internal.h	Wed Apr 27 23:11:24 2016 -0700
@@ -34,6 +34,7 @@
 void check_user_mode_swap_ssp_usp(m68k_options *opts);
 void m68k_set_last_prefetch(m68k_options *opts, uint32_t address);
 void translate_m68k_odd(m68k_options *opts, m68kinst *inst);
+void m68k_trap_if_not_supervisor(m68k_options *opts, m68kinst *inst);
 
 //functions implemented in m68k_core.c
 int8_t native_reg(m68k_op_info * op, m68k_options * opts);