From: Jack Lange Date: Sun, 6 Mar 2011 01:11:15 +0000 (-0600) Subject: decoder updates X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=847838d7621455a02df5d657914d7da163718234;p=palacios.git decoder updates --- diff --git a/palacios/include/palacios/vmm_decoder.h b/palacios/include/palacios/vmm_decoder.h index 81cf0b0..41817f7 100644 --- a/palacios/include/palacios/vmm_decoder.h +++ b/palacios/include/palacios/vmm_decoder.h @@ -62,7 +62,7 @@ struct x86_prefixes { uint_t br_taken : 1; // 0x3E uint_t op_size : 1; // 0x66 uint_t addr_size : 1; // 0x67 -}; +} __attribute__((packed)); struct x86_instr { @@ -110,13 +110,13 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins * any unused bytes at the end of instr_buf will be filled with nops * IMPORTANT: instr_buf must be allocated and 15 bytes long */ -int v3_encode(struct guest_info * info, struct x86_instr * instr, char * instr_buf); +int v3_encode(struct guest_info * info, struct x86_instr * instr, uint8_t * instr_buf); /* Removes a rep prefix in place */ -void v3_strip_rep_prefix(uchar_t * instr, int length); -void v3_get_prefixes(uchar_t * instr, struct x86_prefixes * prefixes); +void v3_strip_rep_prefix(uint8_t * instr, int length); +uint8_t v3_get_prefixes(uint8_t * instr, struct x86_prefixes * prefixes); diff --git a/palacios/include/palacios/vmm_instr_decoder.h b/palacios/include/palacios/vmm_instr_decoder.h new file mode 100644 index 0000000..b9dc7fd --- /dev/null +++ b/palacios/include/palacios/vmm_instr_decoder.h @@ -0,0 +1,983 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2008, Jack Lange + * Copyright (c) 2008, The V3VEE Project + * All rights reserved. + * + * Author: Jack Lange + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + +#include + + +/* .... Giant fucking switch tables */ + + + + + + + +typedef enum { + INVALID_INSTR, + LMSW, + SMSW, + CLTS, + INVLPG, + + MOV_CR2, + MOV_2CR, + MOV_DR2, + MOV_2DR, + MOV_SR2, + MOV_2SR, + + MOV_MEM2_8, + MOV_MEM2, + MOV_2MEM_8, + MOV_2MEM, + MOV_MEM2AL_8, + MOV_MEM2AX, + MOV_AL2MEM_8, + MOV_AX2MEM, + MOV_IMM2_8, + MOV_IMM2, + + MOVS_8, + MOVS, + MOVSX_8, + MOVSX, + MOVZX_8, + MOVZX, + + HLT, + PUSHF, + POPF, + + ADC_2MEM_8, + ADC_2MEM, + ADC_MEM2_8, + ADC_MEM2, + ADC_IMM2_8, + ADC_IMM2, + ADC_IMM2SX_8, + ADD_IMM2_8, + ADD_IMM2, + ADD_IMM2SX_8, + ADD_2MEM_8, + ADD_2MEM, + ADD_MEM2_8, + ADD_MEM2, + AND_MEM2_8, + AND_MEM2, + AND_2MEM_8, + AND_2MEM, + AND_IMM2_8, + AND_IMM2, + AND_IMM2SX_8, + OR_2MEM_8, + OR_2MEM, + OR_MEM2_8, + OR_MEM2, + OR_IMM2_8, + OR_IMM2, + OR_IMM2SX_8, + SUB_2MEM_8, + SUB_2MEM, + SUB_MEM2_8, + SUB_MEM2, + SUB_IMM2_8, + SUB_IMM2, + SUB_IMM2SX_8, + XOR_2MEM_8, + XOR_2MEM, + XOR_MEM2_8, + XOR_MEM2, + XOR_IMM2_8, + XOR_IMM2, + XOR_IMM2SX_8, + + INC_8, + INC, + DEC_8, + DEC, + NEG_8, + NEG, + NOT_8, + NOT, + XCHG_8, + XCHG, + + SETB, + SETBE, + SETL, + SETLE, + SETNB, + SETNBE, + SETNL, + SETNLE, + SETNO, + SETNP, + SETNS, + SETNZ, + SETP, + SETS, + SETZ, + SETO, + + STOS_8, + STOS +} op_form_t; + + + + +static int get_operand_width(struct guest_info * info, struct x86_instr * instr, op_form_t form) { + switch (form) { + + case CLTS: + case HLT: + return 0; + + + case MOV_MEM2_8: + case MOV_2MEM_8: + case MOV_MEM2AL_8: + case MOV_AL2MEM_8: + case MOV_IMM2_8: + case MOVS_8: + case MOVSX_8: + case MOVZX_8: + case ADC_2MEM_8: + case ADC_MEM2_8: + case ADC_IMM2_8: + case ADD_IMM2_8: + case ADD_2MEM_8: + case ADD_MEM2_8: + case AND_MEM2_8: + case AND_2MEM_8: + case AND_IMM2_8: + case OR_2MEM_8: + case OR_MEM2_8: + case OR_IMM2_8: + case SUB_2MEM_8: + case XOR_2MEM_8: + case SUB_MEM2_8: + case SUB_IMM2_8: + case XOR_MEM2_8: + case XOR_IMM2_8: + case INC_8: + case DEC_8: + case NEG_8: + case NOT_8: + case XCHG_8: + case STOS_8: + case SETB: + case SETBE: + case SETL: + case SETLE: + case SETNB: + case SETNBE: + case SETNL: + case SETNLE: + case SETNO: + case SETNP: + case SETNS: + case SETNZ: + case SETP: + case SETS: + case SETZ: + case SETO: + return 1; + + + case LMSW: + case SMSW: + return 2; + + case MOV_MEM2: + case MOV_2MEM: + case MOV_MEM2AX: + case MOV_AX2MEM: + case MOV_IMM2: + case MOVS: + case MOVSX: + case MOVZX: + case ADC_2MEM: + case ADC_MEM2: + case ADC_IMM2: + case ADD_IMM2: + case ADD_2MEM: + case ADD_MEM2: + case AND_MEM2: + case AND_2MEM: + case AND_IMM2: + case OR_2MEM: + case OR_MEM2: + case OR_IMM2: + case SUB_2MEM: + case SUB_MEM2: + case SUB_IMM2: + case XOR_2MEM: + case XOR_MEM2: + case XOR_IMM2: + case INC: + case DEC: + case NEG: + case NOT: + case STOS: + case XCHG: + case ADC_IMM2SX_8: + case AND_IMM2SX_8: + case ADD_IMM2SX_8: + case OR_IMM2SX_8: + case SUB_IMM2SX_8: + case XOR_IMM2SX_8: + switch (v3_get_vm_cpu_mode(info)) { + case REAL: + return (instr->prefixes.op_size) ? 4 : 2; + case PROTECTED: + case PROTECTED_PAE: + return (instr->prefixes.op_size) ? 2 : 4; + case LONG_32_COMPAT: + case LONG: + default: + PrintError("Unsupported CPU mode: %d\n", info->cpu_mode); + return -1; + } + + + case INVLPG: + switch (v3_get_vm_cpu_mode(info)) { + case REAL: + PrintError("Invalid instruction given operating mode (%d)\n", form); + return 0; + case PROTECTED: + case PROTECTED_PAE: + return 4; + case LONG_32_COMPAT: + case LONG: + default: + PrintError("Unsupported CPU mode: %d\n", info->cpu_mode); + return -1; + } + + + case PUSHF: + case POPF: + switch (v3_get_vm_cpu_mode(info)) { + case REAL: + return 2; + case PROTECTED: + case PROTECTED_PAE: + return 4; + case LONG_32_COMPAT: + case LONG: + default: + PrintError("Unsupported CPU mode: %d\n", info->cpu_mode); + return -1; + } + + case MOV_DR2: + case MOV_2DR: + case MOV_CR2: + case MOV_2CR: + switch (v3_get_vm_cpu_mode(info)) { + case REAL: + case PROTECTED: + case PROTECTED_PAE: + return 4; + case LONG_32_COMPAT: + case LONG: + default: + PrintError("Unsupported CPU mode: %d\n", info->cpu_mode); + return -1; + } + + + case MOV_SR2: + case MOV_2SR: + default: + PrintError("Unsupported instruction form %d\n", form); + return -1; + + } + 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; + + +struct modrm_byte { + uint_t rm : 3; + uint_t reg : 3; + uint_t mod : 2; +} __attribute__((packed)); + + +struct sib_byte { + uint_t base : 3; + uint_t index : 3; + uint_t scale : 2; +} __attribute__((packed)); + + + + +struct v3_gprs; + +static inline int decode_gpr(struct v3_gprs * gprs, + uint8_t reg_code, + struct x86_operand * reg) { + + switch (reg_code) { + case 0: + reg->operand = (addr_t)&(gprs->rax); + break; + case 1: + reg->operand = (addr_t)&(gprs->rcx); + break; + case 2: + reg->operand = (addr_t)&(gprs->rdx); + break; + case 3: + reg->operand = (addr_t)&(gprs->rbx); + break; + case 4: + if (reg->size == 1) { + reg->operand = (addr_t)&(gprs->rax) + 1; + } else { + reg->operand = (addr_t)&(gprs->rsp); + } + break; + case 5: + if (reg->size == 1) { + reg->operand = (addr_t)&(gprs->rcx) + 1; + } else { + reg->operand = (addr_t)&(gprs->rbp); + } + break; + case 6: + if (reg->size == 1) { + reg->operand = (addr_t)&(gprs->rdx) + 1; + } else { + reg->operand = (addr_t)&(gprs->rsi); + } + break; + case 7: + if (reg->size == 1) { + reg->operand = (addr_t)&(gprs->rbx) + 1; + } else { + reg->operand = (addr_t)&(gprs->rdi); + } + break; + default: + reg->operand = 0; + break; + } + + return 0; +} + + +// This converts the displacement into the appropriate masked value +/* + QUESTION: Are the register Values signed ????? + */ +#define MASK_DISPLACEMENT(reg, mode) ({ \ + sint64_t val = 0; \ + if (mode == DISP8) { \ + val = (sint8_t)(reg & 0xff); \ + } else if (mode == DISP16) { \ + val = (sint16_t)(reg & 0xffff); \ + } else if (mode == DISP32) { \ + val = (sint32_t)(reg & 0xffffffff); \ + } else { \ + PrintError("Error invalid displacement size (%d)\n", mode); \ + V3_ASSERT(0); \ + } \ + val; \ + }) + +static int decode_rm_operand16(struct v3_gprs * gprs, + char * modrm_instr, + struct x86_operand * operand, + uint8_t * reg_code) { + + + struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr; + addr_t base_addr = 0; + modrm_mode_t mod_mode = 0; + char * instr_cursor = modrm_instr; + + // PrintDebug("ModRM mod=%d\n", modrm->mod); + + *reg_code = modrm->reg; + + instr_cursor += 1; + + if (modrm->mod == 3) { + //PrintDebug("first operand = Register (RM=%d)\n",modrm->rm); + operand->type = REG_OPERAND; + + decode_gpr(gprs, modrm->rm, operand); + + } else { + + operand->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 = DISP16; + } + + switch (modrm->rm) { + case 0: + base_addr = gprs->rbx + MASK_DISPLACEMENT(gprs->rsi, mod_mode); + break; + case 1: + base_addr = gprs->rbx + MASK_DISPLACEMENT(gprs->rdi, mod_mode); + break; + case 2: + base_addr = gprs->rbp + MASK_DISPLACEMENT(gprs->rsi, mod_mode); + break; + case 3: + base_addr = gprs->rbp + MASK_DISPLACEMENT(gprs->rdi, mod_mode); + 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_mode = DISP16; + } else { + base_addr = gprs->rbp; + } + break; + case 7: + base_addr = gprs->rbx; + break; + } + + + + if (mod_mode == DISP8) { + base_addr += *(sint8_t *)instr_cursor; + instr_cursor += 1; + } else if (mod_mode == DISP16) { + base_addr += *(sint16_t *)instr_cursor; + instr_cursor += 2; + } + + operand->operand = base_addr; + } + + + return (instr_cursor - modrm_instr); +} + + +// returns num_bytes parsed +static int decode_rm_operand32(struct v3_gprs * gprs, // input/output + uint8_t * modrm_instr, // input + struct x86_operand * operand, + uint8_t * reg_code) { + + uchar_t * 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; + + + *reg_code = modrm->reg; + + instr_cursor += 1; + + if (modrm->mod == 3) { + operand->type = REG_OPERAND; + // PrintDebug("first operand = Register (RM=%d)\n",modrm->rm); + + decode_gpr(gprs, modrm->rm, operand); + + } else { + + operand->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: + 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: + has_sib_byte = 1; + break; + case 5: + if (modrm->mod == 0) { + base_addr = 0; + mod_mode = DISP32; + } else { + base_addr = gprs->rbp; + } + break; + case 6: + base_addr = gprs->rsi; + break; + case 7: + base_addr = gprs->rdi; + break; + } + + if (has_sib_byte) { + instr_cursor += 1; + struct sib_byte * sib = (struct sib_byte *)(instr_cursor); + int scale = 0x1 << sib->scale; + + instr_cursor += 1; + + 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 += MASK_DISPLACEMENT(gprs->rax, mod_mode); + break; + case 1: + base_addr += MASK_DISPLACEMENT(gprs->rcx, mod_mode); + break; + case 2: + base_addr += MASK_DISPLACEMENT(gprs->rdx, mod_mode); + break; + case 3: + base_addr += MASK_DISPLACEMENT(gprs->rbx, mod_mode); + break; + case 4: + base_addr += MASK_DISPLACEMENT(gprs->rsp, mod_mode); + break; + case 5: + if (modrm->mod != 0) { + base_addr += MASK_DISPLACEMENT(gprs->rbp, mod_mode); + } + break; + case 6: + base_addr += MASK_DISPLACEMENT(gprs->rsi, mod_mode); + break; + case 7: + base_addr += MASK_DISPLACEMENT(gprs->rdi, mod_mode); + break; + } + + } + + + if (mod_mode == DISP8) { + base_addr += *(sint8_t *)instr_cursor; + instr_cursor += 1; + } else if (mod_mode == DISP32) { + base_addr += *(sint32_t *)instr_cursor; + instr_cursor += 4; + } + + + operand->operand = base_addr; + } + + + return (instr_cursor - modrm_instr); +} + + + + + +static int decode_rm_operand(struct guest_info * core, + uint8_t * instr_ptr, // input + struct x86_operand * operand, + uint8_t * reg_code) { + + v3_cpu_mode_t mode = v3_get_vm_cpu_mode(core); + + if (mode == REAL) { + return decode_rm_operand16(&(core->vm_regs), instr_ptr, operand, reg_code); + } else if ((mode == PROTECTED) || (mode == PROTECTED_PAE)) { + return decode_rm_operand32(&(core->vm_regs), instr_ptr, operand, reg_code); + } else { + PrintError("Invalid CPU_MODE (%d)\n", mode); + return -1; + } +} + + + +static inline op_form_t op_code_to_form_0f(uint8_t * instr) { + switch (instr[1]) { + case 0x01: { + struct modrm_byte * modrm = (struct modrm_byte *)&(instr[2]); + + switch (modrm->reg) { + case 4: + return SMSW; + case 6: + return LMSW; + case 7: + return INVLPG; + default: + return INVALID_INSTR; + } + } + + case 0x06: + return CLTS; + case 0x20: + return MOV_CR2; + case 0x21: + return MOV_DR2; + + case 0x22: + return MOV_2CR; + case 0x23: + return MOV_2DR; + + case 0x90: + return SETO; + case 0x91: + return SETNO; + case 0x92: + return SETB; + case 0x93: + return SETNB; + case 0x94: + return SETZ; + case 0x95: + return SETNZ; + case 0x96: + return SETBE; + case 0x97: + return SETNBE; + case 0x98: + return SETS; + case 0x99: + return SETNS; + case 0x9a: + return SETP; + case 0x9b: + return SETNP; + case 0x9c: + return SETL; + case 0x9d: + return SETNL; + case 0x9e: + return SETLE; + case 0x9f: + return SETNLE; + + case 0xb6: + return MOVZX_8; + case 0xb7: + return MOVZX; + + case 0xbe: + return MOVSX_8; + case 0xbf: + return MOVSX; + + + default: + return INVALID_INSTR; + } +} + + +static op_form_t op_code_to_form(uint8_t * instr) { + switch (instr[0]) { + case 0x00: + return ADD_2MEM_8; + case 0x01: + return ADD_2MEM; + case 0x02: + return ADD_MEM2_8; + case 0x03: + return ADD_MEM2; + + case 0x08: + return OR_2MEM_8; + case 0x09: + return OR_2MEM; + case 0x0a: + return OR_MEM2_8; + case 0x0b: + return OR_MEM2; + + + case 0x0f: + return op_code_to_form_0f(instr); + + case 0x10: + return ADC_2MEM_8; + case 0x11: + return ADC_2MEM; + case 0x12: + return ADC_MEM2_8; + case 0x13: + return ADC_MEM2; + + case 0x20: + return AND_2MEM_8; + case 0x21: + return AND_2MEM; + case 0x22: + return AND_MEM2_8; + case 0x23: + return AND_MEM2; + + case 0x28: + return SUB_2MEM_8; + case 0x29: + return SUB_2MEM; + case 0x2a: + return SUB_MEM2_8; + case 0x2b: + return SUB_MEM2; + + + case 0x30: + return XOR_2MEM_8; + case 0x31: + return XOR_2MEM; + case 0x32: + return XOR_MEM2_8; + case 0x33: + return XOR_MEM2; + + case 0x80:{ + struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]); + + switch (modrm->reg) { + case 0: + return ADD_IMM2_8; + case 1: + return OR_IMM2_8; + case 2: + return ADC_IMM2_8; + case 4: + return AND_IMM2_8; + case 5: + return SUB_IMM2_8; + case 6: + return XOR_IMM2_8; + default: + return INVALID_INSTR; + } + } + case 0x81: { + struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]); + + switch (modrm->reg) { + case 0: + return ADD_IMM2; + case 1: + return OR_IMM2; + case 2: + return ADC_IMM2; + case 4: + return AND_IMM2; + case 5: + return SUB_IMM2; + case 6: + return XOR_IMM2; + default: + return INVALID_INSTR; + } + } + case 0x83: { + struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]); + + switch (modrm->reg) { + case 0: + return ADD_IMM2SX_8; + case 1: + return OR_IMM2SX_8; + case 2: + return ADC_IMM2SX_8; + case 4: + return AND_IMM2SX_8; + case 5: + return SUB_IMM2SX_8; + case 6: + return XOR_IMM2SX_8; + default: + return INVALID_INSTR; + } + } + + case 0x86: + return XCHG_8; + case 0x87: + return XCHG; + case 0x88: + return MOV_2MEM_8; + case 0x89: + return MOV_2MEM; + case 0x8a: + return MOV_MEM2_8; + case 0x8b: + return MOV_MEM2; + + case 0x8c: + return MOV_SR2; + case 0x8e: + return MOV_2SR; + + + case 0x9c: + return PUSHF; + case 0x9d: + return POPF; + + case 0xa0: + return MOV_MEM2AL_8; + case 0xa1: + return MOV_MEM2AX; + case 0xa2: + return MOV_AL2MEM_8; + case 0xa3: + return MOV_AX2MEM; + + case 0xa4: + return MOVS_8; + case 0xa5: + return MOVS; + + case 0xaa: + return STOS_8; + case 0xab: + return STOS; + + case 0xc6: + return MOV_IMM2_8; + case 0xc7: + return MOV_IMM2; + + case 0xf4: + return HLT; + + + case 0xf6: { + struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]); + + switch (modrm->reg) { + case 2: + return NOT_8; + case 3: + return NEG_8; + default: + return INVALID_INSTR; + } + } + case 0xf7: { + struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]); + + switch (modrm->reg) { + case 2: + return NOT; + case 3: + return NEG; + default: + return INVALID_INSTR; + } + } + + + case 0xfe: { + struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]); + + switch (modrm->reg) { + case 0: + return INC_8; + case 1: + return DEC_8; + default: + return INVALID_INSTR; + } + } + + case 0xff: { + struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]); + + switch (modrm->reg) { + case 0: + return INC; + case 1: + return DEC; + default: + return INVALID_INSTR; + } + } + + default: + return INVALID_INSTR; + } +} diff --git a/palacios/src/palacios/vmm.c b/palacios/src/palacios/vmm.c index c5a7eb9..bf338a1 100644 --- a/palacios/src/palacios/vmm.c +++ b/palacios/src/palacios/vmm.c @@ -304,7 +304,6 @@ int v3_start_vm(struct v3_vm_info * vm, unsigned int cpu_mask) { minor = core_idx % 8; - if ((core_mask[major] & (0x1 << minor)) == 0) { PrintError("Logical CPU %d not available for virtual core %d; not started\n", core_idx, vcore_id); diff --git a/palacios/src/palacios/vmm_decoder.c b/palacios/src/palacios/vmm_decoder.c index 1d9e178..676fd6d 100644 --- a/palacios/src/palacios/vmm_decoder.c +++ b/palacios/src/palacios/vmm_decoder.c @@ -24,9 +24,11 @@ -void v3_get_prefixes(uchar_t * instr, struct x86_prefixes * prefixes) { +uint8_t v3_get_prefixes(uint8_t * instr, struct x86_prefixes * prefixes) { + uint8_t * instr_cursor = instr; + while (1) { - switch (*instr) { + switch (*instr_cursor) { case 0xF0: // lock prefixes->lock = 1; break; @@ -42,7 +44,7 @@ void v3_get_prefixes(uchar_t * instr, struct x86_prefixes * prefixes) { prefixes->repz = 1; break; - case 0x2E: // CS override or Branch hint not taken (with Jcc instrs) + case 0x2E: // CS override or Branch hint not taken (with Jcc instr_cursors) prefixes->cs_override = 1; prefixes->br_not_taken = 1; break; @@ -51,7 +53,7 @@ void v3_get_prefixes(uchar_t * instr, struct x86_prefixes * prefixes) { prefixes->ss_override = 1; break; - case 0x3E: // DS override or Branch hint taken (with Jcc instrs) + case 0x3E: // DS override or Branch hint taken (with Jcc instr_cursors) prefixes->ds_override = 1; prefixes->br_taken = 1; break; @@ -77,12 +79,11 @@ void v3_get_prefixes(uchar_t * instr, struct x86_prefixes * prefixes) { break; default: - return; + return (instr_cursor - instr); } - instr++; + instr_cursor++; } - } void v3_strip_rep_prefix(uchar_t * instr, int length) { diff --git a/palacios/src/palacios/vmm_v3dec.c b/palacios/src/palacios/vmm_v3dec.c index 78cb8b6..55f1df2 100644 --- a/palacios/src/palacios/vmm_v3dec.c +++ b/palacios/src/palacios/vmm_v3dec.c @@ -18,802 +18,375 @@ */ #include +#include -/* .... Giant fucking switch tables */ - - - -#define MODRM_MOD(x) (((x) >> 6) & 0x3) -#define MODRM_REG(x) (((x) >> 3) & 0x7) -#define MODRM_RM(x) ((x) & 0x7) - -struct modrm_byte { - uint_t rm : 3; - uint_t reg : 3; - uint_t mod : 2; -} __attribute__((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; - uint_t index : 3; - uint_t scale : 2; -} __attribute__((packed)); - - - - -typedef enum { - INVALID_INSTR, - LMSW, - SMSW, - CLTS, - INVLPG, - - MOV_CR2, - MOV_2CR, - MOV_DR2, - MOV_2DR, - MOV_SR2, - MOV_2SR, - - MOV_2GPR_8, - MOV_2GPR, - MOV_GPR2_8, - MOV_GPR2, - MOV_MEM2AL_8, - MOV_MEM2AX, - MOV_AL2MEM_8, - MOV_AX2MEM, - MOV_IMM2_8, - MOV_IMM2, - - MOVS_8, - MOVS, - MOVSX_8, - MOVSX, - MOVZX_8, - MOVZX, - - HLT, - PUSHF, - POPF, - - ADC_2MEM_8, - ADC_2MEM, - ADC_MEM2_8, - ADC_MEM2, - ADC_IMM2_8, - ADC_IMM2, - ADC_IMM2SX_8, - ADD_IMM2_8, - ADD_IMM2, - ADD_IMM2SX_8, - ADD_2MEM_8, - ADD_2MEM, - ADD_MEM2_8, - ADD_MEM2, - AND_MEM2_8, - AND_MEM2, - AND_2MEM_8, - AND_2MEM, - AND_IMM2_8, - AND_IMM2, - AND_IMM2SX_8, - OR_2MEM_8, - OR_2MEM, - OR_MEM2_8, - OR_MEM2, - OR_IMM2_8, - OR_IMM2, - OR_IMM2SX_8, - SUB_2MEM_8, - SUB_2MEM, - SUB_MEM2_8, - SUB_MEM2, - SUB_IMM2_8, - SUB_IMM2, - SUB_IMM2SX_8, - XOR_2MEM_8, - XOR_2MEM, - XOR_MEM2_8, - XOR_MEM2, - XOR_IMM2_8, - XOR_IMM2, - XOR_IMM2SX_8, - - INC_8, - INC, - DEC_8, - DEC, - NEG_8, - NEG, - NOT_8, - NOT, - XCHG_8, - XCHG, - - SETB, - SETBE, - SETL, - SETLE, - SETNB, - SETNBE, - SETNL, - SETNLE, - SETNO, - SETNP, - SETNS, - SETNZ, - SETP, - SETS, - SETZ, - SETO, - - STOS_8, - STOS -} op_form_t; - -static op_form_t op_code_to_form(uint8_t * instr); - - - -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; - - -struct v3_gprs; - -static inline addr_t decode_register(struct v3_gprs * gprs, char reg_code, reg_size_t reg_size) { - addr_t reg_addr; - - 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 v3_operand_type_t decode_operands16(struct v3_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; - v3_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; - //PrintDebug("first operand = Register (RM=%d)\n",modrm->rm); +static v3_op_type_t op_form_to_type(op_form_t form); +static int parse_operands(struct guest_info * core, uint8_t * instr_ptr, struct x86_instr * instr, op_form_t form); - *first_operand = decode_register(gprs, modrm->rm, reg_size); - } else { +int v3_disasm(struct guest_info * info, void *instr_ptr, addr_t * rip, int mark) { + return 0; +} - 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 = 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_mode = DISP16; - } else { - base_addr = gprs->rbp; - } - break; - case 7: - base_addr = gprs->rbx; - break; - } +int v3_init_decoder(struct guest_info * core) { + return 0; +} - if (mod_mode == DISP8) { - base_addr += (uchar_t)*(instr_cursor); - instr_cursor += 1; - } else if (mod_mode == DISP16) { - base_addr += (ushort_t)*(instr_cursor); - instr_cursor += 2; - } - - *first_operand = base_addr; - } +int v3_deinit_decoder(struct guest_info * core) { + return 0; +} - *offset += (instr_cursor - modrm_instr); - *second_operand = decode_register(gprs, modrm->reg, reg_size); - return addr_type; +int v3_encode(struct guest_info * info, struct x86_instr * instr, uint8_t * instr_buf) { + return 0; } +int v3_decode(struct guest_info * core, addr_t instr_ptr, struct x86_instr * instr) { + op_form_t form; + memset(instr, 0, sizeof(struct x86_instr)); -static inline v3_operand_type_t decode_operands32(struct v3_gprs * gprs, // input/output - uchar_t * modrm_instr, // input - int * offset, // output - addr_t * first_operand, // output - addr_t * second_operand, // output - reg_size_t reg_size) { // input - - uchar_t * 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; - v3_operand_type_t addr_type = INVALID_OPERAND; + // scan for prefixes + instr_ptr += v3_get_prefixes((uint8_t *)instr_ptr, &(instr->prefixes)); + // check for REX prefix - instr_cursor += 1; - if (modrm->mod == 3) { - mod_mode = REG; - addr_type = REG_OPERAND; - - // PrintDebug("first operand = Register (RM=%d)\n",modrm->rm); + form = op_code_to_form((uint8_t *)instr_ptr); + instr->op_type = op_form_to_type(form); - *first_operand = decode_register(gprs, modrm->rm, reg_size); + parse_operands(core, (uint8_t *)instr_ptr, instr, form); - } else { - addr_type = MEM_OPERAND; + return 0; +} - 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: - 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: - has_sib_byte = 1; - break; - case 5: - if (modrm->mod == 0) { - base_addr = 0; - mod_mode = DISP32; - } else { - base_addr = gprs->rbp; - } - break; - case 6: - base_addr = gprs->rsi; - break; - case 7: - base_addr = gprs->rdi; - break; - } - if (has_sib_byte) { - instr_cursor += 1; - struct sib_byte * sib = (struct sib_byte *)(instr_cursor); - int scale = 1; - instr_cursor += 1; - if (sib->scale == 1) { - scale = 2; - } else if (sib->scale == 2) { - scale = 4; - } else if (sib->scale == 3) { - scale = 8; +static int parse_operands(struct guest_info * core, uint8_t * instr_ptr, struct x86_instr * instr, op_form_t form) { + // get operational mode of the guest for operand width + int operand_width = get_operand_width(core, instr, form); + int ret = 0; + + + switch (form) { + + case ADC_IMM2_8: + case ADD_IMM2_8: + case AND_IMM2_8: + case OR_IMM2_8: + case SUB_IMM2_8: + case XOR_IMM2_8: + case MOV_IMM2_8: + case ADC_IMM2: + case ADD_IMM2: + case AND_IMM2: + case OR_IMM2: + case SUB_IMM2: + case XOR_IMM2: + case MOV_IMM2:{ + uint8_t reg_code = 0;; + instr->dst_operand.size = operand_width; + + ret = decode_rm_operand(core, instr_ptr, &(instr->dst_operand), ®_code); + + if (ret == -1) { + PrintError("Error decoding operand\n"); + return -1; } + instr_ptr += ret; - 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; - } + instr->src_operand.type = IMM_OPERAND; + instr->src_operand.size = operand_width; - 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; + if (operand_width == 1) { + instr->src_operand.operand = *(uint8_t *)instr_ptr; + } else if (operand_width == 2) { + instr->src_operand.operand = *(uint16_t *)instr_ptr; + } else if (operand_width == 4) { + instr->src_operand.operand = *(uint32_t *)instr_ptr; + } else { + PrintError("Illegal operand width (%d)\n", operand_width); + return -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; + break; } - - - *first_operand = base_addr; - } + case ADC_2MEM_8: + case ADD_2MEM_8: + case AND_2MEM_8: + case OR_2MEM_8: + case SUB_2MEM_8: + case XOR_2MEM_8: + case MOV_2MEM_8: + case ADC_2MEM: + case ADD_2MEM: + case AND_2MEM: + case OR_2MEM: + case SUB_2MEM: + case XOR_2MEM: + case MOV_2MEM: { + uint8_t reg_code = 0; + + instr->dst_operand.size = operand_width; + + ret = decode_rm_operand(core, instr_ptr, &(instr->dst_operand), ®_code); + + if (ret == -1) { + PrintError("Error decoding operand\n"); + return -1; + } - *offset += (instr_cursor - modrm_instr); + instr_ptr += ret; - *second_operand = decode_register(gprs, modrm->reg, reg_size); + instr->src_operand.type = REG_OPERAND; + instr->src_operand.size = operand_width; - return addr_type; -} + decode_gpr(&(core->vm_regs), reg_code, &(instr->src_operand)); + break; + } + case ADC_MEM2_8: + case ADD_MEM2_8: + case AND_MEM2_8: + case OR_MEM2_8: + case SUB_MEM2_8: + case XOR_MEM2_8: + case MOV_MEM2_8: + case ADC_MEM2: + case ADD_MEM2: + case AND_MEM2: + case OR_MEM2: + case SUB_MEM2: + case XOR_MEM2: + case MOV_MEM2: { + uint8_t reg_code = 0; + instr->src_operand.size = operand_width; + + ret = decode_rm_operand(core, instr_ptr, &(instr->src_operand), ®_code); + + if (ret == -1) { + PrintError("Error decoding operand\n"); + return -1; + } + instr_ptr += ret; -static inline op_form_t op_code_to_form_0f(uint8_t * instr) { - switch (instr[1]) { - case 0x01: { - struct modrm_byte * modrm = (struct modrm_byte *)&(instr[2]); + instr->dst_operand.size = operand_width; + instr->dst_operand.type = REG_OPERAND; + decode_gpr(&(core->vm_regs), reg_code, &(instr->dst_operand)); - switch (modrm->reg) { - case 4: - return SMSW; - case 6: - return LMSW; - case 7: - return INVLPG; - default: - return INVALID_INSTR; - } + break; } - case 0x06: - return CLTS; - case 0x20: - return MOV_CR2; - case 0x21: - return MOV_DR2; - - case 0x22: - return MOV_2CR; - case 0x23: - return MOV_2DR; - - case 0x90: - return SETO; - case 0x91: - return SETNO; - case 0x92: - return SETB; - case 0x93: - return SETNB; - case 0x94: - return SETZ; - case 0x95: - return SETNZ; - case 0x96: - return SETBE; - case 0x97: - return SETNBE; - case 0x98: - return SETS; - case 0x99: - return SETNS; - case 0x9a: - return SETP; - case 0x9b: - return SETNP; - case 0x9c: - return SETL; - case 0x9d: - return SETNL; - case 0x9e: - return SETLE; - case 0x9f: - return SETNLE; - - case 0xb6: - return MOVZX_8; - case 0xb7: - return MOVZX; - - case 0xbe: - return MOVSX_8; - case 0xbf: - return MOVSX; - - default: - return INVALID_INSTR; - } -} + case ADC_IMM2SX_8: + case ADD_IMM2SX_8: + case AND_IMM2SX_8: + case OR_IMM2SX_8: + case SUB_IMM2SX_8: + case XOR_IMM2SX_8: { + uint8_t reg_code = 0; + instr->src_operand.size = operand_width; + ret = decode_rm_operand(core, instr_ptr, &(instr->src_operand), ®_code); -static op_form_t op_code_to_form(uint8_t * instr) { - switch (instr[0]) { - case 0x00: - return ADD_2MEM_8; - case 0x01: - return ADD_2MEM; - case 0x02: - return ADD_MEM2_8; - case 0x03: - return ADD_MEM2; - - case 0x08: - return OR_2MEM_8; - case 0x09: - return OR_2MEM; - case 0x0a: - return OR_MEM2_8; - case 0x0b: - return OR_MEM2; - - - case 0x0f: - return op_code_to_form_0f(instr); - - case 0x10: - return ADC_2MEM_8; - case 0x11: - return ADC_2MEM; - case 0x12: - return ADC_MEM2_8; - case 0x13: - return ADC_MEM2; - - case 0x20: - return AND_2MEM_8; - case 0x21: - return AND_2MEM; - case 0x22: - return AND_MEM2_8; - case 0x23: - return AND_MEM2; - - case 0x28: - return SUB_2MEM_8; - case 0x29: - return SUB_2MEM; - case 0x2a: - return SUB_MEM2_8; - case 0x2b: - return SUB_MEM2; - - - case 0x30: - return XOR_2MEM_8; - case 0x31: - return XOR_2MEM; - case 0x32: - return XOR_MEM2_8; - case 0x33: - return XOR_MEM2; - - case 0x80:{ - struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]); - - switch (modrm->reg) { - case 0: - return ADD_IMM2_8; - case 1: - return OR_IMM2_8; - case 2: - return ADC_IMM2_8; - case 4: - return AND_IMM2_8; - case 5: - return SUB_IMM2_8; - case 6: - return XOR_IMM2_8; - default: - return INVALID_INSTR; - } - } - case 0x81: { - struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]); - - switch (modrm->reg) { - case 0: - return ADD_IMM2; - case 1: - return OR_IMM2; - case 2: - return ADC_IMM2; - case 4: - return AND_IMM2; - case 5: - return SUB_IMM2; - case 6: - return XOR_IMM2; - default: - return INVALID_INSTR; - } - } - case 0x83: { - struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]); - - switch (modrm->reg) { - case 0: - return ADD_IMM2SX_8; - case 1: - return OR_IMM2SX_8; - case 2: - return ADC_IMM2SX_8; - case 4: - return AND_IMM2SX_8; - case 5: - return SUB_IMM2SX_8; - case 6: - return XOR_IMM2SX_8; - default: - return INVALID_INSTR; + if (ret == -1) { + PrintError("Error decoding operand\n"); + return -1; } - } - case 0x86: - return XCHG_8; - case 0x87: - return XCHG; - case 0x88: - return MOV_2GPR_8; - case 0x89: - return MOV_2GPR; - case 0x8a: - return MOV_GPR2_8; - case 0x8b: - return MOV_GPR2; - - case 0x8c: - return MOV_SR2; - case 0x8e: - return MOV_2SR; - - - case 0x9c: - return PUSHF; - case 0x9d: - return POPF; - - case 0xa0: - return MOV_MEM2AL_8; - case 0xa1: - return MOV_MEM2AX; - case 0xa2: - return MOV_AL2MEM_8; - case 0xa3: - return MOV_AX2MEM; - - case 0xa4: - return MOVS_8; - case 0xa5: - return MOVS; - - case 0xaa: - return STOS_8; - case 0xab: - return STOS; - - case 0xc6: - return MOV_IMM2_8; - case 0xc7: - return MOV_IMM2; - - case 0xf4: - return HLT; - - - case 0xf6: { - struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]); - - switch (modrm->reg) { - case 2: - return NOT_8; - case 3: - return NEG_8; - default: - return INVALID_INSTR; - } - } - case 0xf7: { - struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]); - - switch (modrm->reg) { - case 2: - return NOT; - case 3: - return NEG; - default: - return INVALID_INSTR; - } - } - - - case 0xfe: { - struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]); + instr_ptr += ret; - switch (modrm->reg) { - case 0: - return INC_8; - case 1: - return DEC_8; - default: - return INVALID_INSTR; - } - } + instr->src_operand.type = IMM_OPERAND; + instr->src_operand.size = operand_width; + instr->src_operand.operand = *(sint8_t *)instr_ptr; // sign extend. - case 0xff: { - struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]); - switch (modrm->reg) { - case 0: - return INC; - case 1: - return DEC; - default: - return INVALID_INSTR; - } } default: - return INVALID_INSTR; + PrintError("Invalid Instruction form: %d\n", form); + return -1; + } -} - -int v3_disasm(struct guest_info * info, void *instr_ptr, addr_t * rip, int mark) { - return 0; -} - - -int v3_init_decoder(struct guest_info * core) { return 0; } +static v3_op_type_t op_form_to_type(op_form_t form) { + switch (form) { + case LMSW: + return V3_OP_LMSW; + case SMSW: + return V3_OP_SMSW; + case CLTS: + return V3_OP_CLTS; + case INVLPG: + return V3_OP_INVLPG; + + case MOV_CR2: + return V3_OP_MOVCR2; + case MOV_2CR: + return V3_OP_MOV2CR; + + + case MOV_MEM2_8: + case MOV_MEM2: + case MOV_2MEM_8: + case MOV_2MEM: + case MOV_MEM2AL_8: + case MOV_MEM2AX: + case MOV_AL2MEM_8: + case MOV_AX2MEM: + case MOV_IMM2_8: + case MOV_IMM2: + return V3_OP_MOV; + + case MOVS_8: + case MOVS: + return V3_OP_MOVS; + + case MOVSX_8: + case MOVSX: + return V3_OP_MOVSX; + + case MOVZX_8: + case MOVZX: + return V3_OP_MOVZX; -int v3_deinit_decoder(struct guest_info * core) { - return 0; -} + + case ADC_2MEM_8: + case ADC_2MEM: + case ADC_MEM2_8: + case ADC_MEM2: + case ADC_IMM2_8: + case ADC_IMM2: + case ADC_IMM2SX_8: + return V3_OP_ADC; + + + case ADD_2MEM_8: + case ADD_2MEM: + case ADD_MEM2_8: + case ADD_MEM2: + case ADD_IMM2_8: + case ADD_IMM2: + case ADD_IMM2SX_8: + return V3_OP_ADD; + + case AND_MEM2_8: + case AND_MEM2: + case AND_2MEM_8: + case AND_2MEM: + case AND_IMM2_8: + case AND_IMM2: + case AND_IMM2SX_8: + return V3_OP_AND; + + case OR_2MEM_8: + case OR_2MEM: + case OR_MEM2_8: + case OR_MEM2: + case OR_IMM2_8: + case OR_IMM2: + case OR_IMM2SX_8: + return V3_OP_OR; + + case SUB_2MEM_8: + case SUB_2MEM: + case SUB_MEM2_8: + case SUB_MEM2: + case SUB_IMM2_8: + case SUB_IMM2: + case SUB_IMM2SX_8: + return V3_OP_SUB; + + case XOR_2MEM_8: + case XOR_2MEM: + case XOR_MEM2_8: + case XOR_MEM2: + case XOR_IMM2_8: + case XOR_IMM2: + case XOR_IMM2SX_8: + return V3_OP_XOR; + + case INC_8: + case INC: + return V3_OP_INC; + + case DEC_8: + case DEC: + return V3_OP_DEC; + + case NEG_8: + case NEG: + return V3_OP_NEG; + + case NOT_8: + case NOT: + return V3_OP_NOT; + + case XCHG_8: + case XCHG: + return V3_OP_XCHG; + + case SETB: + return V3_OP_SETB; + case SETBE: + return V3_OP_SETBE; + case SETL: + return V3_OP_SETL; + case SETLE: + return V3_OP_SETLE; + case SETNB: + return V3_OP_SETNB; + case SETNBE: + return V3_OP_SETNBE; + case SETNL: + return V3_OP_SETNL; + case SETNLE: + return V3_OP_SETNLE; + case SETNO: + return V3_OP_SETNO; + case SETNP: + return V3_OP_SETNP; + case SETNS: + return V3_OP_SETNS; + case SETNZ: + return V3_OP_SETNZ; + case SETP: + return V3_OP_SETP; + case SETS: + return V3_OP_SETS; + case SETZ: + return V3_OP_SETZ; + case SETO: + return V3_OP_SETO; + + case STOS_8: + case STOS: + return V3_OP_STOS; + + case HLT: + case PUSHF: + case POPF: + case MOV_DR2: + case MOV_2DR: + case MOV_SR2: + case MOV_2SR: -int v3_encode(struct guest_info * info, struct x86_instr * instr, char * instr_buf) { - return 0; -} - -int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * instr) { - op_code_to_form((void *)instr_ptr); + default: + return V3_INVALID_OP; - return 0; + } }