# HG changeset patch # User Mike Pavone # Date 1355372286 28800 # Node ID f2aaaf36c8758c1ae2b1d1b2ac971a5bfe773aba # Parent 3adbd97f71f26eec924c75fd9ed96a0833bc5db5 Add support for dbcc instruction diff -r 3adbd97f71f2 -r f2aaaf36c875 68kinst.c --- a/68kinst.c Wed Dec 12 20:17:59 2012 -0800 +++ b/68kinst.c Wed Dec 12 20:18:06 2012 -0800 @@ -665,9 +665,9 @@ case 1: //DBcc decoded->op = M68K_DBCC; decoded->src.addr_mode = MODE_IMMEDIATE; - decoded->src.params.immed = *(++istream); decoded->dst.addr_mode = MODE_REG; decoded->dst.params.regs.pri = *istream & 0x7; + decoded->src.params.immed = sign_extend16(*(++istream)); break; case 7: //TRAPcc #ifdef M68020 diff -r 3adbd97f71f2 -r f2aaaf36c875 m68k_to_x86.c --- a/m68k_to_x86.c Wed Dec 12 20:17:59 2012 -0800 +++ b/m68k_to_x86.c Wed Dec 12 20:18:06 2012 -0800 @@ -346,7 +346,7 @@ dst = mov_ir(dst, src.disp, reg, inst->extra.size); } } else if(src.mode == MODE_REG_DIRECT) { - printf("mov_rrdisp8 from reg %d to offset %d from reg %d (%d)\n", src.base, (inst->dst.addr_mode == MODE_REG ? offsetof(m68k_context, dregs) : offsetof(m68k_context, aregs)) + 4 * inst->dst.params.regs.pri, CONTEXT, inst->dst.params.regs.pri); + printf("mov_rrdisp8 from reg %d to offset %d from reg %d (%d)\n", src.base, (int)(inst->dst.addr_mode == MODE_REG ? offsetof(m68k_context, dregs) : offsetof(m68k_context, aregs)) + 4 * inst->dst.params.regs.pri, CONTEXT, inst->dst.params.regs.pri); dst = mov_rrdisp8(dst, src.base, CONTEXT, (inst->dst.addr_mode == MODE_REG ? offsetof(m68k_context, dregs) : offsetof(m68k_context, aregs)) + 4 * inst->dst.params.regs.pri, inst->extra.size); } else { dst = mov_irdisp8(dst, src.disp, CONTEXT, (inst->dst.addr_mode == MODE_REG ? offsetof(m68k_context, dregs) : offsetof(m68k_context, aregs)) + 4 * inst->dst.params.regs.pri, inst->extra.size); @@ -458,7 +458,7 @@ { //TODO: Add cycles int32_t disp = inst->src.params.immed; - uint32_t after = inst->address + (inst->variant == VAR_BYTE ? 2 : (inst->variant == VAR_WORD ? 4 : 6)); + uint32_t after = inst->address + 2; dst = mov_ir(dst, after, SCRATCH1, SZ_D); dst = push_r(dst, SCRATCH1); dst = sub_ir(dst, 4, opts->aregs[7], SZ_D); @@ -481,7 +481,7 @@ { //TODO: Add cycles int32_t disp = inst->src.params.immed; - uint32_t after = inst->address + (inst->variant == VAR_BYTE ? 2 : (inst->variant == VAR_WORD ? 4 : 6)); + uint32_t after = inst->address + 2; printf("bcc@%X: after=%X, disp=%X, dest=%X\n", inst->address, after, disp, after+disp); uint8_t * dest_addr = get_native_address(opts->native_code_map, after + disp); if (inst->extra.cond == COND_TRUE) { @@ -557,6 +557,88 @@ return dst; } +uint8_t * translate_m68k_dbcc(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) +{ + //best case duration + dst = cycles(dst, 10); + dst = check_cycles(dst); + uint8_t * skip_loc = NULL; + //TODO: Check if COND_TRUE technically valid here even though + //it's basically a slow NOP + if (inst->extra.cond != COND_FALSE) { + uint8_t cond = CC_NZ; + switch (inst->extra.cond) + { + case COND_HIGH: + cond = CC_Z; + case COND_LOW_SAME: + dst = mov_rr(dst, FLAG_Z, SCRATCH1, SZ_B); + dst = or_rr(dst, FLAG_C, SCRATCH1, SZ_B); + break; + case COND_CARRY_CLR: + cond = CC_Z; + case COND_CARRY_SET: + dst = cmp_ir(dst, 0, FLAG_C, SZ_B); + break; + case COND_NOT_EQ: + cond = CC_Z; + case COND_EQ: + dst = cmp_ir(dst, 0, FLAG_Z, SZ_B); + break; + case COND_OVERF_CLR: + cond = CC_Z; + case COND_OVERF_SET: + dst = cmp_ir(dst, 0, FLAG_V, SZ_B); + break; + case COND_PLUS: + cond = CC_Z; + case COND_MINUS: + dst = cmp_ir(dst, 0, FLAG_N, SZ_B); + break; + case COND_GREATER_EQ: + cond = CC_Z; + case COND_LESS: + dst = cmp_rr(dst, FLAG_N, FLAG_V, SZ_B); + break; + case COND_GREATER: + cond = CC_Z; + case COND_LESS_EQ: + dst = mov_rr(dst, FLAG_V, SCRATCH1, SZ_B); + dst = xor_rr(dst, FLAG_N, SCRATCH1, SZ_B); + dst = or_rr(dst, FLAG_Z, SCRATCH1, SZ_B); + break; + } + skip_loc = dst + 1; + dst = jcc(dst, cond, dst + 2); + } + if (opts->dregs[inst->dst.params.regs.pri] >= 0) { + dst = sub_ir(dst, 1, opts->dregs[inst->dst.params.regs.pri], SZ_W); + dst = cmp_ir(dst, -1, opts->dregs[inst->dst.params.regs.pri], SZ_W); + } else { + dst = sub_irdisp8(dst, 1, CONTEXT, offsetof(m68k_context, dregs) + 4 * inst->dst.params.regs.pri, SZ_W); + dst = cmp_irdisp8(dst, -1, CONTEXT, offsetof(m68k_context, dregs) + 4 * inst->dst.params.regs.pri, SZ_W); + } + uint8_t *loop_end_loc = dst+1; + dst = jcc(dst, CC_Z, dst+2); + uint32_t after = inst->address + 2; + uint8_t * dest_addr = get_native_address(opts->native_code_map, after + inst->src.params.immed); + if (!dest_addr) { + opts->deferred = defer_address(opts->deferred, after + inst->src.params.immed, dst + 1); + //dummy address to be replaced later, make sure it generates a 4-byte displacement + dest_addr = dst + 256; + } + dst = jmp(dst, dest_addr); + *loop_end_loc = dst - (loop_end_loc+1); + if (skip_loc) { + dst = cycles(dst, 2); + *skip_loc = dst - (skip_loc+1); + dst = cycles(dst, 2); + } else { + dst = cycles(dst, 4); + } + dst = check_cycles(dst); +} + uint8_t * translate_m68k(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) { map_native_address(opts->native_code_map, inst->address, dst); @@ -570,6 +652,8 @@ return translate_m68k_bcc(dst, inst, opts); } else if(inst->op == M68K_RTS) { return translate_m68k_rts(dst, inst, opts); + } else if(inst->op == M68K_DBCC) { + return translate_m68k_dbcc(dst, inst, opts); } x86_ea src_op, dst_op; if (inst->src.addr_mode != MODE_UNUSED) {