summaryrefslogtreecommitdiff
path: root/m68k_to_x86.c
diff options
context:
space:
mode:
authorMike Pavone <pavone@retrodev.com>2012-12-27 21:54:54 -0800
committerMike Pavone <pavone@retrodev.com>2012-12-27 21:54:54 -0800
commit62efe845474039b5ce0a0248c133d80f60a1ae3d (patch)
treea97e85b7d66df1ea508362b7c49dee8587aad9ba /m68k_to_x86.c
parent9d03b4ec8b00bc244e5c8f6bc0ff00bb4fff614e (diff)
Allow indexed modes to be used as a destination
Diffstat (limited to 'm68k_to_x86.c')
-rw-r--r--m68k_to_x86.c121
1 files changed, 120 insertions, 1 deletions
diff --git a/m68k_to_x86.c b/m68k_to_x86.c
index 8462756..9fd598c 100644
--- a/m68k_to_x86.c
+++ b/m68k_to_x86.c
@@ -349,7 +349,7 @@ uint8_t * translate_m68k_src(m68kinst * inst, x86_ea * ea, uint8_t * out, x86_68
uint8_t * translate_m68k_dst(m68kinst * inst, x86_ea * ea, uint8_t * out, x86_68k_options * opts, uint8_t fake_read)
{
- int8_t reg = native_reg(&(inst->dst), opts);
+ int8_t reg = native_reg(&(inst->dst), opts), sec_reg;
int32_t dec_amount, inc_amount;
if (reg >= 0) {
ea->mode = MODE_REG_DIRECT;
@@ -440,6 +440,67 @@ 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_AREG_INDEX_DISP8:
+ out = cycles(out, fake_read ? (6 + inst->extra.size == OPSIZE_LONG ? 8 : 4) : 6);
+ if (opts->aregs[inst->dst.params.regs.pri] >= 0) {
+ out = mov_rr(out, opts->aregs[inst->dst.params.regs.pri], SCRATCH1, SZ_D);
+ } else {
+ out = mov_rdisp8r(out, CONTEXT, reg_offset(&(inst->dst)), SCRATCH1, SZ_D);
+ }
+ sec_reg = (inst->dst.params.regs.sec >> 1) & 0x7;
+ if (inst->dst.params.regs.sec & 1) {
+ if (inst->dst.params.regs.sec & 0x10) {
+ if (opts->aregs[sec_reg] >= 0) {
+ out = add_rr(out, opts->aregs[sec_reg], SCRATCH1, SZ_D);
+ } else {
+ out = add_rdisp8r(out, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_D);
+ }
+ } else {
+ if (opts->dregs[sec_reg] >= 0) {
+ out = add_rr(out, opts->dregs[sec_reg], SCRATCH1, SZ_D);
+ } else {
+ out = add_rdisp8r(out, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_D);
+ }
+ }
+ } else {
+ if (inst->dst.params.regs.sec & 0x10) {
+ if (opts->aregs[sec_reg] >= 0) {
+ out = movsx_rr(out, opts->aregs[sec_reg], SCRATCH2, SZ_W, SZ_D);
+ } else {
+ out = movsx_rdisp8r(out, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_W, SZ_D);
+ }
+ } else {
+ if (opts->dregs[sec_reg] >= 0) {
+ out = movsx_rr(out, opts->dregs[sec_reg], SCRATCH2, SZ_W, SZ_D);
+ } else {
+ out = movsx_rdisp8r(out, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_W, SZ_D);
+ }
+ }
+ out = add_rr(out, SCRATCH2, SCRATCH1, SZ_D);
+ }
+ if (inst->dst.params.regs.displacement) {
+ out = add_ir(out, inst->dst.params.regs.displacement, SCRATCH1, SZ_D);
+ }
+ if (fake_read) {
+ out = mov_rr(out, SCRATCH1, SCRATCH2, SZ_D);
+ } else {
+ 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;
case MODE_PC_DISPLACE:
out = cycles(out, fake_read ? BUS+(inst->extra.size == OPSIZE_LONG ? BUS*2 : BUS) : BUS);
out = mov_ir(out, inst->dst.params.regs.displacement + inst->address+2, fake_read ? SCRATCH2 : SCRATCH1, SZ_D);
@@ -462,6 +523,64 @@ 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_PC_INDEX_DISP8:
+ out = cycles(out, fake_read ? (6 + inst->extra.size == OPSIZE_LONG ? 8 : 4) : 6);
+ out = mov_ir(out, inst->address+2, SCRATCH1, SZ_D);
+ sec_reg = (inst->dst.params.regs.sec >> 1) & 0x7;
+ if (inst->dst.params.regs.sec & 1) {
+ if (inst->dst.params.regs.sec & 0x10) {
+ if (opts->aregs[sec_reg] >= 0) {
+ out = add_rr(out, opts->aregs[sec_reg], SCRATCH1, SZ_D);
+ } else {
+ out = add_rdisp8r(out, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_D);
+ }
+ } else {
+ if (opts->dregs[sec_reg] >= 0) {
+ out = add_rr(out, opts->dregs[sec_reg], SCRATCH1, SZ_D);
+ } else {
+ out = add_rdisp8r(out, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH1, SZ_D);
+ }
+ }
+ } else {
+ if (inst->dst.params.regs.sec & 0x10) {
+ if (opts->aregs[sec_reg] >= 0) {
+ out = movsx_rr(out, opts->aregs[sec_reg], SCRATCH2, SZ_W, SZ_D);
+ } else {
+ out = movsx_rdisp8r(out, CONTEXT, offsetof(m68k_context, aregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_W, SZ_D);
+ }
+ } else {
+ if (opts->dregs[sec_reg] >= 0) {
+ out = movsx_rr(out, opts->dregs[sec_reg], SCRATCH2, SZ_W, SZ_D);
+ } else {
+ out = movsx_rdisp8r(out, CONTEXT, offsetof(m68k_context, dregs) + sizeof(uint32_t)*sec_reg, SCRATCH2, SZ_W, SZ_D);
+ }
+ }
+ out = add_rr(out, SCRATCH2, SCRATCH1, SZ_D);
+ }
+ if (inst->dst.params.regs.displacement) {
+ out = add_ir(out, inst->dst.params.regs.displacement, SCRATCH1, SZ_D);
+ }
+ if (fake_read) {
+ out = mov_rr(out, SCRATCH1, SCRATCH2, SZ_D);
+ } else {
+ 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;
case MODE_ABSOLUTE:
case MODE_ABSOLUTE_SHORT:
//Add cycles for reading address from instruction stream