diff gen_x86.c @ 81:6d231dbe75ab

Add support for indexed modes as a source, some work on jmp and jsr with areg indirect mode
author Mike Pavone <pavone@retrodev.com>
date Sat, 22 Dec 2012 21:37:25 -0800
parents f80fa1776507
children 6331ddec228f
line wrap: on
line diff
--- a/gen_x86.c	Fri Dec 21 22:33:24 2012 -0800
+++ b/gen_x86.c	Sat Dec 22 21:37:25 2012 -0800
@@ -20,6 +20,7 @@
 #define PRE_REX 0x40
 #define OP_PUSH 0x50
 #define OP_POP 0x58
+#define OP_MOVSXD 0x63
 #define PRE_SIZE 0x66
 #define OP_JCC 0x70
 #define OP_IMMED_ARITH 0x80
@@ -36,12 +37,13 @@
 #define OP_CALL 0xE8
 #define OP_JMP 0xE9
 #define OP_JMP_BYTE 0xEB
-#define OP_CALL_EA 0xFF
+#define OP_SINGLE_EA 0xFF
 
 #define OP2_JCC 0x80
 #define OP2_SETCC 0x90
 #define OP2_BT 0xA3
 #define OP2_BTX_I 0xBA
+#define OP2_MOVSX 0xBE
 
 #define OP_EX_ADDI 0x0
 #define OP_EX_ORI  0x1
@@ -66,6 +68,12 @@
 #define OP_EX_BTR 0x6
 #define OP_EX_BTC 0x7
 
+#define OP_EX_INC     0x0
+#define OP_EX_DEC     0x1
+#define OP_EX_CALL_EA 0x2
+#define OP_EX_JMP_EA  0x4
+#define OP_EX_PUSH_EA 0x6
+
 #define BIT_IMMED_RAX 0x4
 #define BIT_DIR 0x2
 #define BIT_SIZE 0x1
@@ -863,6 +871,67 @@
 	return out;
 }
 
+uint8_t * movsx_rr(uint8_t * out, uint8_t src, uint8_t dst, uint8_t src_size, uint8_t size)
+{
+	if (size == SZ_W) {
+		*(out++) = PRE_SIZE;
+	}
+	if (size == SZ_Q || dst >= R8 || src >= 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++;
+	}
+	if (src_size == SZ_D) {
+		*(out++) = OP_MOVSXD;
+	} else {
+		*(out++) = PRE_2BYTE;
+		*(out++) = OP2_MOVSX | (src_size == SZ_B ? 0 : BIT_SIZE);
+	}
+	*(out++) = MODE_REG_DIRECT | src | (dst << 3);
+	return out;
+}
+
+uint8_t * movsx_rdisp8r(uint8_t * out, uint8_t src, int8_t disp, uint8_t dst, uint8_t src_size, uint8_t size)
+{
+	if (size == SZ_W) {
+		*(out++) = PRE_SIZE;
+	}
+	if (size == SZ_Q || dst >= R8 || src >= 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++;
+	}
+	if (src_size == SZ_D) {
+		*(out++) = OP_MOVSXD;
+	} else {
+		*(out++) = PRE_2BYTE;
+		*(out++) = OP2_MOVSX | (src_size == SZ_B ? 0 : BIT_SIZE);
+	}
+	*(out++) = MODE_REG_DISPLACE8 | src | (dst << 3);
+	*(out++) = disp;
+	return out;
+}
+
 uint8_t * pushf(uint8_t * out)
 {
 	*(out++) = OP_PUSHF;
@@ -1074,6 +1143,12 @@
 	return out;
 }
 
+uint8_t * jmp_r(uint8_t * out, uint8_t dst)
+{
+	*(out++) = OP_SINGLE_EA;
+	*(out++) = MODE_REG_DIRECT | dst | (OP_EX_JMP_EA << 3);
+}
+
 uint8_t * call(uint8_t * out, uint8_t * fun)
 {
 	ptrdiff_t disp = fun-(out+5);
@@ -1094,6 +1169,12 @@
 	return out;
 }
 
+uint8_t * call_r(uint8_t * out, uint8_t dst)
+{
+	*(out++) = OP_SINGLE_EA;
+	*(out++) = MODE_REG_DIRECT | dst | (OP_EX_CALL_EA << 3);
+}
+
 uint8_t * retn(uint8_t * out)
 {
 	*(out++) = OP_RETN;