summaryrefslogtreecommitdiff
path: root/m68k_to_x86.c
diff options
context:
space:
mode:
Diffstat (limited to 'm68k_to_x86.c')
-rw-r--r--m68k_to_x86.c38
1 files changed, 33 insertions, 5 deletions
diff --git a/m68k_to_x86.c b/m68k_to_x86.c
index 8b57091..5781fef 100644
--- a/m68k_to_x86.c
+++ b/m68k_to_x86.c
@@ -31,7 +31,6 @@ void m68k_load_context();
void m68k_modified_ret_addr();
void m68k_native_addr();
void m68k_native_addr_and_sync();
-void m68k_trap();
void m68k_invalid();
void m68k_retrans_stub();
void set_sr();
@@ -3090,7 +3089,7 @@ uint8_t * translate_m68k(uint8_t * dst, m68kinst * inst, x86_68k_options * opts)
dst = mov_ir(dst, 1, FLAG_N, SZ_B);
dst = mov_ir(dst, VECTOR_CHK, SCRATCH2, SZ_D);
dst = mov_ir(dst, inst->address+isize, SCRATCH1, SZ_D);
- dst = jmp(dst, (uint8_t *)m68k_trap);
+ dst = jmp(dst, opts->trap);
*passed = dst - (passed+1);
if (dst_op.mode == MODE_REG_DIRECT) {
if (src_op.mode == MODE_REG_DIRECT) {
@@ -3112,7 +3111,7 @@ uint8_t * translate_m68k(uint8_t * dst, m68kinst * inst, x86_68k_options * opts)
dst = mov_ir(dst, 0, FLAG_N, SZ_B);
dst = mov_ir(dst, VECTOR_CHK, SCRATCH2, SZ_D);
dst = mov_ir(dst, inst->address+isize, SCRATCH1, SZ_D);
- dst = jmp(dst, (uint8_t *)m68k_trap);
+ dst = jmp(dst, opts->trap);
*passed = dst - (passed+1);
dst = cycles(dst, 4);
break;
@@ -3152,7 +3151,7 @@ uint8_t * translate_m68k(uint8_t * dst, m68kinst * inst, x86_68k_options * opts)
dst = pop_r(dst, RDX);
dst = mov_ir(dst, VECTOR_INT_DIV_ZERO, SCRATCH2, SZ_D);
dst = mov_ir(dst, inst->address+2, SCRATCH1, SZ_D);
- dst = jmp(dst, (uint8_t *)m68k_trap);
+ dst = jmp(dst, opts->trap);
*not_zero = dst - (not_zero+1);
if (inst->op == M68K_DIVS) {
dst = cdq(dst);
@@ -3853,7 +3852,7 @@ uint8_t * translate_m68k(uint8_t * dst, m68kinst * inst, x86_68k_options * opts)
case M68K_TRAP:
dst = mov_ir(dst, src_op.disp + VECTOR_TRAP_0, SCRATCH2, SZ_D);
dst = mov_ir(dst, inst->address+2, SCRATCH1, SZ_D);
- dst = jmp(dst, (uint8_t *)m68k_trap);
+ dst = jmp(dst, opts->trap);
break;
//case M68K_TRAPV:
case M68K_TST:
@@ -4521,6 +4520,35 @@ void init_x86_68k_opts(x86_68k_options * opts, memmap_chunk * memmap, uint32_t n
dst = pop_r(dst, SCRATCH2);
dst = jmp_r(dst, SCRATCH1);
+ opts->trap = dst;
+ dst = push_r(dst, SCRATCH2);
+ //swap USP and SSP if not already in supervisor mode
+ dst = bt_irdisp8(dst, 5, CONTEXT, offsetof(m68k_context, status), SZ_B);
+ already_supervisor = dst+1;
+ dst = jcc(dst, CC_C, dst+2);
+ dst = mov_rdisp8r(dst, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SCRATCH2, SZ_D);
+ dst = mov_rrdisp8(dst, opts->aregs[7], CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t) * 8, SZ_D);
+ dst = mov_rr(dst, SCRATCH2, opts->aregs[7], SZ_D);
+ *already_supervisor = dst - (already_supervisor+1);
+ //save PC
+ dst = sub_ir(dst, 4, opts->aregs[7], SZ_D);
+ dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D);
+ dst = call(dst, opts->write_32_lowfirst);
+ //save status register
+ dst = sub_ir(dst, 2, opts->aregs[7], SZ_D);
+ dst = call(dst, (uint8_t *)get_sr);
+ dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D);
+ dst = call(dst, opts->write_16);
+ //set supervisor bit
+ dst = or_irdisp8(dst, 0x20, CONTEXT, offsetof(m68k_context, status), SZ_B);
+ //calculate vector address
+ dst = pop_r(dst, SCRATCH1);
+ dst = shl_ir(dst, 2, SCRATCH1, SZ_D);
+ dst = call(dst, opts->read_32);
+ dst = call(dst, (uint8_t *)m68k_native_addr_and_sync);
+ dst = cycles(dst, 18);
+ dst = jmp_r(dst, SCRATCH1);
+
opts->cur_code = dst;
}