#define MODRM_MOD(x) ((x >> 6) & 0x3)
#define MODRM_REG(x) ((x >> 3) & 0x7)
-#define MODRM_RM(x) (x & 0x07)
+#define MODRM_RM(x) (x & 0x7)
struct modrm_byte {
uint_t rm : 3 PACKED;
};
+#define SIB_BASE(x) ((x >> 6) & 0x3)
+#define SIB_INDEX(x) ((x >> 3) & 0x7)
+#define SIB_SCALE(x) (x & 0x7)
+
struct sib_byte {
uint_t base : 3 PACKED;
uint_t index : 3 PACKED;
}
}
-typedef enum {INVALID_ADDR_TYPE, REG, DISP0, DISP8, DISP16, DISP32} modrm_addr_type_t;
+typedef enum {INVALID_ADDR_TYPE, REG, DISP0, DISP8, DISP16, DISP32} modrm_mode_t;
typedef enum {INVALID_REG_SIZE, REG64, REG32, REG16, REG8} reg_size_t;
-typedef enum {INVALID_OPERAND_TYPE, REG_TO_REG, REG_TO_MEM, MEM_TO_REG} operand_type_t;
+typedef enum {INVALID_OPERAND, REG_OPERAND, MEM_OPERAND} operand_type_t;
struct guest_gprs;
+static inline addr_t decode_register(struct guest_gprs * gprs, char reg_code, reg_size_t reg_size) {
+ addr_t reg_addr;
-static inline int decode_operands16(struct guest_gprs * gprs,
- char * modrm_instr,
- addr_t * first_operand,
- addr_t * second_operand,
- reg_size_t reg_size) {
+ switch (reg_code) {
+ case 0:
+ reg_addr = (addr_t)&(gprs->rax);
+ break;
+ case 1:
+ reg_addr = (addr_t)&(gprs->rcx);
+ break;
+ case 2:
+ reg_addr = (addr_t)&(gprs->rdx);
+ break;
+ case 3:
+ reg_addr = (addr_t)&(gprs->rbx);
+ break;
+ case 4:
+ if (reg_size == REG8) {
+ reg_addr = (addr_t)&(gprs->rax) + 1;
+ } else {
+ reg_addr = (addr_t)&(gprs->rsp);
+ }
+ break;
+ case 5:
+ if (reg_size == REG8) {
+ reg_addr = (addr_t)&(gprs->rcx) + 1;
+ } else {
+ reg_addr = (addr_t)&(gprs->rbp);
+ }
+ break;
+ case 6:
+ if (reg_size == REG8) {
+ reg_addr = (addr_t)&(gprs->rdx) + 1;
+ } else {
+ reg_addr = (addr_t)&(gprs->rsi);
+ }
+ break;
+ case 7:
+ if (reg_size == REG8) {
+ reg_addr = (addr_t)&(gprs->rbx) + 1;
+ } else {
+ reg_addr = (addr_t)&(gprs->rdi);
+ }
+ break;
+ default:
+ reg_addr = 0;
+ break;
+ }
+
+ return reg_addr;
+}
+
+
+
+static inline operand_type_t decode_operands16(struct guest_gprs * gprs,
+ char * modrm_instr,
+ addr_t * first_operand,
+ addr_t * second_operand,
+ reg_size_t reg_size) {
- struct modrm_byte * modrm = (struct modrm_byte*)modrm_instr;
+ struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
addr_t base_addr = 0;
- modrm_addr_type_t mod_type = 0;
+ modrm_mode_t mod_mode = 0;
+ operand_type_t addr_type = INVALID_OPERAND;
PrintDebug("ModRM mod=%d\n", modrm->mod);
if (modrm->mod == 3) {
- mod_type = REG;
-
+ mod_mode = REG;
+ addr_type = REG_OPERAND;
PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
- switch (modrm->rm) {
- case 0:
- PrintDebug("EAX Operand\n");
- *first_operand = (addr_t)&(gprs->rax);
- break;
- case 1:
- *first_operand = (addr_t)&(gprs->rcx);
- break;
- case 2:
- *first_operand = (addr_t)&(gprs->rdx);
- break;
- case 3:
- *first_operand = (addr_t)&(gprs->rbx);
- break;
- case 4:
- if (reg_size == REG8) {
- *first_operand = (addr_t)(&(gprs->rax) + 1);
- } else {
- *first_operand = (addr_t)&(gprs->rsp);
- }
- break;
- case 5:
- if (reg_size == REG8) {
- *first_operand = (addr_t)(&(gprs->rcx) + 1);
- } else {
- *first_operand = (addr_t)&(gprs->rbp);
- }
- break;
- case 6:
- if (reg_size == REG8) {
- *first_operand = (addr_t)(&(gprs->rdx) + 1);
- } else {
- *first_operand = (addr_t)&(gprs->rsi);
- }
- break;
- case 7:
- if (reg_size == REG8) {
- *first_operand = (addr_t)(&(gprs->rbx) + 1);
- } else {
- *first_operand = (addr_t)&(gprs->rdi);
- }
- break;
- }
+ *first_operand = decode_register(gprs, modrm->rm, reg_size);
} else {
+
+ addr_type = MEM_OPERAND;
+
if (modrm->mod == 0) {
- mod_type = DISP0;
+ mod_mode = DISP0;
} else if (modrm->mod == 1) {
- mod_type = DISP8;
+ mod_mode = DISP8;
} else if (modrm->mod == 2) {
- mod_type = DISP16;
+ mod_mode = DISP16;
}
switch (modrm->rm) {
case 0:
base_addr = gprs->rbx + gprs->rsi;
+ break;
case 1:
base_addr = gprs->rbx + gprs->rdi;
+ break;
case 2:
base_addr = gprs->rbp + gprs->rsi;
+ break;
case 3:
base_addr = gprs->rbp + gprs->rdi;
+ break;
case 4:
base_addr = gprs->rsi;
+ break;
case 5:
base_addr = gprs->rdi;
+ break;
case 6:
if (modrm->mod == 0) {
base_addr = 0;
- mod_type = DISP16;
+ mod_mode = DISP16;
} else {
base_addr = gprs->rbp;
}
+ break;
case 7:
base_addr = gprs->rbx;
+ break;
}
- if (mod_type == DISP8) {
+ if (mod_mode == DISP8) {
base_addr += (uchar_t)*(modrm_instr + 1);
- } else if (mod_type == DISP16) {
+ } else if (mod_mode == DISP16) {
base_addr += (ushort_t)*(modrm_instr + 1);
}
-
*first_operand = base_addr;
}
+ *second_operand = decode_register(gprs, modrm->reg, reg_size);
+
+ return addr_type;
+}
+
- switch (modrm->reg) {
+static inline operand_type_t decode_operands32(struct guest_gprs * gprs,
+ char * modrm_instr,
+ addr_t * first_operand,
+ addr_t * second_operand,
+ reg_size_t reg_size) {
+
+ char * instr_cursor = modrm_instr;
+ struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
+ addr_t base_addr = 0;
+ modrm_mode_t mod_mode = 0;
+ uint_t has_sib_byte = 0;
+ operand_type_t addr_type = INVALID_OPERAND;
+
+ if (modrm->mod == 3) {
+ mod_mode = REG;
+ addr_type = REG_OPERAND;
+
+ PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
+
+ *first_operand = decode_register(gprs, modrm->rm, reg_size);
+
+ } else {
+
+ addr_type = MEM_OPERAND;
+
+ if (modrm->mod == 0) {
+ mod_mode = DISP0;
+ } else if (modrm->mod == 1) {
+ mod_mode = DISP8;
+ } else if (modrm->mod == 2) {
+ mod_mode = DISP32;
+ }
+
+ switch (modrm->rm) {
case 0:
- *second_operand = (addr_t)&(gprs->rax);
+ base_addr = gprs->rax;
break;
case 1:
- *second_operand = (addr_t)&(gprs->rcx);
+ base_addr = gprs->rcx;
break;
case 2:
- *second_operand = (addr_t)&(gprs->rdx);
+ base_addr = gprs->rdx;
break;
case 3:
- *second_operand = (addr_t)&(gprs->rbx);
+ base_addr = gprs->rbx;
break;
case 4:
- if (reg_size == REG8) {
- *second_operand = (addr_t)&(gprs->rax) + 1;
- } else {
- *second_operand = (addr_t)&(gprs->rsp);
- }
+ has_sib_byte = 1;
break;
case 5:
- if (reg_size == REG8) {
- *second_operand = (addr_t)&(gprs->rcx) + 1;
+ if (modrm->mod == 0) {
+ base_addr = 0;
+ mod_mode = DISP32;
} else {
- *second_operand = (addr_t)&(gprs->rbp);
+ base_addr = gprs->rbp;
}
break;
case 6:
- if (reg_size == REG8) {
- *second_operand = (addr_t)&(gprs->rdx) + 1;
- } else {
- *second_operand = (addr_t)&(gprs->rsi);
- }
+ base_addr = gprs->rsi;
break;
case 7:
- if (reg_size == REG8) {
- *second_operand = (addr_t)&(gprs->rbx) + 1;
- } else {
- *second_operand = (addr_t)&(gprs->rdi);
- }
+ base_addr = gprs->rdi;
break;
+ }
+
+ if (has_sib_byte) {
+ instr_cursor += 1;
+ struct sib_byte * sib = (struct sib_byte *)(instr_cursor);
+ int scale = 1;
+
+
+ if (sib->scale == 1) {
+ scale = 2;
+ } else if (sib->scale == 2) {
+ scale = 4;
+ } else if (sib->scale == 3) {
+ scale = 8;
+ }
+
+
+ switch (sib->index) {
+ case 0:
+ base_addr = gprs->rax;
+ break;
+ case 1:
+ base_addr = gprs->rcx;
+ break;
+ case 2:
+ base_addr = gprs->rdx;
+ break;
+ case 3:
+ base_addr = gprs->rbx;
+ break;
+ case 4:
+ base_addr = 0;
+ break;
+ case 5:
+ base_addr = gprs->rbp;
+ break;
+ case 6:
+ base_addr = gprs->rsi;
+ break;
+ case 7:
+ base_addr = gprs->rdi;
+ break;
+ }
+
+ base_addr *= scale;
+
+
+ switch (sib->base) {
+ case 0:
+ base_addr += gprs->rax;
+ break;
+ case 1:
+ base_addr += gprs->rcx;
+ break;
+ case 2:
+ base_addr += gprs->rdx;
+ break;
+ case 3:
+ base_addr += gprs->rbx;
+ break;
+ case 4:
+ base_addr += gprs->rsp;
+ break;
+ case 5:
+ if (modrm->mod != 0) {
+ base_addr += gprs->rbp;
+ }
+ break;
+ case 6:
+ base_addr += gprs->rsi;
+ break;
+ case 7:
+ base_addr += gprs->rdi;
+ break;
+ }
+
+ }
+
+ instr_cursor += 1;
+
+ if (mod_mode == DISP8) {
+ base_addr += (uchar_t)*(instr_cursor);
+ } else if (mod_mode == DISP32) {
+ base_addr += (uint_t)*(instr_cursor);
+ }
+
+
+ *first_operand = base_addr;
}
- return 0;
+ *second_operand = decode_register(gprs, modrm->reg, reg_size);
+ return addr_type;
}
-
#endif