diff m68k_to_x86.c @ 146:5416a5c4628e

Implement most of the "X" instructions
author Mike Pavone <pavone@retrodev.com>
date Mon, 31 Dec 2012 20:09:09 -0800
parents c4d10c2aaee2
children 3e68e517cc01
line wrap: on
line diff
--- a/m68k_to_x86.c	Mon Dec 31 19:17:01 2012 -0800
+++ b/m68k_to_x86.c	Mon Dec 31 20:09:09 2012 -0800
@@ -2172,8 +2172,31 @@
 		dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B);
 		dst = m68k_save_result(inst, dst, opts);
 		break;
-	//case M68K_ADDX:
-	//	break;
+	case M68K_ADDX:
+		dst = cycles(dst, BUS);
+		dst = bt_irdisp8(dst, 0, CONTEXT, 0, SZ_B);
+		if (src_op.mode == MODE_REG_DIRECT) {
+			if (dst_op.mode == MODE_REG_DIRECT) {
+				dst = adc_rr(dst, src_op.base, dst_op.base, inst->extra.size);
+			} else {
+				dst = adc_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, inst->extra.size);
+			}
+		} else if (src_op.mode == MODE_REG_DISPLACE8) {
+			dst = adc_rdisp8r(dst, src_op.base, src_op.disp, dst_op.base, inst->extra.size);
+		} else {
+			if (dst_op.mode == MODE_REG_DIRECT) {
+				dst = adc_ir(dst, src_op.disp, dst_op.base, inst->extra.size);
+			} else {
+				dst = adc_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size);
+			}
+		}
+		dst = setcc_r(dst, CC_C, FLAG_C);
+		dst = setcc_r(dst, CC_Z, FLAG_Z);
+		dst = setcc_r(dst, CC_S, FLAG_N);
+		dst = setcc_r(dst, CC_O, FLAG_V);
+		dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B);
+		dst = m68k_save_result(inst, dst, opts);
+		break;
 	case M68K_AND:
 		dst = cycles(dst, BUS);
 		if (src_op.mode == MODE_REG_DIRECT) {
@@ -2636,8 +2659,107 @@
 			dst = setcc_r(dst, CC_S, FLAG_N);
 		}
 		break;
-	/*case M68K_ROXL:
-	case M68K_ROXR:*/
+	case M68K_ROXL:
+	case M68K_ROXR:
+		dst = mov_ir(dst, 0, FLAG_V, SZ_B);
+		if (inst->src.addr_mode == MODE_UNUSED) {
+			dst = cycles(dst, BUS);
+			//Memory rotate
+			dst = bt_irdisp8(dst, 0, CONTEXT, 0, SZ_B);
+			if (inst->op == M68K_ROXL) {
+				dst = rol_ir(dst, 1, dst_op.base, inst->extra.size);
+			} else {
+				dst = ror_ir(dst, 1, dst_op.base, inst->extra.size);
+			}
+			dst = setcc_r(dst, CC_C, FLAG_C);
+			dst = cmp_ir(dst, 0, dst_op.base, inst->extra.size);
+			dst = setcc_r(dst, CC_Z, FLAG_Z);
+			dst = setcc_r(dst, CC_S, FLAG_N);
+			dst = m68k_save_result(inst, dst, opts);
+		} else {
+			if (src_op.mode == MODE_IMMED) {
+				dst = cycles(dst, (inst->extra.size == OPSIZE_LONG ? 8 : 6) + src_op.disp*2);
+				dst = bt_irdisp8(dst, 0, CONTEXT, 0, SZ_B);
+				if (dst_op.mode == MODE_REG_DIRECT) {
+					if (inst->op == M68K_ROXL) {
+						dst = rol_ir(dst, src_op.disp, dst_op.base, inst->extra.size);
+					} else {
+						dst = ror_ir(dst, src_op.disp, dst_op.base, inst->extra.size);
+					}
+				} else {
+					if (inst->op == M68K_ROXL) {
+						dst = rol_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size);
+					} else {
+						dst = ror_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size);
+					}
+				}
+				dst = setcc_r(dst, CC_C, FLAG_C);
+			} else {
+				if (src_op.mode == MODE_REG_DIRECT) {
+					if (src_op.base != SCRATCH1) {
+						dst = mov_rr(dst, src_op.base, SCRATCH1, SZ_B);
+					}
+				} else {
+					dst = mov_rdisp8r(dst, src_op.base, src_op.disp, SCRATCH1, SZ_B);
+				}
+				dst = and_ir(dst, 63, SCRATCH1, SZ_D);
+				zero_off = dst+1;
+				dst = jcc(dst, CC_NZ, dst+2);
+				dst = add_rr(dst, SCRATCH1, CYCLES, SZ_D);
+				dst = add_rr(dst, SCRATCH1, CYCLES, SZ_D);
+				dst = cmp_ir(dst, 32, SCRATCH1, SZ_B);
+				norm_off = dst+1;
+				dst = jcc(dst, CC_L, dst+2);
+				dst = bt_irdisp8(dst, 0, CONTEXT, 0, SZ_B);
+				if (dst_op.mode == MODE_REG_DIRECT) {
+					if (inst->op == M68K_ROXL) {
+						dst = rol_ir(dst, 31, dst_op.base, inst->extra.size);
+						dst = rol_ir(dst, 1, dst_op.base, inst->extra.size);
+					} else {
+						dst = ror_ir(dst, 31, dst_op.base, inst->extra.size);
+						dst = ror_ir(dst, 1, dst_op.base, inst->extra.size);
+					}
+				} else {
+					if (inst->op == M68K_ROXL) {
+						dst = rol_irdisp8(dst, 31, dst_op.base, dst_op.disp, inst->extra.size);
+						dst = rol_irdisp8(dst, 1, dst_op.base, dst_op.disp, inst->extra.size);
+					} else {
+						dst = ror_irdisp8(dst, 31, dst_op.base, dst_op.disp, inst->extra.size);
+						dst = ror_irdisp8(dst, 1, dst_op.base, dst_op.disp, inst->extra.size);
+					}
+				}
+				dst = sub_ir(dst, 32, SCRATCH1, SZ_B);
+				*norm_off = dst - (norm_off+1);
+				dst = bt_irdisp8(dst, 0, CONTEXT, 0, SZ_B);
+				if (dst_op.mode == MODE_REG_DIRECT) {
+					if (inst->op == M68K_ROXL) {
+						dst = rol_clr(dst, dst_op.base, inst->extra.size);
+					} else {
+						dst = ror_clr(dst, dst_op.base, inst->extra.size);
+					}
+				} else {
+					if (inst->op == M68K_ROXL) {
+						dst = rol_clrdisp8(dst, dst_op.base, dst_op.disp, inst->extra.size);
+					} else {
+						dst = ror_clrdisp8(dst, dst_op.base, dst_op.disp, inst->extra.size);
+					}
+				}
+				dst = setcc_r(dst, CC_C, FLAG_C);
+				end_off = dst + 1;
+				dst = jmp(dst, dst+2);
+				*zero_off = dst - (zero_off+1);
+				dst = mov_ir(dst, 0, FLAG_C, SZ_B);
+				*end_off = dst - (end_off+1);
+			}
+			if (dst_op.mode == MODE_REG_DIRECT) {
+				dst = cmp_ir(dst, 0, dst_op.base, inst->extra.size);
+			} else {
+				dst = cmp_irdisp8(dst, 0, dst_op.base, dst_op.disp, inst->extra.size);
+			}
+			dst = setcc_r(dst, CC_Z, FLAG_Z);
+			dst = setcc_r(dst, CC_S, FLAG_N);
+		}
+		break;
 	case M68K_RTE:
 		dst = mov_rr(dst, opts->aregs[7], SCRATCH1, SZ_D);
 		dst = call(dst, (uint8_t *)m68k_read_long_scratch1);
@@ -2686,8 +2808,31 @@
 		dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B);
 		dst = m68k_save_result(inst, dst, opts);
 		break;
-	//case M68K_SUBX:
-	//	break;
+	case M68K_SUBX:
+		dst = cycles(dst, BUS);
+		dst = bt_irdisp8(dst, 0, CONTEXT, 0, SZ_B);
+		if (src_op.mode == MODE_REG_DIRECT) {
+			if (dst_op.mode == MODE_REG_DIRECT) {
+				dst = sbb_rr(dst, src_op.base, dst_op.base, inst->extra.size);
+			} else {
+				dst = sbb_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, inst->extra.size);
+			}
+		} else if (src_op.mode == MODE_REG_DISPLACE8) {
+			dst = sbb_rdisp8r(dst, src_op.base, src_op.disp, dst_op.base, inst->extra.size);
+		} else {
+			if (dst_op.mode == MODE_REG_DIRECT) {
+				dst = sbb_ir(dst, src_op.disp, dst_op.base, inst->extra.size);
+			} else {
+				dst = sbb_irdisp8(dst, src_op.disp, dst_op.base, dst_op.disp, inst->extra.size);
+			}
+		}
+		dst = setcc_r(dst, CC_C, FLAG_C);
+		dst = setcc_r(dst, CC_Z, FLAG_Z);
+		dst = setcc_r(dst, CC_S, FLAG_N);
+		dst = setcc_r(dst, CC_O, FLAG_V);
+		dst = mov_rrind(dst, FLAG_C, CONTEXT, SZ_B);
+		dst = m68k_save_result(inst, dst, opts);
+		break;
 	case M68K_SWAP:
 		dst = cycles(dst, BUS);
 		if (src_op.mode == MODE_REG_DIRECT) {