# HG changeset patch # User Michael Pavone # Date 1461823884 25200 # Node ID 33a46d35b913e7a6e019ad5e62d8a69fd6f282ca # Parent d70000fdff0bf7de6575d1be69c0110d5e87c598 Implement privelege violation exceptions diff -r d70000fdff0b -r 33a46d35b913 m68k_core.c --- 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); diff -r d70000fdff0b -r 33a46d35b913 m68k_core_x86.c --- 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); diff -r d70000fdff0b -r 33a46d35b913 m68k_internal.h --- 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);