changeset 691:74d636e85bf8

WIP of functions to determine size of x86 instruction to allow patching of arbitrary pieces of code
author Michael Pavone <pavone@retrodev.com>
date Sat, 14 Mar 2015 12:05:03 -0700
parents fc04781f4d28
children e11e68918691
files gen_x86.c
diffstat 1 files changed, 75 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/gen_x86.c	Wed Jan 14 09:38:54 2015 -0800
+++ b/gen_x86.c	Sat Mar 14 12:05:03 2015 -0700
@@ -2069,3 +2069,78 @@
 	pop_r(code, RBP);
 	pop_r(code, RBX);
 }
+
+uint8_t has_modrm(uint8_t prefix, uint8_t opcode)
+{
+	if (!prefix) {
+		switch (opcode)
+		{
+		case OP_JMP:
+		case OP_JMP_BYTE:
+		case OP_JCC:
+		case OP_CALL:
+		case OP_RETN:
+		case OP_LOOP:
+		case OP_MOV_I8R:
+		case OP_MOV_IR:
+		case OP_PUSHF:
+		case OP_POPF:
+		case OP_PUSH:
+		case OP_POP:
+		case OP_CDQ:
+			return 0;
+		}
+	} else if (prefix == PRE_2BYTE) {
+		switch (opcode)
+		{
+		case OP2_JCC:
+			return 0;
+		}
+	}
+	return 1;
+}
+
+uint8_t has_sib(uint8_t mod_rm)
+{
+	uint8_t mode = mod_rm & 0xC0;
+	uint8_t rm = mod_rm & 3;
+
+	return mode != MODE_REG_DIRECT && rm == RSP;
+}
+
+uint32_t x86_inst_size(code_ptr start)
+{
+	code_ptr code = start;
+	uint8_t cont = 1;
+	uint8_t prefix = 0;
+	uint8_t op_size = SZ_B;
+	uint8_t main_op;
+
+	while (cont)
+	{
+		if (*code == PRE_SIZE) {
+			op_size = SZ_W;
+		} else if (*code == PRE_REX) {
+			if (*code & REX_QUAD) {
+				op_size = SZ_Q;
+			}
+		} else if(*code == PRE_2BYTE || PRE_XOP) {
+			prefix = *code;
+		} else {
+			main_op = *code;
+			cont = 0;
+		}
+		code++;
+	}
+	if (has_modrm(prefix, main_op)) {
+		uint8_t mod_rm = *(code++);
+		if (has_sib(mod_rm)) {
+			uint8_t sib = *(code++);
+		} else {
+
+		}
+	} else {
+	}
+
+	return code-start;
+}