# HG changeset patch # User Mike Pavone # Date 1356661270 28800 # Node ID f63b0e58e2d51b8bdc5d2c3eab0e46d24edeefee # Parent c3d034e076eebe3a4bcd647b58d765542c8fd457 Implement EXT, add some fixes to LINK/UNLK diff -r c3d034e076ee -r f63b0e58e2d5 68kinst.c --- a/68kinst.c Thu Dec 27 10:40:03 2012 -0800 +++ b/68kinst.c Thu Dec 27 18:21:10 2012 -0800 @@ -527,14 +527,14 @@ 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 @@ 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 -r c3d034e076ee -r f63b0e58e2d5 m68k_to_x86.c --- a/m68k_to_x86.c Thu Dec 27 10:40:03 2012 -0800 +++ b/m68k_to_x86.c Thu Dec 27 18:21:10 2012 -0800 @@ -901,6 +901,29 @@ 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 @@ 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 @@ 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;*/