changeset 15:c0f339564819

Make x86 generator generic with respect to operand size for immediate parameters.
author Mike Pavone <pavone@retrodev.com>
date Tue, 27 Nov 2012 22:43:32 -0800
parents 2bdad0f52f42
children 54fba9ef781b
files 68kinst.c 68kinst.h gen_x86.c gen_x86.h test_x86.c
diffstat 5 files changed, 173 insertions(+), 217 deletions(-) [+]
line wrap: on
line diff
--- a/68kinst.c	Tue Nov 27 09:28:13 2012 -0800
+++ b/68kinst.c	Tue Nov 27 22:43:32 2012 -0800
@@ -39,12 +39,12 @@
 		case 0:
 			dst->addr_mode = MODE_ABSOLUTE_SHORT;
 			ext = *(++cur);
-			dst->params.u32 = sign_extend16(ext);
+			dst->params.immed = sign_extend16(ext);
 			break;
 		case 1:
 			dst->addr_mode = MODE_ABSOLUTE;
 			ext = *(++cur);
-			dst->params.u32 = ext << 16 | *(++cur);
+			dst->params.immed = ext << 16 | *(++cur);
 			break;
 		case 2:
 			dst->addr_mode = MODE_PC_DISPLACE;
@@ -57,13 +57,13 @@
 			switch (size)
 			{
 			case OPSIZE_BYTE:
-				dst->params.u8 = ext;
+				dst->params.immed = ext & 0xFF;
 				break;
 			case OPSIZE_WORD:
-				dst->params.u16 = ext;
+				dst->params.immed = ext;
 				break;
 			case OPSIZE_LONG:
-				dst->params.u32 = ext << 16 | *(++cur);
+				dst->params.immed = ext << 16 | *(++cur);
 				break;
 			}
 			break;
@@ -145,7 +145,7 @@
 			opmode = (*istream >> 3) & 0x7;
 			reg = *istream & 0x7;
 			decoded->src.addr_mode = MODE_IMMEDIATE;
-			decoded->src.params.u8 = *(++istream);
+			decoded->src.params.immed = *(++istream) & 0xFF;
 			decoded->extra.size = OPSIZE_BYTE;
 			istream = m68k_decode_op_ex(istream, opmode, reg, OPSIZE_BYTE, &(decoded->dst));
 		} else if ((*istream & 0xC0) == 0xC0) {
@@ -160,12 +160,12 @@
 					decoded->op = M68K_ORI_CCR;
 					decoded->extra.size = OPSIZE_BYTE;
 					decoded->src.addr_mode = MODE_IMMEDIATE;
-					decoded->src.params.u8 = *(++istream);
+					decoded->src.params.immed = *(++istream) & 0xFF;
 				} else if((*istream & 0xFF) == 0x7C) {
 					decoded->op = M68K_ORI_SR;
 					decoded->extra.size = OPSIZE_WORD;
 					decoded->src.addr_mode = MODE_IMMEDIATE;
-					decoded->src.params.u16 = *(++istream);
+					decoded->src.params.immed = *(++istream);
 				} else {
 					decoded->op = M68K_OR;
 					decoded->variant = VAR_IMMEDIATE;
@@ -176,14 +176,14 @@
 					switch (size)
 					{
 					case OPSIZE_BYTE:
-						decoded->src.params.u8 = *(++istream);
+						decoded->src.params.immed = *(++istream) & 0xFF;
 						break;
 					case OPSIZE_WORD:
-						decoded->src.params.u16 = *(++istream);
+						decoded->src.params.immed = *(++istream);
 						break;
 					case OPSIZE_LONG:
 						immed = *(++istream);
-						decoded->src.params.u32 = immed << 16 | *(++istream);
+						decoded->src.params.immed = immed << 16 | *(++istream);
 						break;
 					}
 					istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst));
@@ -195,12 +195,12 @@
 					decoded->op = M68K_ANDI_CCR;
 					decoded->extra.size = OPSIZE_BYTE;
 					decoded->src.addr_mode = MODE_IMMEDIATE;
-					decoded->src.params.u8 = *(++istream);
+					decoded->src.params.immed = *(++istream) & 0xFF;
 				} else if((*istream & 0xFF) == 0x7C) {
 					decoded->op = M68K_ANDI_SR;
 					decoded->extra.size = OPSIZE_WORD;
 					decoded->src.addr_mode = MODE_IMMEDIATE;
-					decoded->src.params.u16 = *(++istream);
+					decoded->src.params.immed = *(++istream);
 				} else {
 					decoded->op = M68K_AND;
 					decoded->variant = VAR_IMMEDIATE;
@@ -211,14 +211,14 @@
 					switch (size)
 					{
 					case OPSIZE_BYTE:
-						decoded->src.params.u8 = *(++istream);
+						decoded->src.params.immed = *(++istream) & 0xFF;
 						break;
 					case OPSIZE_WORD:
-						decoded->src.params.u16 = *(++istream);
+						decoded->src.params.immed = *(++istream);
 						break;
 					case OPSIZE_LONG:
 						immed = *(++istream);
-						decoded->src.params.u32 = immed << 16 | *(++istream);
+						decoded->src.params.immed = immed << 16 | *(++istream);
 						break;
 					}
 					istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst));
@@ -234,14 +234,14 @@
 				switch (size)
 				{
 				case OPSIZE_BYTE:
-					decoded->src.params.u8 = *(++istream);
+					decoded->src.params.immed = *(++istream) & 0xFF;
 					break;
 				case OPSIZE_WORD:
-					decoded->src.params.u16 = *(++istream);
+					decoded->src.params.immed = *(++istream);
 					break;
 				case OPSIZE_LONG:
 					immed = *(++istream);
-					decoded->src.params.u32 = immed << 16 | *(++istream);
+					decoded->src.params.immed = immed << 16 | *(++istream);
 					break;
 				}
 				istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst));
@@ -256,14 +256,14 @@
 				switch (size)
 				{
 				case OPSIZE_BYTE:
-					decoded->src.params.u8 = *(++istream);
+					decoded->src.params.immed = *(++istream) & 0xFF;
 					break;
 				case OPSIZE_WORD:
-					decoded->src.params.u16 = *(++istream);
+					decoded->src.params.immed = *(++istream);
 					break;
 				case OPSIZE_LONG:
 					immed = *(++istream);
-					decoded->src.params.u32 = immed << 16 | *(++istream);
+					decoded->src.params.immed = immed << 16 | *(++istream);
 					break;
 				}
 				istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst));
@@ -286,7 +286,7 @@
 					break;
 				}
 				decoded->src.addr_mode = MODE_IMMEDIATE;
-				decoded->src.params.u8 = *(++istream);
+				decoded->src.params.immed = *(++istream) & 0xFF;
 				istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst));
 				break;
 			case 5:
@@ -295,12 +295,12 @@
 					decoded->op = M68K_EORI_CCR;
 					decoded->extra.size = OPSIZE_BYTE;
 					decoded->src.addr_mode = MODE_IMMEDIATE;
-					decoded->src.params.u8 = *(++istream);
+					decoded->src.params.immed = *(++istream) & 0xFF;
 				} else if((*istream & 0xFF) == 0x7C) {
 					decoded->op = M68K_EORI_SR;
 					decoded->extra.size = OPSIZE_WORD;
 					decoded->src.addr_mode = MODE_IMMEDIATE;
-					decoded->src.params.u16 = *(++istream);
+					decoded->src.params.immed = *(++istream);
 				} else {
 					decoded->op = M68K_EOR;
 					decoded->variant = VAR_IMMEDIATE;
@@ -311,14 +311,14 @@
 					switch (size)
 					{
 					case OPSIZE_BYTE:
-						decoded->src.params.u8 = *(++istream);
+						decoded->src.params.immed = *(++istream) & 0xFF;
 						break;
 					case OPSIZE_WORD:
-						decoded->src.params.u16 = *(++istream);
+						decoded->src.params.immed = *(++istream);
 						break;
 					case OPSIZE_LONG:
 						immed = *(++istream);
-						decoded->src.params.u32 = immed << 16 | *(++istream);
+						decoded->src.params.immed = immed << 16 | *(++istream);
 						break;
 					}
 					istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst));
@@ -334,14 +334,14 @@
 				switch (decoded->extra.size)
 				{
 				case OPSIZE_BYTE:
-					decoded->src.params.u8 = *(++istream);
+					decoded->src.params.immed = *(++istream) & 0xFF;
 					break;
 				case OPSIZE_WORD:
-					decoded->src.params.u16 = *(++istream);
+					decoded->src.params.immed = *(++istream);
 					break;
 				case OPSIZE_LONG:
 					immed = *(++istream);
-					decoded->src.params.u32 = (immed << 16) | *(++istream);
+					decoded->src.params.immed = (immed << 16) | *(++istream);
 					break;
 				}
 				istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst));
@@ -411,11 +411,11 @@
 					immed = *(++istream);
 					if(*istream & 0x400) {
 						decoded->dst.addr_mode = MODE_REG;
-						decoded->dst.params.u16 = immed;
+						decoded->dst.params.immed = immed;
 						istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->src));
 					} else {
 						decoded->src.addr_mode = MODE_REG;
-						decoded->src.params.u16 = immed;
+						decoded->src.params.immed = immed;
 						istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst));
 					}
 				} else {
@@ -497,7 +497,7 @@
 							decoded->op = M68K_BKPT;
 							decoded->src.addr_mode = MODE_IMMEDIATE;
 							decoded->extra.size = OPSIZE_UNSIZED;
-							decoded->src.params.u32 = *istream & 0x7;
+							decoded->src.params.immed = *istream & 0x7;
 #endif
 							break;
 						case 0x10:
@@ -573,7 +573,7 @@
 								decoded->op = M68K_TRAP;
 								decoded->extra.size = OPSIZE_UNSIZED;
 								decoded->src.addr_mode = MODE_IMMEDIATE;
-								decoded->src.params.u32 = *istream & 0xF;
+								decoded->src.params.immed = *istream & 0xF;
 								break;
 							case 2:
 								//LINK.w
@@ -582,7 +582,7 @@
 								decoded->src.addr_mode = MODE_AREG;
 								decoded->src.params.regs.pri = *istream & 0x7;
 								decoded->dst.addr_mode = MODE_IMMEDIATE;
-								decoded->dst.params.u16 = *(++istream);
+								decoded->dst.params.immed = *(++istream);
 								break;
 							case 3:
 								//UNLK
@@ -616,7 +616,7 @@
 								case 2:
 									decoded->op = M68K_STOP;
 									decoded->src.addr_mode = MODE_IMMEDIATE;
-									decoded->src.params.u32 =*(++istream);
+									decoded->src.params.immed =*(++istream);
 									break;
 								case 3:
 									decoded->op = M68K_RTE;
@@ -625,7 +625,7 @@
 #ifdef M68010
 									decoded->op = M68K_RTD;
 									decoded->src.addr_mode = MODE_IMMEDIATE;
-									decoded->src.params.u32 =*(++istream);
+									decoded->src.params.immed =*(++istream);
 #endif
 									break;
 								case 5:
@@ -662,7 +662,7 @@
 			case 1: //DBcc
 				decoded->op = M68K_DBCC;
 				decoded->src.addr_mode = MODE_IMMEDIATE;
-				decoded->src.params.u16 = *(++istream);
+				decoded->src.params.immed = *(++istream);
 				decoded->dst.addr_mode = MODE_REG;
 				decoded->dst.params.regs.pri = *istream & 0x7;
 				break;
@@ -688,18 +688,7 @@
 			if (!immed) {
 				immed = 8;
 			}
-			switch (size)
-			{
-			case OPSIZE_BYTE:
-				decoded->src.params.u8 = immed;
-				break;
-			case OPSIZE_WORD:
-				decoded->src.params.u16 = immed;
-				break;
-			case OPSIZE_LONG:
-				decoded->src.params.u32 = immed;
-				break;
-			}
+			decoded->src.params.immed = immed;
 			if (*istream & 0x100) {
 				decoded->op = M68K_SUB;
 			} else {
@@ -724,13 +713,14 @@
 			decoded->variant = VAR_BYTE;
 			immed = sign_extend8(immed);
 		}
-		decoded->src.params.u32 = immed;
+		decoded->src.params.immed = immed;
 		break;
 	case MOVEQ:
 		decoded->op = M68K_MOVE;
 		decoded->variant = VAR_QUICK;
+		decoded->extra.size = OPSIZE_LONG;
 		decoded->src.addr_mode = MODE_IMMEDIATE;
-		decoded->src.params.u32 = sign_extend8(*istream & 0xFF);
+		decoded->src.params.immed = sign_extend8(*istream & 0xFF);
 		decoded->dst.addr_mode = MODE_REG;
 		decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream);
 		immed = *istream & 0xFF;
@@ -1012,18 +1002,7 @@
 			immed = (*istream >> 9) & 0x7;
 			if (*istream & 0x100) {
 				decoded->src.addr_mode = MODE_IMMEDIATE;
-				switch(decoded->extra.size)
-				{
-				case OPSIZE_BYTE:
-					decoded->src.params.u8 = immed;
-					break;
-				case OPSIZE_WORD:
-					decoded->src.params.u16 = immed;
-					break;
-				case OPSIZE_LONG:
-					decoded->src.params.u32 = immed;
-					break;
-				}
+				decoded->src.params.immed = immed;
 			} else {
 				decoded->src.addr_mode = MODE_REG;
 				decoded->src.params.regs.pri = immed;
@@ -1136,7 +1115,7 @@
 	"le"
 };
 
-int m68k_disasm_op(m68k_op_info *decoded, uint8_t size, char *dst, int need_comma)
+int m68k_disasm_op(m68k_op_info *decoded, char *dst, int need_comma)
 {
 	char * c = need_comma ? "," : "";
 	switch(decoded->addr_mode)
@@ -1154,11 +1133,11 @@
 	case MODE_AREG_DISPLACE:
 		return sprintf(dst, "%s (a%d, %d)", c, decoded->params.regs.pri, decoded->params.regs.displacement);
 	case MODE_IMMEDIATE:
-		return sprintf(dst, "%s #%d", c, (size == OPSIZE_LONG || size == OPSIZE_UNSIZED) ? decoded->params.u32 : (size == OPSIZE_WORD ? decoded->params.u16 : decoded->params.u8));
+		return sprintf(dst, "%s #%d", c, decoded->params.immed);
 	case MODE_ABSOLUTE_SHORT:
-		return sprintf(dst, "%s $%X.w", c, decoded->params.u32);
+		return sprintf(dst, "%s $%X.w", c, decoded->params.immed);
 	case MODE_ABSOLUTE:
-		return sprintf(dst, "%s $%X", c, decoded->params.u32);
+		return sprintf(dst, "%s $%X", c, decoded->params.immed);
 	case MODE_PC_DISPLACE:
 		return sprintf(dst, "%s (pc, %d)", c, decoded->params.regs.displacement);
 	default:
@@ -1166,7 +1145,7 @@
 	}
 }
 
-int m68k_disasm_movem_op(m68k_op_info *decoded, m68k_op_info *other, uint8_t size, char *dst, int need_comma)
+int m68k_disasm_movem_op(m68k_op_info *decoded, m68k_op_info *other, char *dst, int need_comma)
 {
 	int8_t dir, reg, bit, regnum, last=-1, lastreg, first=-1;
 	char *rtype, *last_rtype;
@@ -1181,7 +1160,7 @@
 		}
 		strcat(dst, " ");
 		for (oplen = 1, reg=0; bit < 16 && bit > -1; bit += dir, reg++) {
-			if (decoded->params.u16 & (1 << bit)) {
+			if (decoded->params.immed & (1 << bit)) {
 				if (reg > 7) {
 					rtype = "a";
 					regnum = reg - 8;
@@ -1214,7 +1193,7 @@
 		}
 		return oplen;
 	} else {
-		return m68k_disasm_op(decoded, size, dst, need_comma);
+		return m68k_disasm_op(decoded, dst, need_comma);
 	}
 }
 
@@ -1233,16 +1212,14 @@
 		dst[ret] = 0;
 		strcat(dst, cond_mnem[decoded->extra.cond]);
 		ret = strlen(dst);
-		size = decoded->op = M68K_BCC ? OPSIZE_LONG : OPSIZE_WORD;
 		break;
 	case M68K_BSR:
-		size = OPSIZE_LONG;
 		ret = sprintf(dst, "bsr%s", decoded->variant == VAR_BYTE ? ".s" : "");
 		break;
 	case M68K_MOVE_FROM_SR:
 		ret = sprintf(dst, "%s", mnemonics[decoded->op]);
 		ret += sprintf(dst + ret, " SR");
-		ret += m68k_disasm_op(&(decoded->dst), decoded->extra.size, dst + ret, 1);
+		ret += m68k_disasm_op(&(decoded->dst), dst + ret, 1);
 		return ret;
 	case M68K_ANDI_SR:
 	case M68K_EORI_SR:
@@ -1254,7 +1231,7 @@
 	case M68K_MOVE_CCR:
 	case M68K_ORI_CCR:
 		ret = sprintf(dst, "%s", mnemonics[decoded->op]);
-		ret += m68k_disasm_op(&(decoded->src), decoded->extra.size, dst + ret, 0);
+		ret += m68k_disasm_op(&(decoded->src), dst + ret, 0);
 		ret += sprintf(dst + ret, ", %s", special_op);
 		return ret;
 	default:
@@ -1265,13 +1242,13 @@
 				size == OPSIZE_BYTE ? ".b" : (size == OPSIZE_WORD ? ".w" : (size == OPSIZE_LONG ? ".l" : "")));
 	}
 	if (decoded->op == M68K_MOVEM) {
-		op1len = m68k_disasm_movem_op(&(decoded->src), &(decoded->dst), size, dst + ret, 0);
+		op1len = m68k_disasm_movem_op(&(decoded->src), &(decoded->dst), dst + ret, 0);
 		ret += op1len;
-		ret += m68k_disasm_movem_op(&(decoded->dst), &(decoded->src), size, dst + ret, op1len);
+		ret += m68k_disasm_movem_op(&(decoded->dst), &(decoded->src), dst + ret, op1len);
 	} else {
-		op1len = m68k_disasm_op(&(decoded->src), size, dst + ret, 0);
+		op1len = m68k_disasm_op(&(decoded->src), dst + ret, 0);
 		ret += op1len;
-		ret += m68k_disasm_op(&(decoded->dst), size, dst + ret, op1len);
+		ret += m68k_disasm_op(&(decoded->dst), dst + ret, op1len);
 	}
 	return ret;
 }
--- a/68kinst.h	Tue Nov 27 09:28:13 2012 -0800
+++ b/68kinst.h	Tue Nov 27 22:43:32 2012 -0800
@@ -158,9 +158,7 @@
 			uint8_t sec;
 			int32_t displacement;
 		} regs;
-		uint8_t u8;
-		uint16_t u16;
-		uint32_t u32;
+		uint32_t immed;
 	} params;
 } m68k_op_info;
 
--- a/gen_x86.c	Tue Nov 27 09:28:13 2012 -0800
+++ b/gen_x86.c	Tue Nov 27 22:43:32 2012 -0800
@@ -29,6 +29,7 @@
 #define OP_MOV_I8R 0xB0
 #define OP_MOV_IR 0xB8
 #define OP_RETN 0xC3
+#define OP_MOV_IEA 0xC6
 #define OP_CALL 0xE8
 #define OP_CALL_EA 0xFF
 
@@ -197,79 +198,77 @@
 	return out;
 }
 
-uint8_t * x86_i8r(uint8_t * out, uint8_t opcode, uint8_t op_ex, uint8_t al_opcode, uint8_t val, uint8_t dst)
+uint8_t * x86_ir(uint8_t * out, uint8_t opcode, uint8_t op_ex, uint8_t al_opcode, int32_t val, uint8_t dst, uint8_t size)
 {
-	if (dst == RAX) {
+	uint8_t sign_extend = 0;
+	if ((size == SZ_D || size == SZ_Q) && val <= 0x7F && val >= -0x80) {
+		sign_extend = 1;
+		opcode |= BIT_DIR;
+	}
+	if (size == SZ_W) {
+		*(out++) = PRE_SIZE;
+	}
+	if (dst == RAX && !sign_extend) {
+		if (size != SZ_B) {
+			al_opcode |= BIT_SIZE;
+			if (size == SZ_Q) {
+				*out = PRE_REX | REX_QUAD;
+			}
+		}
 		*(out++) = al_opcode | BIT_IMMED_RAX;
 	} else {
+		if (size == SZ_Q || dst >= R8 || (size == SZ_B && dst >= RSP && dst <= RDI)) {
+			*out = PRE_REX;
+			if (size == SZ_Q) {
+				*out |= REX_QUAD;
+			}
+			if (dst >= R8) {
+				*out |= REX_RM_FIELD;
+				dst -= (R8 - X86_R8);
+			}
+			out++;
+		}
 		if (dst >= AH && dst <= BH) {
 			dst -= (AH-X86_AH);
-		} else if(dst >= R8) {
-			*(out++) = PRE_REX | REX_RM_FIELD;
+		}
+		if (size != SZ_B) {
+			opcode |= BIT_SIZE;
 		}
 		*(out++) = opcode;
 		*(out++) = MODE_REG_DIRECT | dst | (op_ex << 3);
 	}
 	*(out++) = val;
+	if (size != SZ_B && !sign_extend) {
+		val >>= 8;
+		*(out++) = val;
+		if (size != SZ_W) {
+			val >>= 8;
+			*(out++) = val;
+			val >>= 8;
+			*(out++) = val;
+		}
+	}
 	return out;
 }
 
-uint8_t * x86_i32r(uint8_t * out, uint8_t opcode, uint8_t op_ex, uint8_t al_opcode, int32_t val, uint8_t dst)
-{
-	uint8_t sign_extend = 0;
-	if (val <= 0x7F && val >= -0x80) {
-		sign_extend = 1;
-		opcode |= BIT_DIR;
-	}
-	if (dst == RAX && !sign_extend) {
-		*(out++) = al_opcode | BIT_IMMED_RAX | BIT_SIZE;
-	} else {
-		if(dst >= R8) {
-			*(out++) = PRE_REX | REX_RM_FIELD;
-		}
-		*(out++) = opcode | BIT_SIZE;
-		*(out++) = MODE_REG_DIRECT | dst | (op_ex << 3);
-	}
-	*(out++) = val;
-	if (!sign_extend) {
-		val >>= 8;
-		*(out++) = val;
-		val >>= 8;
-		*(out++) = val;
-		val >>= 8;
-		*(out++) = val;
-	}
-	return out;
-}
 
 uint8_t * add_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
 {
 	return x86_rr_sizedir(out, OP_ADD, src, dst, size);
 }
 
-uint8_t * add_i8r(uint8_t * out, uint8_t val, uint8_t dst)
+uint8_t * add_ir(uint8_t * out, int32_t val, uint8_t dst, uint8_t size)
 {
-	return x86_i8r(out, OP_IMMED_ARITH, OP_EX_ADDI, OP_ADD, val, dst);
-}
-
-uint8_t * add_i32r(uint8_t * out, int32_t val, uint8_t dst)
-{
-	return x86_i32r(out, OP_IMMED_ARITH, OP_EX_ADDI, OP_ADD, val, dst);
+	return x86_ir(out, OP_IMMED_ARITH, OP_EX_ADDI, OP_ADD, val, dst, size);
 }
 
 uint8_t * or_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
 {
 	return x86_rr_sizedir(out, OP_OR, src, dst, size);
 }
-
-uint8_t * or_i8r(uint8_t * out, uint8_t val, uint8_t dst)
+uint8_t * or_ir(uint8_t * out, int32_t val, uint8_t dst, uint8_t size)
 {
-	return x86_i8r(out, OP_IMMED_ARITH, OP_EX_ORI, OP_OR, val, dst);
-}
-
-uint8_t * or_i32r(uint8_t * out, int32_t val, uint8_t dst)
-{
-	return x86_i32r(out, OP_IMMED_ARITH, OP_EX_ORI, OP_OR, val, dst);
+	return x86_ir(out, OP_IMMED_ARITH, OP_EX_ORI, OP_OR, val, dst, size);
 }
 
 uint8_t * and_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
@@ -277,14 +276,9 @@
 	return x86_rr_sizedir(out, OP_AND, src, dst, size);
 }
 
-uint8_t * and_i8r(uint8_t * out, uint8_t val, uint8_t dst)
+uint8_t * and_ir(uint8_t * out, int32_t val, uint8_t dst, uint8_t size)
 {
-	return x86_i8r(out, OP_IMMED_ARITH, OP_EX_ANDI, OP_AND, val, dst);
-}
-
-uint8_t * and_i32r(uint8_t * out, int32_t val, uint8_t dst)
-{
-	return x86_i32r(out, OP_IMMED_ARITH, OP_EX_ANDI, OP_AND, val, dst);
+	return x86_ir(out, OP_IMMED_ARITH, OP_EX_ANDI, OP_AND, val, dst, size);
 }
 
 uint8_t * xor_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
@@ -292,14 +286,9 @@
 	return x86_rr_sizedir(out, OP_XOR, src, dst, size);
 }
 
-uint8_t * xor_i8r(uint8_t * out, uint8_t val, uint8_t dst)
+uint8_t * xor_ir(uint8_t * out, int32_t val, uint8_t dst, uint8_t size)
 {
-	return x86_i8r(out, OP_IMMED_ARITH, OP_EX_XORI, OP_XOR, val, dst);
-}
-
-uint8_t * xor_i32r(uint8_t * out, int32_t val, uint8_t dst)
-{
-	return x86_i32r(out, OP_IMMED_ARITH, OP_EX_XORI, OP_XOR, val, dst);
+	return x86_ir(out, OP_IMMED_ARITH, OP_EX_XORI, OP_XOR, val, dst, size);
 }
 
 uint8_t * sub_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
@@ -307,30 +296,19 @@
 	return x86_rr_sizedir(out, OP_SUB, src, dst, size);
 }
 
-uint8_t * sub_i8r(uint8_t * out, uint8_t val, uint8_t dst)
+uint8_t * sub_ir(uint8_t * out, int32_t val, uint8_t dst, uint8_t size)
 {
-	return x86_i8r(out, OP_IMMED_ARITH, OP_EX_SUBI, OP_SUB, val, dst);
+	return x86_ir(out, OP_IMMED_ARITH, OP_EX_SUBI, OP_SUB, val, dst, size);
 }
 
-uint8_t * sub_i32r(uint8_t * out, int32_t val, uint8_t dst)
-{
-	return x86_i32r(out, OP_IMMED_ARITH, OP_EX_SUBI, OP_SUB, val, dst);
-}
-
-
 uint8_t * cmp_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
 {
 	return x86_rr_sizedir(out, OP_CMP, src, dst, size);
 }
 
-uint8_t * cmp_i8r(uint8_t * out, uint8_t val, uint8_t dst)
+uint8_t * cmp_ir(uint8_t * out, int32_t val, uint8_t dst, uint8_t size)
 {
-	return x86_i8r(out, OP_IMMED_ARITH, OP_EX_CMPI, OP_CMP, val, dst);
-}
-
-uint8_t * cmp_i32r(uint8_t * out, int32_t val, uint8_t dst)
-{
-	return x86_i32r(out, OP_IMMED_ARITH, OP_EX_CMPI, OP_CMP, val, dst);
+	return x86_ir(out, OP_IMMED_ARITH, OP_EX_CMPI, OP_CMP, val, dst, size);
 }
 
 uint8_t * mov_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
@@ -358,49 +336,58 @@
 	return x86_rrind_sizedir(out, OP_MOV, dst, src, size, BIT_DIR);
 }
 
-uint8_t * mov_i8r(uint8_t * out, uint8_t val, uint8_t dst)
-{
-	if (dst >= AH && dst <= BH) {
-		dst -= AH - X86_AH;
-	} else if (dst >= RSP && dst <= RDI) {
-		*(out++) = PRE_REX;
-	} else if (dst >= R8) {
-		*(out++) = PRE_REX | REX_RM_FIELD;
-		dst -= R8 - X86_R8;
+uint8_t * mov_ir(uint8_t * out, int64_t val, uint8_t dst, uint8_t size)
+{	
+	uint8_t sign_extend = 0;
+	if (size == SZ_Q && val <= 0x7FFFFFFF && val >= -2147483648) {
+		sign_extend = 1;
+	}
+	if (size == SZ_W) {
+		*(out++) = PRE_SIZE;
 	}
-	*(out++) = OP_MOV_I8R | dst;
-	*(out++) = val;
-	return out;
-}
-
-uint8_t * mov_i16r(uint8_t * out, uint16_t val, uint8_t dst)
-{
-	*(out++) = PRE_SIZE;
-	if (dst >= R8) {
-		*(out++) = PRE_REX | REX_RM_FIELD;
-		dst -= R8 - X86_R8;
+	if (size == SZ_Q || dst >= R8 || (size == SZ_B && dst >= RSP && dst <= RDI)) {
+		*out = PRE_REX;
+		if (size == SZ_Q) {
+			*out |= REX_QUAD;
+		}
+		if (dst >= R8) {
+			*out |= REX_RM_FIELD;
+			dst -= (R8 - X86_R8);
+		}
+		out++;
+	}
+	if (dst >= AH && dst <= BH) {
+		dst -= (AH-X86_AH);
 	}
-	*(out++) = OP_MOV_IR | dst;
-	*(out++) = val;
-	val >>= 8;
+	if (size == SZ_B) {
+		*(out++) = OP_MOV_I8R;
+	} else if (size == SZ_Q && sign_extend) {
+		*(out++) = OP_MOV_IEA | BIT_SIZE;
+		*(out++) = MODE_REG_DIRECT | dst;
+	} else {
+		*(out++) = OP_MOV_IR;
+	}
 	*(out++) = val;
-	return out;
-}
-
-uint8_t * mov_i32r(uint8_t * out, uint32_t val, uint8_t dst)
-{
-	if (dst >= R8) {
-		*(out++) = PRE_REX | REX_RM_FIELD;
-		dst -= R8 - X86_R8;
+	if (size != SZ_B) {
+		val >>= 8;
+		*(out++) = val;
+		if (size != SZ_W) {
+			val >>= 8;
+			*(out++) = val;
+			val >>= 8;
+			*(out++) = val;
+			if (size == SZ_Q && !sign_extend) {
+				val >>= 8;
+				*(out++) = val;
+				val >>= 8;
+				*(out++) = val;
+				val >>= 8;
+				*(out++) = val;
+				val >>= 8;
+				*(out++) = val;
+			}
+		}
 	}
-	*(out++) = OP_MOV_IR | dst;
-	*(out++) = val;
-	val >>= 8;
-	*(out++) = val;
-	val >>= 8;
-	*(out++) = val;
-	val >>= 8;
-	*(out++) = val;
 	return out;
 }
 
--- a/gen_x86.h	Tue Nov 27 09:28:13 2012 -0800
+++ b/gen_x86.h	Tue Nov 27 22:43:32 2012 -0800
@@ -58,26 +58,18 @@
 uint8_t * and_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size);
 uint8_t * sub_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size);
 uint8_t * cmp_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size);
-uint8_t * add_i8r(uint8_t * out, uint8_t val, uint8_t dst);
-uint8_t * or_i8r(uint8_t * out, uint8_t val, uint8_t dst);
-uint8_t * xor_i8r(uint8_t * out, uint8_t val, uint8_t dst);
-uint8_t * and_i8r(uint8_t * out, uint8_t val, uint8_t dst);
-uint8_t * sub_i8r(uint8_t * out, uint8_t val, uint8_t dst);
-uint8_t * cmp_i8r(uint8_t * out, uint8_t val, uint8_t dst);
-uint8_t * add_i32r(uint8_t * out, int32_t val, uint8_t dst);
-uint8_t * or_i32r(uint8_t * out, int32_t val, uint8_t dst);
-uint8_t * xor_i32r(uint8_t * out, int32_t val, uint8_t dst);
-uint8_t * and_i32r(uint8_t * out, int32_t val, uint8_t dst);
-uint8_t * sub_i32r(uint8_t * out, int32_t val, uint8_t dst);
-uint8_t * cmp_i32r(uint8_t * out, int32_t val, uint8_t dst);
+uint8_t * add_ir(uint8_t * out, int32_t val, uint8_t dst, uint8_t size);
+uint8_t * or_ir(uint8_t * out, int32_t val, uint8_t dst, uint8_t size);
+uint8_t * xor_ir(uint8_t * out, int32_t val, uint8_t dst, uint8_t size);
+uint8_t * and_ir(uint8_t * out, int32_t val, uint8_t dst, uint8_t size);
+uint8_t * sub_ir(uint8_t * out, int32_t val, uint8_t dst, uint8_t size);
+uint8_t * cmp_ir(uint8_t * out, int32_t val, uint8_t dst, uint8_t size);
 uint8_t * mov_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size);
 uint8_t * mov_rrdisp8(uint8_t * out, uint8_t src, uint8_t dst_base, int8_t disp, uint8_t size);
 uint8_t * mov_rdisp8r(uint8_t * out, uint8_t src_base, int8_t disp, uint8_t dst, uint8_t size);
 uint8_t * mov_rrind(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size);
 uint8_t * mov_rindr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size);
-uint8_t * mov_i8r(uint8_t * out, uint8_t val, uint8_t dst);
-uint8_t * mov_i16r(uint8_t * out, uint16_t val, uint8_t dst);
-uint8_t * mov_i32r(uint8_t * out, uint32_t val, uint8_t dst);
+uint8_t * mov_ir(uint8_t * out, int64_t val, uint8_t dst, uint8_t size);
 uint8_t * pushf(uint8_t * out);
 uint8_t * popf(uint8_t * out);
 uint8_t * push_r(uint8_t * out, uint8_t reg);
--- a/test_x86.c	Tue Nov 27 09:28:13 2012 -0800
+++ b/test_x86.c	Tue Nov 27 22:43:32 2012 -0800
@@ -1,4 +1,5 @@
 #include "gen_x86.h"
+#include "m68k_to_x86.h"
 #include <stdio.h>
 #include <stddef.h>
 
@@ -14,12 +15,13 @@
 	cur = mov_rr(cur, R11, R12, SZ_W);
 	cur = mov_rr(cur, RAX, RBX, SZ_D);
 	cur = mov_rr(cur, RAX, RBX, SZ_Q);
-	cur = mov_i32r(cur, 5, RAX);
-	cur = mov_i32r(cur, 3, R8);
-	cur = mov_i8r(cur, 4, RSP);
+	cur = mov_ir(cur, 5, RAX, SZ_D);
+	cur = mov_ir(cur, 3, R8, SZ_D);
+	cur = mov_ir(cur, 4, RSP, SZ_B);
 	cur = add_rr(cur, RAX, RBX, SZ_D);
-	cur = add_i8r(cur, 5, RAX);
-	cur = add_i8r(cur, 5, RBX);
+	cur = add_ir(cur, 5, RAX, SZ_B);
+	cur = add_ir(cur, 5, RBX, SZ_B);
+	cur = add_ir(cur, 5, RBP, SZ_B);
 	cur = pushf(cur);
 	cur = popf(cur);
 	cur = setcc_r(cur, CC_S, RBX);