diff gen_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 937b47c9b79b
children f80fa1776507
line wrap: on
line diff
--- a/gen_x86.c	Tue Dec 18 23:55:10 2012 -0800
+++ b/gen_x86.c	Wed Dec 19 20:23:59 2012 -0800
@@ -40,6 +40,8 @@
 
 #define OP2_JCC 0x80
 #define OP2_SETCC 0x90
+#define OP2_BT 0xA3
+#define OP2_BTX_I 0xBA
 
 #define OP_EX_ADDI 0x0
 #define OP_EX_ORI  0x1
@@ -59,6 +61,11 @@
 #define OP_EX_SAL 0x6 //identical to SHL
 #define OP_EX_SAR 0x7
 
+#define OP_EX_BT  0x4
+#define OP_EX_BTS 0x5
+#define OP_EX_BTR 0x6
+#define OP_EX_BTC 0x7
+
 #define BIT_IMMED_RAX 0x4
 #define BIT_DIR 0x2
 #define BIT_SIZE 0x1
@@ -880,6 +887,106 @@
 	return out;
 }
 
+uint8_t * bt_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t size)
+{
+	if (size == SZ_W) {
+		*(out++) = PRE_SIZE;
+	}
+	if (size == SZ_Q || src >= R8 || dst >= R8) {
+		*out = PRE_REX;
+		if (size == SZ_Q) {
+			*out |= REX_QUAD;
+		}
+		if (src >= R8) {
+			*out |= REX_REG_FIELD;
+			src -= (R8 - X86_R8);
+		}
+		if (dst >= R8) {
+			*out |= REX_RM_FIELD;
+			dst -= (R8 - X86_R8);
+		}
+		out++;
+	}
+	*(out++) = PRE_2BYTE;
+	*(out++) = OP2_BT;
+	*(out++) = MODE_REG_DIRECT | dst | (src << 3);
+	return out;
+}
+
+uint8_t * bt_rrdisp8(uint8_t * out, uint8_t src, uint8_t dst_base, int8_t dst_disp, uint8_t size)
+{
+	if (size == SZ_W) {
+		*(out++) = PRE_SIZE;
+	}
+	if (size == SZ_Q || src >= R8 || dst_base >= R8) {
+		*out = PRE_REX;
+		if (size == SZ_Q) {
+			*out |= REX_QUAD;
+		}
+		if (src >= R8) {
+			*out |= REX_REG_FIELD;
+			src -= (R8 - X86_R8);
+		}
+		if (dst_base >= R8) {
+			*out |= REX_RM_FIELD;
+			dst_base -= (R8 - X86_R8);
+		}
+		out++;
+	}
+	*(out++) = PRE_2BYTE;
+	*(out++) = OP2_BT;
+	*(out++) = MODE_REG_DISPLACE8 | dst_base | (src << 3);
+	*(out++) = dst_disp;
+	return out;
+}
+
+uint8_t * bt_ir(uint8_t * out, uint8_t val, uint8_t dst, uint8_t size)
+{
+	if (size == SZ_W) {
+		*(out++) = PRE_SIZE;
+	}
+	if (size == SZ_Q || dst >= R8) {
+		*out = PRE_REX;
+		if (size == SZ_Q) {
+			*out |= REX_QUAD;
+		}
+		if (dst >= R8) {
+			*out |= REX_RM_FIELD;
+			dst -= (R8 - X86_R8);
+		}
+		out++;
+	}
+	*(out++) = PRE_2BYTE;
+	*(out++) = OP2_BTX_I;
+	*(out++) = MODE_REG_DIRECT | dst | (OP_EX_BT << 3);
+	*(out++) = val;
+	return out;
+}
+
+uint8_t * bt_irdisp8(uint8_t * out, uint8_t val, uint8_t dst_base, int8_t dst_disp, uint8_t size)
+{
+	if (size == SZ_W) {
+		*(out++) = PRE_SIZE;
+	}
+	if (size == SZ_Q || dst_base >= R8) {
+		*out = PRE_REX;
+		if (size == SZ_Q) {
+			*out |= REX_QUAD;
+		}
+		if (dst_base >= R8) {
+			*out |= REX_RM_FIELD;
+			dst_base -= (R8 - X86_R8);
+		}
+		out++;
+	}
+	*(out++) = PRE_2BYTE;
+	*(out++) = OP2_BTX_I;
+	*(out++) = MODE_REG_DISPLACE8 | dst_base | (OP_EX_BT << 3);
+	*(out++) = dst_disp;
+	*(out++) = val;
+	return out;
+}
+
 uint8_t * jcc(uint8_t * out, uint8_t cc, uint8_t * dest)
 {
 	ptrdiff_t disp = dest-(out+2);