summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Pavone <pavone@retrodev.com>2014-03-05 19:26:53 -0800
committerMichael Pavone <pavone@retrodev.com>2014-03-05 19:26:53 -0800
commita87c5969394dcf435da8a1165fbb1757af78fa0c (patch)
treec83dad7f65cb40688a2faedcb5f039c4e9f80a1c
parentb8b8b8416b1ee82bc69ca6792f578b8bfb8683b9 (diff)
Combine implementations of lea and pea. Update bit instructions to use the op_ family of functions to simplify their implementation a bit.
-rw-r--r--m68k_core.c64
-rw-r--r--m68k_core_x86.c74
-rw-r--r--m68k_internal.h3
3 files changed, 43 insertions, 98 deletions
diff --git a/m68k_core.c b/m68k_core.c
index 6054c90..42c53bf 100644
--- a/m68k_core.c
+++ b/m68k_core.c
@@ -86,10 +86,10 @@ void m68k_write_size(m68k_options *opts, uint8_t size)
}
}
-void translate_m68k_lea(m68k_options * opts, m68kinst * inst)
+void translate_m68k_lea_pea(m68k_options * opts, m68kinst * inst)
{
code_info *code = &opts->gen.code;
- int8_t dst_reg = native_reg(&(inst->dst), opts);
+ int8_t dst_reg = inst->op == M68K_PEA ? opts->gen.scratch1 : native_reg(&(inst->dst), opts);
switch(inst->src.addr_mode)
{
case MODE_AREG_INDIRECT:
@@ -118,13 +118,17 @@ void translate_m68k_lea(m68k_options * opts, m68kinst * inst)
dst_reg = opts->gen.scratch1;
}
calc_areg_index_disp8(opts, &inst->src, dst_reg);
- if (dst_reg == opts->gen.scratch1) {
+ if (dst_reg == opts->gen.scratch1 && inst->op != M68K_PEA) {
native_to_areg(opts, opts->gen.scratch1, inst->dst.params.regs.pri);
}
break;
case MODE_PC_DISPLACE:
cycles(&opts->gen, 8);
- ldi_areg(opts, inst->src.params.regs.displacement + inst->address+2, inst->dst.params.regs.pri);
+ if (inst->op == M68K_PEA) {
+ ldi_native(opts, inst->src.params.regs.displacement + inst->address+2, dst_reg);
+ } else {
+ ldi_areg(opts, inst->src.params.regs.displacement + inst->address+2, inst->dst.params.regs.pri);
+ }
break;
case MODE_PC_INDEX_DISP8:
cycles(&opts->gen, BUS*3);
@@ -133,61 +137,29 @@ void translate_m68k_lea(m68k_options * opts, m68kinst * inst)
}
ldi_native(opts, inst->address+2, dst_reg);
calc_index_disp8(opts, &inst->src, dst_reg);
- if (dst_reg == opts->gen.scratch1) {
+ if (dst_reg == opts->gen.scratch1 && inst->op != M68K_PEA) {
native_to_areg(opts, opts->gen.scratch1, inst->dst.params.regs.pri);
}
break;
case MODE_ABSOLUTE:
case MODE_ABSOLUTE_SHORT:
cycles(&opts->gen, (inst->src.addr_mode == MODE_ABSOLUTE) ? BUS * 3 : BUS * 2);
- ldi_areg(opts, inst->src.params.immed, inst->dst.params.regs.pri);
+ if (inst->op == M68K_PEA) {
+ ldi_native(opts, inst->src.params.immed, dst_reg);
+ } else {
+ ldi_areg(opts, inst->src.params.immed, inst->dst.params.regs.pri);
+ }
break;
default:
m68k_disasm(inst, disasm_buf);
printf("%X: %s\naddress mode %d not implemented (lea src)\n", inst->address, disasm_buf, inst->src.addr_mode);
exit(1);
}
-}
-
-void translate_m68k_pea(m68k_options * opts, m68kinst * inst)
-{
- code_info *code = &opts->gen.code;
- switch(inst->src.addr_mode)
- {
- case MODE_AREG_INDIRECT:
- cycles(&opts->gen, BUS);
- areg_to_native(opts, inst->src.params.regs.pri, opts->gen.scratch1);
- break;
- case MODE_AREG_DISPLACE:
- cycles(&opts->gen, 8);
- calc_areg_displace(opts, &inst->src, opts->gen.scratch1);
- break;
- case MODE_AREG_INDEX_DISP8:
- cycles(&opts->gen, 6);//TODO: Check to make sure this is correct
- calc_areg_index_disp8(opts, &inst->src, opts->gen.scratch1);
- break;
- case MODE_PC_DISPLACE:
- cycles(&opts->gen, 8);
- ldi_native(opts, inst->src.params.regs.displacement + inst->address+2, opts->gen.scratch1);
- break;
- case MODE_PC_INDEX_DISP8:
- cycles(&opts->gen, BUS*3);//TODO: Check to make sure this is correct
- ldi_native(opts, inst->address+2, opts->gen.scratch1);
- calc_index_disp8(opts, &inst->src, opts->gen.scratch1);
- break;
- case MODE_ABSOLUTE:
- case MODE_ABSOLUTE_SHORT:
- cycles(&opts->gen, (inst->src.addr_mode == MODE_ABSOLUTE) ? BUS * 3 : BUS * 2);
- ldi_native(opts, inst->src.params.immed, opts->gen.scratch1);
- break;
- default:
- m68k_disasm(inst, disasm_buf);
- printf("%X: %s\naddress mode %d not implemented (lea src)\n", inst->address, disasm_buf, inst->src.addr_mode);
- exit(1);
+ if (inst->op == M68K_PEA) {
+ subi_areg(opts, 4, 7);
+ areg_to_native(opts, 7, opts->gen.scratch2);
+ call(code, opts->write_32_lowfirst);
}
- subi_areg(opts, 4, 7);
- areg_to_native(opts, 7, opts->gen.scratch2);
- call(code, opts->write_32_lowfirst);
}
void push_const(m68k_options *opts, int32_t value)
diff --git a/m68k_core_x86.c b/m68k_core_x86.c
index 1269adf..7a1c69a 100644
--- a/m68k_core_x86.c
+++ b/m68k_core_x86.c
@@ -1300,6 +1300,10 @@ void op_ir(code_info *code, m68kinst *inst, int32_t val, uint8_t dst, uint8_t si
case M68K_ADD: add_ir(code, val, dst, size); break;
case M68K_ADDX: adc_ir(code, val, dst, size); break;
case M68K_AND: and_ir(code, val, dst, size); break;
+ case M68K_BTST: bt_ir(code, val, dst, size); break;
+ case M68K_BSET: bts_ir(code, val, dst, size); break;
+ case M68K_BCLR: btr_ir(code, val, dst, size); break;
+ case M68K_BCHG: btc_ir(code, val, dst, size); break;
case M68K_EOR: xor_ir(code, val, dst, size); break;
case M68K_OR: or_ir(code, val, dst, size); break;
case M68K_ROL: rol_ir(code, val, dst, size); break;
@@ -1318,6 +1322,10 @@ void op_irdisp(code_info *code, m68kinst *inst, int32_t val, uint8_t dst, int32_
case M68K_ADD: add_irdisp(code, val, dst, disp, size); break;
case M68K_ADDX: adc_irdisp(code, val, dst, disp, size); break;
case M68K_AND: and_irdisp(code, val, dst, disp, size); break;
+ case M68K_BTST: bt_irdisp(code, val, dst, disp, size); break;
+ case M68K_BSET: bts_irdisp(code, val, dst, disp, size); break;
+ case M68K_BCLR: btr_irdisp(code, val, dst, disp, size); break;
+ case M68K_BCHG: btc_irdisp(code, val, dst, disp, size); break;
case M68K_EOR: xor_irdisp(code, val, dst, disp, size); break;
case M68K_OR: or_irdisp(code, val, dst, disp, size); break;
case M68K_ROL: rol_irdisp(code, val, dst, disp, size); break;
@@ -1336,6 +1344,10 @@ void op_rr(code_info *code, m68kinst *inst, uint8_t src, uint8_t dst, uint8_t si
case M68K_ADD: add_rr(code, src, dst, size); break;
case M68K_ADDX: adc_rr(code, src, dst, size); break;
case M68K_AND: and_rr(code, src, dst, size); break;
+ case M68K_BTST: bt_rr(code, src, dst, size); break;
+ case M68K_BSET: bts_rr(code, src, dst, size); break;
+ case M68K_BCLR: btr_rr(code, src, dst, size); break;
+ case M68K_BCHG: btc_rr(code, src, dst, size); break;
case M68K_EOR: xor_rr(code, src, dst, size); break;
case M68K_OR: or_rr(code, src, dst, size); break;
case M68K_SUB: sub_rr(code, src, dst, size); break;
@@ -1350,6 +1362,10 @@ void op_rrdisp(code_info *code, m68kinst *inst, uint8_t src, uint8_t dst, int32_
case M68K_ADD: add_rrdisp(code, src, dst, disp, size); break;
case M68K_ADDX: adc_rrdisp(code, src, dst, disp, size); break;
case M68K_AND: and_rrdisp(code, src, dst, disp, size); break;
+ case M68K_BTST: bt_rrdisp(code, src, dst, disp, size); break;
+ case M68K_BSET: bts_rrdisp(code, src, dst, disp, size); break;
+ case M68K_BCLR: btr_rrdisp(code, src, dst, disp, size); break;
+ case M68K_BCHG: btc_rrdisp(code, src, dst, disp, size); break;
case M68K_EOR: xor_rrdisp(code, src, dst, disp, size); break;
case M68K_OR: or_rrdisp(code, src, dst, disp, size); break;
case M68K_SUB: sub_rrdisp(code, src, dst, disp, size); break;
@@ -1482,10 +1498,8 @@ void translate_m68k(m68k_options * opts, m68kinst * inst)
check_cycles_int(&opts->gen, inst->address);
if (inst->op == M68K_MOVE) {
return translate_m68k_move(opts, inst);
- } else if(inst->op == M68K_LEA) {
- return translate_m68k_lea(opts, inst);
- } else if(inst->op == M68K_PEA) {
- return translate_m68k_pea(opts, inst);
+ } else if(inst->op == M68K_LEA || inst->op == M68K_PEA) {
+ return translate_m68k_lea_pea(opts, inst);
} else if(inst->op == M68K_BSR) {
return translate_m68k_bsr(opts, inst);
} else if(inst->op == M68K_BCC) {
@@ -1637,30 +1651,10 @@ void translate_m68k(m68k_options * opts, m68kinst * inst)
if (inst->extra.size == OPSIZE_BYTE) {
src_op.disp &= 0x7;
}
- if (inst->op == M68K_BTST) {
- if (dst_op.mode == MODE_REG_DIRECT) {
- bt_ir(code, src_op.disp, dst_op.base, inst->extra.size);
- } else {
- bt_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size);
- }
- } else if (inst->op == M68K_BSET) {
- if (dst_op.mode == MODE_REG_DIRECT) {
- bts_ir(code, src_op.disp, dst_op.base, inst->extra.size);
- } else {
- bts_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size);
- }
- } else if (inst->op == M68K_BCLR) {
- if (dst_op.mode == MODE_REG_DIRECT) {
- btr_ir(code, src_op.disp, dst_op.base, inst->extra.size);
- } else {
- btr_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size);
- }
+ if (dst_op.mode == MODE_REG_DIRECT) {
+ op_ir(code, inst, src_op.disp, dst_op.base, inst->extra.size);
} else {
- if (dst_op.mode == MODE_REG_DIRECT) {
- btc_ir(code, src_op.disp, dst_op.base, inst->extra.size);
- } else {
- btc_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size);
- }
+ op_irdisp(code, inst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size);
}
} else {
if (src_op.mode == MODE_REG_DISPLACE8 || (inst->dst.addr_mode != MODE_REG && src_op.base != opts->gen.scratch1 && src_op.base != opts->gen.scratch2)) {
@@ -1703,30 +1697,10 @@ void translate_m68k(m68k_options * opts, m68kinst * inst)
and_ir(code, 7, src_op.base, SZ_D);
size = SZ_D;
}
- if (inst->op == M68K_BTST) {
- if (dst_op.mode == MODE_REG_DIRECT) {
- bt_rr(code, src_op.base, dst_op.base, size);
- } else {
- bt_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, size);
- }
- } else if (inst->op == M68K_BSET) {
- if (dst_op.mode == MODE_REG_DIRECT) {
- bts_rr(code, src_op.base, dst_op.base, size);
- } else {
- bts_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, size);
- }
- } else if (inst->op == M68K_BCLR) {
- if (dst_op.mode == MODE_REG_DIRECT) {
- btr_rr(code, src_op.base, dst_op.base, size);
- } else {
- btr_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, size);
- }
+ if (dst_op.mode == MODE_REG_DIRECT) {
+ op_rr(code, inst, src_op.base, dst_op.base, size);
} else {
- if (dst_op.mode == MODE_REG_DIRECT) {
- btc_rr(code, src_op.base, dst_op.base, size);
- } else {
- btc_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, size);
- }
+ op_rrdisp(code, inst, src_op.base, dst_op.base, dst_op.disp, size);
}
if (src_op.base == opts->gen.scratch2) {
pop_r(code, opts->gen.scratch2);
diff --git a/m68k_internal.h b/m68k_internal.h
index ddc2c16..4c97ad0 100644
--- a/m68k_internal.h
+++ b/m68k_internal.h
@@ -46,8 +46,7 @@ void m68k_handle_deferred(m68k_context * context);
code_ptr get_native_address_trans(m68k_context * context, uint32_t address);
//individual instructions
-void translate_m68k_lea(m68k_options * opts, m68kinst * inst);
-void translate_m68k_pea(m68k_options * opts, m68kinst * inst);
+void translate_m68k_lea_pea(m68k_options * opts, m68kinst * inst);
void translate_m68k_bsr(m68k_options * opts, m68kinst * inst);
void translate_m68k_jmp_jsr(m68k_options * opts, m68kinst * inst);
void translate_m68k_unlk(m68k_options * opts, m68kinst * inst);