summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pavone <pavone@retrodev.com>2013-04-21 13:00:34 -0700
committerMike Pavone <pavone@retrodev.com>2013-04-21 13:00:34 -0700
commit28b19a047f98ac80090e5286d5f0c0349b91dc38 (patch)
treea6b8b394b7027d6dc8d8f1467acf7abe27d0dc10
parent1dd89758e07ed71dc664a8341c19315293ef2730 (diff)
Implement CHK instruction (not fully tested).
-rw-r--r--68kinst.h42
-rw-r--r--m68k_to_x86.c44
-rw-r--r--runtime.S3
3 files changed, 84 insertions, 5 deletions
diff --git a/68kinst.h b/68kinst.h
index ae2b38f..96210b4 100644
--- a/68kinst.h
+++ b/68kinst.h
@@ -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;
diff --git a/runtime.S b/runtime.S
index ccc644f..0136aba 100644
--- a/runtime.S
+++ b/runtime.S
@@ -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: