Mercurial > repos > blastem
comparison m68k_core_x86.c @ 990:33a46d35b913
Implement privelege violation exceptions
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Wed, 27 Apr 2016 23:11:24 -0700 |
parents | d70000fdff0b |
children | 784bc1e45e80 |
comparison
equal
deleted
inserted
replaced
989:d70000fdff0b | 990:33a46d35b913 |
---|---|
1968 } | 1968 } |
1969 } | 1969 } |
1970 | 1970 |
1971 #define BIT_SUPERVISOR 5 | 1971 #define BIT_SUPERVISOR 5 |
1972 | 1972 |
1973 void m68k_trap_if_not_supervisor(m68k_options *opts, m68kinst *inst) | |
1974 { | |
1975 code_info *code = &opts->gen.code; | |
1976 //check supervisor bit in SR and trap if not in supervisor mode | |
1977 bt_irdisp(code, BIT_SUPERVISOR, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); | |
1978 code_ptr in_sup_mode = code->cur + 1; | |
1979 jcc(code, CC_C, code->cur + 2); | |
1980 | |
1981 ldi_native(opts, VECTOR_PRIV_VIOLATION, opts->gen.scratch2); | |
1982 ldi_native(opts, inst->address, opts->gen.scratch1); | |
1983 jmp(code, opts->trap); | |
1984 | |
1985 *in_sup_mode = code->cur - (in_sup_mode + 1); | |
1986 } | |
1987 | |
1973 void translate_m68k_andi_ori_ccr_sr(m68k_options *opts, m68kinst *inst) | 1988 void translate_m68k_andi_ori_ccr_sr(m68k_options *opts, m68kinst *inst) |
1974 { | 1989 { |
1975 code_info *code = &opts->gen.code; | 1990 code_info *code = &opts->gen.code; |
1991 if (inst->op == M68K_ANDI_SR || inst->op == M68K_ORI_SR) { | |
1992 m68k_trap_if_not_supervisor(opts, inst); | |
1993 } | |
1976 cycles(&opts->gen, 20); | 1994 cycles(&opts->gen, 20); |
1977 //TODO: If ANDI to SR, trap if not in supervisor mode | |
1978 uint32_t flag_mask = 0; | 1995 uint32_t flag_mask = 0; |
1979 uint32_t base_flag = inst->op == M68K_ANDI_SR || inst->op == M68K_ANDI_CCR ? X0 : X1; | 1996 uint32_t base_flag = inst->op == M68K_ANDI_SR || inst->op == M68K_ANDI_CCR ? X0 : X1; |
1980 for (int i = 0; i < 5; i++) | 1997 for (int i = 0; i < 5; i++) |
1981 { | 1998 { |
1982 if ((base_flag == X0) ^ ((inst->src.params.immed & 1 << i) > 0)) | 1999 if ((base_flag == X0) ^ ((inst->src.params.immed & 1 << i) > 0)) |
2007 } | 2024 } |
2008 | 2025 |
2009 void translate_m68k_eori_ccr_sr(m68k_options *opts, m68kinst *inst) | 2026 void translate_m68k_eori_ccr_sr(m68k_options *opts, m68kinst *inst) |
2010 { | 2027 { |
2011 code_info *code = &opts->gen.code; | 2028 code_info *code = &opts->gen.code; |
2029 if (inst->op == M68K_EORI_SR) { | |
2030 m68k_trap_if_not_supervisor(opts, inst); | |
2031 } | |
2012 cycles(&opts->gen, 20); | 2032 cycles(&opts->gen, 20); |
2013 //TODO: If ANDI to SR, trap if not in supervisor mode | |
2014 if (inst->src.params.immed & 0x1) { | 2033 if (inst->src.params.immed & 0x1) { |
2015 xor_flag(opts, 1, FLAG_C); | 2034 xor_flag(opts, 1, FLAG_C); |
2016 } | 2035 } |
2017 if (inst->src.params.immed & 0x2) { | 2036 if (inst->src.params.immed & 0x2) { |
2018 xor_flag(opts, 1, FLAG_V); | 2037 xor_flag(opts, 1, FLAG_V); |
2047 } | 2066 } |
2048 | 2067 |
2049 void translate_m68k_move_ccr_sr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) | 2068 void translate_m68k_move_ccr_sr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) |
2050 { | 2069 { |
2051 code_info *code = &opts->gen.code; | 2070 code_info *code = &opts->gen.code; |
2052 //TODO: Privilege check for MOVE to SR | 2071 if (inst->op == M68K_MOVE_SR) { |
2072 m68k_trap_if_not_supervisor(opts, inst); | |
2073 } | |
2053 if (src_op->mode == MODE_IMMED) { | 2074 if (src_op->mode == MODE_IMMED) { |
2054 set_all_flags(opts, src_op->disp); | 2075 set_all_flags(opts, src_op->disp); |
2055 if (inst->op == M68K_MOVE_SR) { | 2076 if (inst->op == M68K_MOVE_SR) { |
2056 mov_irdisp(code, (src_op->disp >> 8), opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); | 2077 mov_irdisp(code, (src_op->disp >> 8), opts->gen.context_reg, offsetof(m68k_context, status), SZ_B); |
2057 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { | 2078 if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) { |
2083 } | 2104 } |
2084 } | 2105 } |
2085 | 2106 |
2086 void translate_m68k_stop(m68k_options *opts, m68kinst *inst) | 2107 void translate_m68k_stop(m68k_options *opts, m68kinst *inst) |
2087 { | 2108 { |
2088 //TODO: Trap if not in system mode | 2109 m68k_trap_if_not_supervisor(opts, inst); |
2089 //manual says 4 cycles, but it has to be at least 8 since it's a 2-word instruction | 2110 //manual says 4 cycles, but it has to be at least 8 since it's a 2-word instruction |
2090 //possibly even 12 since that's how long MOVE to SR takes | 2111 //possibly even 12 since that's how long MOVE to SR takes |
2091 //On further thought prefetch + the fact that this stops the CPU may make | 2112 //On further thought prefetch + the fact that this stops the CPU may make |
2092 //Motorola's accounting make sense here | 2113 //Motorola's accounting make sense here |
2093 code_info *code = &opts->gen.code; | 2114 code_info *code = &opts->gen.code; |
2187 } | 2208 } |
2188 | 2209 |
2189 void translate_m68k_move_from_sr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) | 2210 void translate_m68k_move_from_sr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op) |
2190 { | 2211 { |
2191 code_info *code = &opts->gen.code; | 2212 code_info *code = &opts->gen.code; |
2192 //TODO: Trap if not in system mode | |
2193 call(code, opts->get_sr); | 2213 call(code, opts->get_sr); |
2194 if (dst_op->mode == MODE_REG_DIRECT) { | 2214 if (dst_op->mode == MODE_REG_DIRECT) { |
2195 mov_rr(code, opts->gen.scratch1, dst_op->base, SZ_W); | 2215 mov_rr(code, opts->gen.scratch1, dst_op->base, SZ_W); |
2196 } else { | 2216 } else { |
2197 mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, SZ_W); | 2217 mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, SZ_W); |