diff m68k_to_x86.c @ 61:918468c623e9

Add support for BTST instruction (untested), absolute addressing mode for instructions other than move (untested) and fix decoding of MOVEM.
author Mike Pavone <pavone@retrodev.com>
date Wed, 19 Dec 2012 20:23:59 -0800
parents 32650c77008a
children 2b1a65f4b85d
line wrap: on
line diff
--- a/m68k_to_x86.c	Tue Dec 18 23:55:10 2012 -0800
+++ b/m68k_to_x86.c	Wed Dec 19 20:23:59 2012 -0800
@@ -175,8 +175,9 @@
 		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 @@
 		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 @@
 	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 @@
 		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: