diff options
Diffstat (limited to 'm68k_to_x86.c')
-rw-r--r-- | m68k_to_x86.c | 69 |
1 files changed, 67 insertions, 2 deletions
diff --git a/m68k_to_x86.c b/m68k_to_x86.c index 2b6abba..262dfab 100644 --- a/m68k_to_x86.c +++ b/m68k_to_x86.c @@ -175,8 +175,9 @@ uint8_t * translate_m68k_src(m68kinst * inst, x86_ea * ea, uint8_t * out, x86_68 ea->base = SCRATCH1; break; case MODE_IMMEDIATE: + case MODE_IMMEDIATE_WORD: if (inst->variant != VAR_QUICK) { - if (inst->extra.size == OPSIZE_LONG) { + if (inst->extra.size == OPSIZE_LONG && inst->src.addr_mode == MODE_IMMEDIATE) { out = cycles(out, BUS); out = check_cycles(out); } @@ -254,6 +255,32 @@ uint8_t * translate_m68k_dst(m68kinst * inst, x86_ea * ea, uint8_t * out, x86_68 ea->mode = MODE_REG_DIRECT; ea->base = SCRATCH1; break; + case MODE_ABSOLUTE: + case MODE_ABSOLUTE_SHORT: + //Add cycles for reading address from instruction stream + if (inst->dst.addr_mode == MODE_ABSOLUTE) { + out = cycles(out, BUS*2); + } else { + out = cycles(out, BUS); + } + out = mov_ir(out, inst->dst.params.immed, SCRATCH1, SZ_D); + out = push_r(out, SCRATCH1); + switch (inst->extra.size) + { + case OPSIZE_BYTE: + out = call(out, (char *)m68k_read_byte_scratch1); + break; + case OPSIZE_WORD: + out = call(out, (char *)m68k_read_word_scratch1); + break; + case OPSIZE_LONG: + out = call(out, (char *)m68k_read_long_scratch1); + break; + } + out = pop_r(out, SCRATCH2); + ea->mode = MODE_REG_DIRECT; + ea->base = SCRATCH1; + break; default: printf("address mode %d not implemented (dst)\n", inst->dst.addr_mode); exit(1); @@ -1010,7 +1037,46 @@ uint8_t * translate_m68k(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) case M68K_BCHG: case M68K_BCLR: case M68K_BSET: + break; case M68K_BTST: + dst = cycles(dst, inst->extra.size == OPSIZE_BYTE ? 4 : 6); + if (src_op.mode == MODE_IMMEDIATE) { + if (inst->extra.size == OPSIZE_BYTE) { + src_op.disp &= 0x7; + } + if (dst_op.mode == MODE_REG_DIRECT) { + dst = bt_ir(dst, src_op.disp, dst_op.base, SZ_D); + } else { + dst = bt_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, SZ_D); + } + } else { + if (src_op.mode == MODE_REG_DISPLACE8) { + if (dst_op.base == SCRATCH1) { + dst = push_r(dst, SCRATCH2); + dst = mov_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH2, SZ_B); + src_op.base = SCRATCH1; + } else { + dst = mov_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH1, SZ_B); + src_op.base = SCRATCH1; + } + } + if (inst->extra.size == OPSIZE_BYTE) { + dst = and_ir(dst, 0x7, src_op.base, SZ_B); + } + if (dst_op.mode == MODE_REG_DIRECT) { + dst = bt_rr(dst, src_op.base, dst_op.base, SZ_D); + } else { + dst = bt_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, SZ_D); + } + } + //x86 sets the carry flag to the value of the bit tested + //68K sets the zero flag to the complement of the bit tested + dst = setcc_r(dst, CC_NC, FLAG_Z); + if (src_op.base == SCRATCH2) { + dst = pop_r(dst, SCRATCH2); + } + dst = m68k_save_result(inst, dst, opts); + break; case M68K_CHK: break; case M68K_CMP: @@ -1096,7 +1162,6 @@ uint8_t * translate_m68k(uint8_t * dst, m68kinst * inst, x86_68k_options * opts) dst = mov_rr(dst, CONTEXT, RDI, SZ_Q); dst = call(dst, (uint8_t *)print_regs_exit); break; - case M68K_JMP: case M68K_JSR: case M68K_LEA: case M68K_LINK: |