summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pavone <pavone@retrodev.com>2012-12-27 18:21:10 -0800
committerMike Pavone <pavone@retrodev.com>2012-12-27 18:21:10 -0800
commitebbab3cb4d9f149cd43528b71d3fcb1497626a32 (patch)
tree82ce943ca6adfd332612e6d68f0de609547f096a
parent346cbc52292d8b0fbb25df451b07d44d40258746 (diff)
Implement EXT, add some fixes to LINK/UNLK
-rw-r--r--68kinst.c10
-rw-r--r--m68k_to_x86.c28
2 files changed, 32 insertions, 6 deletions
diff --git a/68kinst.c b/68kinst.c
index 64d22e2..c28a103 100644
--- a/68kinst.c
+++ b/68kinst.c
@@ -527,14 +527,14 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
break;
case 0x10:
decoded->op = M68K_EXT;
- decoded->src.addr_mode = MODE_REG;
- decoded->src.params.regs.pri = *istream & 0x7;
+ decoded->dst.addr_mode = MODE_REG;
+ decoded->dst.params.regs.pri = *istream & 0x7;
decoded->extra.size = OPSIZE_WORD;
break;
case 0x18:
decoded->op = M68K_EXT;
- decoded->src.addr_mode = MODE_REG;
- decoded->src.params.regs.pri = *istream & 0x7;
+ decoded->dst.addr_mode = MODE_REG;
+ decoded->dst.params.regs.pri = *istream & 0x7;
decoded->extra.size = OPSIZE_LONG;
break;
case 0x38:
@@ -607,7 +607,7 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
decoded->src.addr_mode = MODE_AREG;
decoded->src.params.regs.pri = *istream & 0x7;
decoded->dst.addr_mode = MODE_IMMEDIATE;
- decoded->dst.params.immed = *(++istream);
+ decoded->dst.params.immed = sign_extend16(*(++istream));
break;
case 3:
//UNLK
diff --git a/m68k_to_x86.c b/m68k_to_x86.c
index 338ffee..13943c6 100644
--- a/m68k_to_x86.c
+++ b/m68k_to_x86.c
@@ -901,6 +901,29 @@ uint8_t * translate_m68k_clr(uint8_t * dst, m68kinst * inst, x86_68k_options * o
return dst;
}
+uint8_t * translate_m68k_ext(uint8_t * dst, m68kinst * inst, x86_68k_options * opts)
+{
+ x86_ea dst_op;
+ uint8_t dst_size = inst->extra.size;
+ inst->extra.size--;
+ dst = translate_m68k_dst(inst, &dst_op, dst, opts, 0);
+ if (dst_op.mode == MODE_REG_DIRECT) {
+ dst = movsx_rr(dst, dst_op.base, dst_op.base, inst->extra.size, dst_size);
+ dst = cmp_ir(dst, 0, dst_op.base, dst_size);
+ } else {
+ dst = movsx_rdisp8r(dst, dst_op.base, dst_op.disp, SCRATCH1, inst->extra.size, dst_size);
+ dst = cmp_ir(dst, 0, SCRATCH1, dst_size);
+ dst = mov_rrdisp8(dst, SCRATCH1, dst_op.base, dst_op.disp, dst_size);
+ }
+ inst->extra.size = dst_size;
+ dst = mov_ir(dst, 0, FLAG_V, SZ_B);
+ dst = mov_ir(dst, 0, FLAG_C, SZ_B);
+ dst = setcc_r(dst, CC_Z, FLAG_Z);
+ dst = setcc_r(dst, CC_S, FLAG_N);
+ //M68K EXT only operates on registers so no need for a call to save result here
+ return dst;
+}
+
uint8_t * translate_m68k_lea(uint8_t * dst, m68kinst * inst, x86_68k_options * opts)
{
int8_t dst_reg = native_reg(&(inst->dst), opts);
@@ -1410,6 +1433,8 @@ uint8_t * translate_m68k(uint8_t * dst, m68kinst * inst, x86_68k_options * opts)
return translate_m68k_movem(dst, inst, opts);
} else if(inst->op == M68K_LINK) {
return translate_m68k_link(dst, inst, opts);
+ } else if(inst->op == M68K_EXT) {
+ return translate_m68k_ext(dst, inst, opts);
}
x86_ea src_op, dst_op;
if (inst->src.addr_mode != MODE_UNUSED) {
@@ -1842,8 +1867,9 @@ uint8_t * translate_m68k(uint8_t * dst, m68kinst * inst, x86_68k_options * opts)
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);
+ dst = mov_rrdisp8(dst, SCRATCH1, dst_op.base, dst_op.disp, SZ_D);
}
+ dst = add_ir(dst, 4, opts->aregs[7], SZ_D);
break;
/*case M68K_INVALID:
break;*/