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.c45
1 files changed, 42 insertions, 3 deletions
diff --git a/m68k_to_x86.c b/m68k_to_x86.c
index 11f3794..8da98e4 100644
--- a/m68k_to_x86.c
+++ b/m68k_to_x86.c
@@ -1191,6 +1191,30 @@ uint8_t * translate_m68k_dbcc(uint8_t * dst, m68kinst * inst, x86_68k_options *
return dst;
}
+uint8_t * translate_m68k_link(uint8_t * dst, m68kinst * inst, x86_68k_options * opts)
+{
+ int8_t reg = native_reg(&(inst->src), opts);
+ //compensate for displacement word
+ dst = cycles(dst, BUS);
+ dst = sub_ir(dst, 4, opts->aregs[7], SZ_D);
+ dst = mov_rr(dst, opts->aregs[7], SCRATCH2, SZ_D);
+ if (reg >= 0) {
+ dst = mov_rr(dst, reg, SCRATCH1, SZ_D);
+ } else {
+ dst = mov_rdisp8r(dst, CONTEXT, reg_offset(&(inst->src)), SCRATCH1, SZ_D);
+ }
+ dst = call(dst, (char *)m68k_write_long_highfirst);
+ if (reg >= 0) {
+ dst = mov_rr(dst, opts->aregs[7], reg, SZ_D);
+ } else {
+ dst = mov_rrdisp8(dst, opts->aregs[7], CONTEXT, reg_offset(&(inst->src)), SZ_D);
+ }
+ dst = add_ir(dst, inst->dst.params.immed, opts->aregs[7], SZ_D);
+ //prefetch
+ dst = cycles(dst, BUS);
+ return dst;
+}
+
typedef uint8_t * (*shift_ir_t)(uint8_t * out, uint8_t val, uint8_t dst, uint8_t size);
typedef uint8_t * (*shift_irdisp8_t)(uint8_t * out, uint8_t val, uint8_t dst_base, int8_t disp, uint8_t size);
typedef uint8_t * (*shift_clr_t)(uint8_t * out, uint8_t dst, uint8_t size);
@@ -1317,6 +1341,8 @@ uint8_t * translate_m68k(uint8_t * dst, m68kinst * inst, x86_68k_options * opts)
return translate_m68k_clr(dst, inst, opts);
} else if(inst->op == M68K_MOVEM) {
return translate_m68k_movem(dst, inst, opts);
+ } else if(inst->op == M68K_LINK) {
+ return translate_m68k_link(dst, inst, opts);
}
x86_ea src_op, dst_op;
if (inst->src.addr_mode != MODE_UNUSED) {
@@ -1543,7 +1569,6 @@ uint8_t * translate_m68k(uint8_t * dst, m68kinst * inst, x86_68k_options * opts)
break;
/*case M68K_JSR:
case M68K_LEA:
- case M68K_LINK:
case M68K_MOVE_FROM_SR:
break;*/
case M68K_MOVE_CCR:
@@ -1718,8 +1743,22 @@ uint8_t * translate_m68k(uint8_t * dst, m68kinst * inst, x86_68k_options * opts)
dst = setcc_r(dst, CC_S, FLAG_N);
dst = setcc_r(dst, CC_O, FLAG_V);
break;
- /*case M68K_UNLK:
- case M68K_INVALID:
+ case M68K_UNLK:
+ dst = cycles(dst, BUS);
+ if (dst_op.mode == MODE_REG_DIRECT) {
+ dst = mov_rr(dst, dst_op.base, opts->aregs[7], SZ_D);
+ } else {
+ dst = mov_rdisp8r(dst, dst_op.base, dst_op.disp, opts->aregs[7], SZ_D);
+ }
+ dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D);
+ dst = call(dst, (uint8_t *)m68k_read_long_scratch1);
+ if (dst_op.mode == MODE_REG_DIRECT) {
+ dst = mov_rr(dst, SCRATCH1, dst_op.base, SZ_D);
+ } else {
+ dst = mov_rdisp8r(dst, SCRATCH1, dst_op.base, dst_op.disp, SZ_D);
+ }
+ break;
+ /*case M68K_INVALID:
break;*/
default:
printf("instruction %d not yet implemented\n", inst->op);