MAKE_INSTR(SMSW, 3, 0x0f, 0x01, 0x00);
+static const uchar_t PREFIX_LOCK = 0xF0;
+static const uchar_t PREFIX_REPNE = 0xF2;
+static const uchar_t PREFIX_REPNZ = 0xF2;
+static const uchar_t PREFIX_REP = 0xF3;
+static const uchar_t PREFIX_REPE = 0xF3;
+static const uchar_t PREFIX_REPZ = 0xF3;
+static const uchar_t PREFIX_CS_OVERRIDE = 0x2E;
+static const uchar_t PREFIX_SS_OVERRIDE = 0x36;
+static const uchar_t PREFIX_DS_OVERRIDE = 0x3E;
+static const uchar_t PREFIX_ES_OVERRIDE = 0x26;
+static const uchar_t PREFIX_FS_OVERRIDE = 0x64;
+static const uchar_t PREFIX_GS_OVERRIDE = 0x65;
+static const uchar_t PREFIX_BR_NOT_TAKEN = 0x2E;
+static const uchar_t PREFIX_BR_TAKEN = 0x3E;
+static const uchar_t PREFIX_OP_SIZE = 0x66;
+static const uchar_t PREFIX_ADDR_SIZE = 0x67;
+
static inline int is_prefix_byte(char byte) {
switch (byte) {
}
}
+
+
+static inline addr_t get_addr_linear(struct guest_info * info, addr_t addr, addr_t seg_base) {
+ switch (info->cpu_mode) {
+ case REAL:
+ return addr + (seg_base << 4);
+ break;
+ case PROTECTED:
+ case PROTECTED_PG:
+ return addr + seg_base;
+ break;
+ default:
+ return 0;
+ }
+}
+
+
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, REG_OPERAND, MEM_OPERAND} operand_type_t;
-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) {
+static inline operand_type_t decode_operands16(struct guest_gprs * gprs, // input/output
+ char * modrm_instr, // input
+ int * offset, // output
+ addr_t * first_operand, // output
+ addr_t * second_operand, // output
+ reg_size_t reg_size) { // input
struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
addr_t base_addr = 0;
modrm_mode_t mod_mode = 0;
operand_type_t addr_type = INVALID_OPERAND;
+ char * instr_cursor = modrm_instr;
PrintDebug("ModRM mod=%d\n", modrm->mod);
+ instr_cursor += 1;
+
if (modrm->mod == 3) {
mod_mode = REG;
addr_type = REG_OPERAND;
break;
}
+
+
if (mod_mode == DISP8) {
- base_addr += (uchar_t)*(modrm_instr + 1);
+ base_addr += (uchar_t)*(instr_cursor);
+ instr_cursor += 1;
} else if (mod_mode == DISP16) {
- base_addr += (ushort_t)*(modrm_instr + 1);
+ base_addr += (ushort_t)*(instr_cursor);
+ instr_cursor += 2;
}
*first_operand = base_addr;
}
+ *offset += (instr_cursor - modrm_instr);
*second_operand = decode_register(gprs, modrm->reg, reg_size);
return addr_type;
-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) {
-
+static inline operand_type_t decode_operands32(struct guest_gprs * gprs, // input/output
+ char * modrm_instr, // input
+ int * offset, // output
+ addr_t * first_operand, // output
+ addr_t * second_operand, // output
+ reg_size_t reg_size) { // input
+
char * instr_cursor = modrm_instr;
struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
addr_t base_addr = 0;
uint_t has_sib_byte = 0;
operand_type_t addr_type = INVALID_OPERAND;
+
+
+ instr_cursor += 1;
+
if (modrm->mod == 3) {
mod_mode = REG;
addr_type = REG_OPERAND;
struct sib_byte * sib = (struct sib_byte *)(instr_cursor);
int scale = 1;
+ instr_cursor += 1;
+
if (sib->scale == 1) {
scale = 2;
}
- instr_cursor += 1;
if (mod_mode == DISP8) {
base_addr += (uchar_t)*(instr_cursor);
+ instr_cursor += 1;
} else if (mod_mode == DISP32) {
base_addr += (uint_t)*(instr_cursor);
+ instr_cursor += 4;
}
*first_operand = base_addr;
}
+ *offset += (instr_cursor - modrm_instr);
+
*second_operand = decode_register(gprs, modrm->reg, reg_size);
return addr_type;