diff options
author | Mike Pavone <pavone@retrodev.com> | 2013-04-21 13:00:34 -0700 |
---|---|---|
committer | Mike Pavone <pavone@retrodev.com> | 2013-04-21 13:00:34 -0700 |
commit | 28b19a047f98ac80090e5286d5f0c0349b91dc38 (patch) | |
tree | a6b8b394b7027d6dc8d8f1467acf7abe27d0dc10 | |
parent | 1dd89758e07ed71dc664a8341c19315293ef2730 (diff) |
Implement CHK instruction (not fully tested).
-rw-r--r-- | 68kinst.h | 42 | ||||
-rw-r--r-- | m68k_to_x86.c | 44 | ||||
-rw-r--r-- | runtime.S | 3 |
3 files changed, 84 insertions, 5 deletions
@@ -182,6 +182,48 @@ typedef struct m68kinst { m68k_op_info dst; } m68kinst; +typedef enum { + VECTOR_RESET_STACK, + VECTOR_RESET_PC, + VECTOR_ACCESS_FAULT, + VECTOR_ADDRESS_ERROR, + VECTOR_ILLEGAL_INST, + VECTOR_INT_DIV_ZERO, + VECTOR_CHK, + VECTOR_TRAPV, + VECTOR_PRIV_VIOLATION, + VECTOR_TRACE, + VECTOR_LINE_1010, + VECTOR_LINE_1111, + VECTOR_COPROC_VIOLATION=13, + VECTOR_FORMAT_ERROR, + VECTOR_UNINIT_INTERRUPT, + VECTOR_SPURIOUS_INTERRUPT=24, + VECTOR_INT_1, + VECTOR_INT_2, + VECTOR_INT_3, + VECTOR_INT_4, + VECTOR_INT_5, + VECTOR_INT_6, + VECTOR_INT_7, + VECTOR_TRAP_0, + VECTOR_TRAP_1, + VECTOR_TRAP_2, + VECTOR_TRAP_3, + VECTOR_TRAP_4, + VECTOR_TRAP_5, + VECTOR_TRAP_6, + VECTOR_TRAP_7, + VECTOR_TRAP_8, + VECTOR_TRAP_9, + VECTOR_TRAP_10, + VECTOR_TRAP_11, + VECTOR_TRAP_12, + VECTOR_TRAP_13, + VECTOR_TRAP_14, + VECTOR_TRAP_15 +} m68k_vector; + uint16_t * m68k_decode(uint16_t * istream, m68kinst * dst, uint32_t address); uint32_t m68k_cycles(m68kinst * inst); int m68k_disasm(m68kinst * decoded, char * dst); diff --git a/m68k_to_x86.c b/m68k_to_x86.c index 85869fd..ba7f14a 100644 --- a/m68k_to_x86.c +++ b/m68k_to_x86.c @@ -3084,8 +3084,46 @@ uint8_t * translate_m68k(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) dst = m68k_save_result(inst, dst, opts); } break; - /*case M68K_CHK: - break;*/ + case M68K_CHK: + { + dst = cycles(dst, 6); + if (dst_op.mode == MODE_REG_DIRECT) { + dst = cmp_ir(dst, 0, dst_op.base, inst->extra.size); + } else { + dst = cmp_irdisp8(dst, 0, dst_op.base, dst_op.disp, inst->extra.size); + } + uint8_t * passed = dst+1; + dst = jcc(dst, CC_GE, dst+2); + dst = mov_ir(dst, 1, FLAG_N, SZ_B); + dst = mov_ir(dst, VECTOR_CHK, SCRATCH2, SZ_D); + dst = mov_ir(dst, inst->address+2, SCRATCH1, SZ_D); + dst = jmp(dst, (uint8_t *)m68k_trap); + *passed = dst - (passed+1); + if (dst_op.mode == MODE_REG_DIRECT) { + if (src_op.mode == MODE_REG_DIRECT) { + dst = cmp_rr(dst, src_op.base, dst_op.base, inst->extra.size); + } else if(src_op.mode == MODE_REG_DISPLACE8) { + dst = cmp_rdisp8r(dst, src_op.base, src_op.disp, dst_op.base, inst->extra.size); + } else { + dst = cmp_ir(dst, src_op.disp, dst_op.base, inst->extra.size); + } + } else if(dst_op.mode == MODE_REG_DISPLACE8) { + if (src_op.mode == MODE_REG_DIRECT) { + dst = cmp_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, inst->extra.size); + } else { + dst = cmp_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size); + } + } + passed = dst+1; + dst = jcc(dst, CC_LE, dst+2); + dst = mov_ir(dst, 0, FLAG_N, SZ_B); + dst = mov_ir(dst, VECTOR_CHK, SCRATCH2, SZ_D); + dst = mov_ir(dst, inst->address+2, SCRATCH1, SZ_D); + dst = jmp(dst, (uint8_t *)m68k_trap); + *passed = dst - (passed+1); + dst = cycles(dst, 4); + break; + } case M68K_DIVS: case M68K_DIVU: //TODO: Trap on division by zero @@ -3802,7 +3840,7 @@ uint8_t * translate_m68k(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) break; //case M68K_TAS: case M68K_TRAP: - dst = mov_ir(dst, src_op.disp, SCRATCH2, SZ_D); + 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); break; @@ -91,10 +91,9 @@ already_supervisor_trap: /* calculate interrupt vector address */ pop %rcx shl $2, %ecx - add $0x80, %ecx call m68k_read_long_scratch1 call m68k_native_addr_and_sync - add $24, %eax + add $18, %eax jmp *%rcx invalid_msg: |