changeset 581:9f40aa5243c2

Combine implementations of lea and pea. Update bit instructions to use the op_ family of functions to simplify their implementation a bit.
author Michael Pavone <pavone@retrodev.com>
date Wed, 05 Mar 2014 19:26:53 -0800
parents 5157bc966c1a
children c05fcbfe1b1a
files m68k_core.c m68k_core_x86.c m68k_internal.h
diffstat 3 files changed, 43 insertions(+), 98 deletions(-) [+]
line wrap: on
line diff
--- a/m68k_core.c	Wed Mar 05 09:33:50 2014 -0800
+++ b/m68k_core.c	Wed Mar 05 19:26:53 2014 -0800
@@ -86,10 +86,10 @@
 	}
 }
 
-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 @@
 			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 @@
 		}
 		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)
--- a/m68k_core_x86.c	Wed Mar 05 09:33:50 2014 -0800
+++ b/m68k_core_x86.c	Wed Mar 05 19:26:53 2014 -0800
@@ -1300,6 +1300,10 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 			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 @@
 				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);
--- a/m68k_internal.h	Wed Mar 05 09:33:50 2014 -0800
+++ b/m68k_internal.h	Wed Mar 05 19:26:53 2014 -0800
@@ -46,8 +46,7 @@
 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);