Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


decoder updates
Jack Lange [Sun, 6 Mar 2011 01:11:15 +0000 (19:11 -0600)]
palacios/include/palacios/vmm_decoder.h
palacios/include/palacios/vmm_instr_decoder.h [new file with mode: 0644]
palacios/src/palacios/vmm.c
palacios/src/palacios/vmm_decoder.c
palacios/src/palacios/vmm_v3dec.c

index 81cf0b0..41817f7 100644 (file)
@@ -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 (file)
index 0000000..b9dc7fd
--- /dev/null
@@ -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 <jarusl@cs.northwestern.edu> 
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#include <palacios/vmm_types.h>
+
+
+/* .... 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;
+    }
+}
index c5a7eb9..bf338a1 100644 (file)
@@ -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);
index 1d9e178..676fd6d 100644 (file)
 
 
 
-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) {
index 78cb8b6..55f1df2 100644 (file)
  */
 
 #include <palacios/vmm_decoder.h>
+#include <palacios/vmm_instr_decoder.h>
 
 
-/* .... 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), &reg_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), &reg_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), &reg_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), &reg_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;
+    }
 }