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.


added hash table
[palacios.git] / palacios / src / palacios / vmm_xed.c
index 5b0d105..e48a1b8 100644 (file)
@@ -1,16 +1,69 @@
+#ifdef __DECODER_TEST__
+#include "vmm_decoder.h"
+#include "vmm_xed.h"
+#include <xed/xed-interface.h>
+#include "vm_guest.h"
+#include "test.h"
+#else
 #include <palacios/vmm_decoder.h>
 #include <palacios/vmm_xed.h>
 #include <xed/xed-interface.h>
 #include <palacios/vm_guest.h>
+#include <palacios/vmm.h>
+
+#endif
 
 static xed_state_t decoder_state;
 
+#define GPR_REGISTER     0
+#define SEGMENT_REGISTER 1
+#define CTRL_REGISTER    2
+#define DEBUG_REGISTER   3
+
+
+
+/* Disgusting mask hack...
+   I can't think right now, so we'll do it this way...
+*/
+static const ullong_t mask_1 = 0x00000000000000ffLL;
+static const ullong_t mask_2 = 0x000000000000ffffLL;
+static const ullong_t mask_4 = 0x00000000ffffffffLL;
+static const ullong_t mask_8 = 0xffffffffffffffffLL;
+
+
+#define MASK(val, length) ({                   \
+      ullong_t mask = 0x0LL;                   \
+      switch (length) {                                \
+      case 1:                                  \
+       mask = mask_1;                          \
+      case 2:                                  \
+       mask = mask_2;                          \
+      case 4:                                  \
+       mask = mask_4;                          \
+      case 8:                                  \
+       mask = mask_8;                          \
+      }                                                \
+      val & mask;})                            \
+
+struct memory_operand {
+  uint_t segment_size;
+  addr_t segment;
+  uint_t base_size;
+  addr_t base;
+  uint_t index_size;
+  addr_t index;
+  addr_t scale;
+  uint_t displacement_size;
+  ullong_t displacement;
+};
+
+
 
 // This returns a pointer to a V3_OPCODE_[*] array defined in vmm_decoder.h
 static int get_opcode(xed_iform_enum_t iform, addr_t * opcode);
 
 static int xed_reg_to_v3_reg(struct guest_info * info, xed_reg_enum_t xed_reg, addr_t * v3_reg, uint_t * reg_len);
-
+static int get_memory_operand(struct guest_info * info,  xed_decoded_inst_t * xed_instr, uint_t index, struct x86_operand * operand);
 
 static int set_decoder_mode(struct guest_info * info, xed_state_t * state) {
   switch (info->cpu_mode) {
@@ -42,7 +95,16 @@ static int set_decoder_mode(struct guest_info * info, xed_state_t * state) {
   return 0;
 }
 
-
+int is_flags_reg(xed_reg_enum_t xed_reg) {
+  switch (xed_reg) {
+  case XED_REG_FLAGS:
+  case XED_REG_EFLAGS:
+  case XED_REG_RFLAGS:
+    return 1;
+  default:
+    return 0;
+  }
+}
 
 
 
@@ -53,6 +115,43 @@ int init_decoder() {
 }
 
 
+int v3_basic_mem_decode(struct guest_info * info, addr_t instr_ptr, uint_t * size, uint_t * instr_length) {
+  xed_decoded_inst_t xed_instr;
+  xed_error_enum_t xed_error;
+  
+
+  if (set_decoder_mode(info, &decoder_state) == -1) {
+    PrintError("Could not set decoder mode\n");
+    return -1;
+  }
+
+
+  xed_decoded_inst_zero_set_mode(&xed_instr, &decoder_state);
+
+  xed_error = xed_decode(&xed_instr, 
+                        REINTERPRET_CAST(const xed_uint8_t *, instr_ptr), 
+                        XED_MAX_INSTRUCTION_BYTES);
+
+  if (xed_error != XED_ERROR_NONE) {
+    PrintError("Xed error: %s\n", xed_error_enum_t2str(xed_error));
+    return -1;
+  }
+
+ *instr_length = xed_decoded_inst_get_length(&xed_instr);
+
+
+ if (xed_decoded_inst_number_of_memory_operands(&xed_instr) == 0) {
+   PrintError("Tried to decode memory operation with no memory operands\n");
+   return -1;
+ }
+
+ *size = xed_decoded_inst_get_memory_operand_length(&xed_instr,0);
+
+ return 0;
+}
+
+
+
 int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * instr) {
   xed_decoded_inst_t xed_instr;
   xed_error_enum_t xed_error;
@@ -85,121 +184,236 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins
 
   xed_iform_enum_t iform = xed_decoded_inst_get_iform_enum(&xed_instr);
 
+
+  PrintDebug("iform=%s\n", xed_iform_enum_t2str(iform));
+
+
+  if (instr->num_operands > 3) {
+    PrintDebug("Special Case Not Handled\n");
+    return -1;
+    // special case
+  } else if (instr->num_operands == 3) {
+    const xed_operand_t * op = xed_inst_operand(xi, 2);
+    xed_operand_enum_t op_enum = xed_operand_name(op);
+
+    if ((!xed_operand_is_register(op_enum)) ||
+       (!is_flags_reg(xed_decoded_inst_get_reg(&xed_instr, op_enum)))) {
+      // special case
+      PrintDebug("Special Case not handled\n");
+      return -1;
+    }
+  }
+
+
+
+
+
   if (get_opcode(iform, &(instr->opcode)) == -1) {
-    PrintError("Could not get opcode. (iform=%s)\n", xed_iform_enum_t2str(iform));
+    PrintDebug("Could not get opcode. (iform=%s)\n", xed_iform_enum_t2str(iform));
     return -1;
   }
 
 
 
-  PrintDebug("Number of operands: %d\n", instr->num_operands);
-  PrintDebug("INSTR length: %d\n", instr->instr_length);
+
+  //PrintDebug("Number of operands: %d\n", instr->num_operands);
+  //PrintDebug("INSTR length: %d\n", instr->instr_length);
 
   // set first operand
   if (instr->num_operands >= 1) {
     const xed_operand_t * op = xed_inst_operand(xi, 0);
-    xed_operand_type_enum_t op_type = xed_operand_type(op);
     xed_operand_enum_t op_enum = xed_operand_name(op);
 
+    struct x86_operand * v3_op = NULL;
+
+    if (xed_operand_written(op)) {
+      v3_op = &(instr->dst_operand);
+    } else {
+      v3_op = &(instr->src_operand);
+    }
+
 
     if (xed_operand_is_register(op_enum)) {
       xed_reg_enum_t xed_reg =  xed_decoded_inst_get_reg(&xed_instr, op_enum);
-      if (xed_reg_to_v3_reg(info, 
-                           xed_reg, 
-                           &(instr->first_operand.operand), 
-                           &(instr->first_operand.size)) == -1) {
-       
+      int v3_reg_type = xed_reg_to_v3_reg(info, 
+                                         xed_reg, 
+                                         &(v3_op->operand), 
+                                         &(v3_op->size));
+                                         
+      if (v3_reg_type == -1) {
        PrintError("First operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg));
-       instr->first_operand.type = INVALID_OPERAND;
+       v3_op->type = INVALID_OPERAND;
        return -1;
+      } else if (v3_reg_type == SEGMENT_REGISTER) {
+       struct v3_segment * seg_reg = (struct v3_segment *)(v3_op->operand);
+       v3_op->operand = (addr_t)&(seg_reg->selector);
       }
 
-      instr->first_operand.type = REG_OPERAND;
-      PrintDebug("First Operand: xed_reg=0x%x\n", instr->first_operand.operand);
-
+      v3_op->type = REG_OPERAND;
     } else {
-      PrintError("Unhandled first operand type %s\n", xed_operand_type_enum_t2str(op_type));
-      return -1;
+
+      switch (op_enum) {
+
+      case XED_OPERAND_MEM0:
+       {
+         /*
+           struct x86_operand * operand = &(instr->dst_operand);
+           
+           if (xed_decoded_inst_mem_read(&xed_instr, 0)) {
+           operand = &(instr->src_operand);
+           } else if (xed_decoded_inst_mem_written(&xed_instr, 0)) {
+           operand = &(instr->dst_operand);
+           }
+         */
+         
+         if (get_memory_operand(info, &xed_instr, 0, v3_op) == -1) {
+           PrintError("Could not get first memory operand\n");
+           return -1;
+         }
+       }
+       break;
+
+      case XED_OPERAND_MEM1:
+      case XED_OPERAND_IMM1:
+       // illegal
+       PrintError("Illegal Operand Order\n");
+       return -1;
+
+
+      case XED_OPERAND_IMM0:
+      case XED_OPERAND_AGEN:
+      case XED_OPERAND_PTR:
+      case XED_OPERAND_RELBR:
+      default:
+       PrintError("Unhandled Operand Type\n");
+       return -1;
+
+
+      }
     }
   }
 
   // set second operand
   if (instr->num_operands >= 2) {
     const xed_operand_t * op = xed_inst_operand(xi, 1);
-    xed_operand_type_enum_t op_type = xed_operand_type(op);
+    //   xed_operand_type_enum_t op_type = xed_operand_type(op);
     xed_operand_enum_t op_enum = xed_operand_name(op);
     
+    struct x86_operand * v3_op;
+
+    if (xed_operand_written(op)) {
+      v3_op = &(instr->dst_operand);
+    } else {
+      v3_op = &(instr->src_operand);
+    }
+
+
     if (xed_operand_is_register(op_enum)) {
       xed_reg_enum_t xed_reg =  xed_decoded_inst_get_reg(&xed_instr, op_enum);
-      if (xed_reg_to_v3_reg(info, 
-                           xed_reg, 
-                           &(instr->second_operand.operand), 
-                           &(instr->second_operand.size)) == -1) {
-       
+      int v3_reg_type = xed_reg_to_v3_reg(info, 
+                                         xed_reg, 
+                                         &(v3_op->operand), 
+                                         &(v3_op->size));
+      if (v3_reg_type == -1) {
        PrintError("Second operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg));
-       instr->second_operand.type = INVALID_OPERAND;
+       v3_op->type = INVALID_OPERAND;
        return -1;
+      } else if (v3_reg_type == SEGMENT_REGISTER) {
+       struct v3_segment * seg_reg = (struct v3_segment *)(v3_op->operand);
+       v3_op->operand = (addr_t)&(seg_reg->selector);
       }
 
-      instr->second_operand.type = REG_OPERAND;
+      v3_op->type = REG_OPERAND;
     
-      PrintDebug("Second Operand: xed_reg=0x%x\n", instr->second_operand.operand); 
+
     } else {
-      PrintError("Unhandled second operand type %s\n", xed_operand_type_enum_t2str(op_type));
-      return -1;
+
+      switch (op_enum) {
+
+      case XED_OPERAND_MEM0:
+       {
+
+         /*
+         if (xed_decoded_inst_mem_read(&xed_instr, 0)) {
+           v3_op = &(instr->src_operand);
+         } else if (xed_decoded_inst_mem_written(&xed_instr, 0)) {
+           v3_op = &(instr->dst_operand);
+         }
+         */
+
+         if (get_memory_operand(info, &xed_instr, 0, v3_op) == -1) {
+           PrintError("Could not get first memory operand\n");
+           return -1;
+         }
+       }
+       break;
+
+      case XED_OPERAND_IMM0:
+       {
+         instr->src_operand.size = xed_decoded_inst_get_immediate_width(&xed_instr);
+
+         if (instr->src_operand.size > 4) {
+           PrintError("Unhandled 64 bit immediates\n");
+           return -1;
+         }
+         instr->src_operand.operand = xed_decoded_inst_get_unsigned_immediate(&xed_instr);
+
+         instr->src_operand.type = IMM_OPERAND;
+
+       }
+       break;
+
+      case XED_OPERAND_MEM1:
+      case XED_OPERAND_IMM1:
+       // illegal
+       PrintError("Illegal Operand Order\n");
+       return -1;
+       
+      case XED_OPERAND_AGEN:
+      case XED_OPERAND_PTR:
+      case XED_OPERAND_RELBR:
+      default:
+       PrintError("Unhandled Operand Type\n");
+       return -1;
+      }
     }
+
   }
 
   // set third operand
   if (instr->num_operands >= 3) {
     const xed_operand_t * op = xed_inst_operand(xi, 2);
-    xed_operand_type_enum_t op_type = xed_operand_type(op);
+    //  xed_operand_type_enum_t op_type = xed_operand_type(op);
     xed_operand_enum_t op_enum = xed_operand_name(op);
 
     if (xed_operand_is_register(op_enum)) {
       xed_reg_enum_t xed_reg =  xed_decoded_inst_get_reg(&xed_instr, op_enum);
-      if (xed_reg_to_v3_reg(info, 
-                           xed_reg, 
-                           &(instr->third_operand.operand), 
-                           &(instr->third_operand.size)) == -1) {
-       
+      int v3_reg_type = xed_reg_to_v3_reg(info, 
+                                         xed_reg, 
+                                         &(instr->third_operand.operand), 
+                                         &(instr->third_operand.size));
+
+      if (v3_reg_type == -1) {
        PrintError("Third operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg));
        instr->third_operand.type = INVALID_OPERAND;
        return -1;
+      } else if (v3_reg_type == SEGMENT_REGISTER) {
+       struct v3_segment * seg_reg = (struct v3_segment *)(instr->third_operand.operand);
+       instr->third_operand.operand = (addr_t)&(seg_reg->selector);
       }
+
+
       instr->third_operand.type = REG_OPERAND;
 
-      PrintDebug("Third Operand: xed_reg=0x%x\n", instr->third_operand.operand); 
+
     } else {
-      PrintError("Unhandled third operand type %s\n", xed_operand_type_enum_t2str(op_type));
+      //      PrintError("Unhandled third operand type %s\n", xed_operand_type_enum_t2str(op_type));
       return -1;
     }
 
 
   }
 
-  /*
-    PrintDebug("category: %s\n", xed_category_enum_t2str(xed_decoded_inst_get_category(&xed_instr)));;
-    PrintDebug("ISA-extension:%s\n ",xed_extension_enum_t2str(xed_decoded_inst_get_extension(&xed_instr)));
-    PrintDebug(" instruction-length: %d\n ", xed_decoded_inst_get_length(&xed_instr));
-    PrintDebug(" operand-size:%d\n ", xed_operand_values_get_effective_operand_width(xed_decoded_inst_operands_const(&xed_instr)));   
-    PrintDebug("address-size:%d\n ", xed_operand_values_get_effective_address_width(xed_decoded_inst_operands_const(&xed_instr))); 
-    PrintDebug("iform-enum-name:%s\n ",xed_iform_enum_t2str(xed_decoded_inst_get_iform_enum(&xed_instr)));
-    PrintDebug("iform-enum-name-dispatch (zero based):%d\n ", xed_decoded_inst_get_iform_enum_dispatch(&xed_instr));
-    PrintDebug("iclass-max-iform-dispatch: %d\n ", xed_iform_max_per_iclass(xed_decoded_inst_get_iclass(&xed_instr)));
-  */  
-  // operands
-  // print_operands(&xed_instr);
-  
-  // memops
-  // print_memops(&xed_instr);
-  
-  // flags
-  //print_flags(&xed_instr);
-  
-  // attributes
-  //print_attributes(&xed_instr);*/
-
 
 
     return 0;
@@ -212,6 +426,95 @@ int v3_encode(struct guest_info * info, struct x86_instr * instr, char * instr_b
 }
 
 
+
+
+
+static int get_memory_operand(struct guest_info * info,  xed_decoded_inst_t * xed_instr, uint_t op_index, struct x86_operand * operand) {
+  struct memory_operand mem_op;
+
+  addr_t seg;
+  addr_t base;
+  addr_t scale;
+  addr_t index;
+  ullong_t displacement;
+  // struct v3_segment * seg_reg;
+
+
+
+
+  memset((void*)&mem_op, '\0', sizeof(struct memory_operand));
+
+  xed_reg_enum_t xed_seg = xed_decoded_inst_get_seg_reg(xed_instr, op_index);
+  if (xed_seg != XED_REG_INVALID) {
+    struct v3_segment *tmp_segment;
+    if (xed_reg_to_v3_reg(info, xed_seg, (addr_t *)&tmp_segment, &(mem_op.segment_size)) == -1) {
+      PrintError("Unhandled Segment Register\n");
+      return -1;
+    }
+    mem_op.segment = tmp_segment->base;
+  }
+
+  xed_reg_enum_t xed_base = xed_decoded_inst_get_base_reg(xed_instr, op_index);
+  if (xed_base != XED_REG_INVALID) {
+    addr_t base_reg;
+    if (xed_reg_to_v3_reg(info, xed_base, &base_reg, &(mem_op.base_size)) == -1) {
+      PrintError("Unhandled Base register\n");
+      return -1;
+    }
+    mem_op.base = *(addr_t *)base_reg;
+  }
+
+  
+
+  xed_reg_enum_t xed_idx = xed_decoded_inst_get_index_reg(xed_instr, op_index);
+  if ((op_index == 0) && (xed_idx != XED_REG_INVALID)) {
+    addr_t index_reg;
+    
+    if (xed_reg_to_v3_reg(info, xed_idx, &index_reg, &(mem_op.index_size)) == -1) {
+      PrintError("Unhandled Index Register\n");
+      return -1;
+    }
+
+    mem_op.index= *(addr_t *)index_reg;
+
+    xed_uint_t xed_scale = xed_decoded_inst_get_scale(xed_instr, op_index);
+    if (xed_scale != 0) {
+      mem_op.scale = xed_scale;
+    }
+  }
+
+
+  xed_uint_t disp_bits = xed_decoded_inst_get_memory_displacement_width(xed_instr, op_index);
+  if (disp_bits) {
+    xed_int64_t xed_disp = xed_decoded_inst_get_memory_displacement(xed_instr, op_index);
+
+    mem_op.displacement_size = disp_bits / 8;
+    mem_op.displacement = xed_disp;
+    
+  }
+
+  operand->type = MEM_OPERAND;
+  operand->size = xed_decoded_inst_get_memory_operand_length(xed_instr, op_index);
+  
+  
+
+  PrintDebug("Struct: Seg=%x, base=%x, index=%x, scale=%x, displacement=%x\n", 
+            mem_op.segment, mem_op.base, mem_op.index, mem_op.scale, mem_op.displacement);
+
+
+  seg = mem_op.segment;
+  base = MASK(mem_op.base, mem_op.base_size);
+  index = MASK(mem_op.index, mem_op.index_size);
+  scale = mem_op.scale;
+  displacement = MASK(mem_op.displacement, mem_op.displacement_size);
+
+  PrintDebug("Seg=%x, base=%x, index=%x, scale=%x, displacement=%x\n", seg, base, index, scale, displacement);
+  
+  operand->operand = seg + base + (scale * index) + displacement;
+  return 0;
+}
+
+
 static int xed_reg_to_v3_reg(struct guest_info * info, xed_reg_enum_t xed_reg, addr_t * v3_reg, uint_t * reg_len) {
 
   switch (xed_reg) {
@@ -226,158 +529,158 @@ static int xed_reg_to_v3_reg(struct guest_info * info, xed_reg_enum_t xed_reg, a
   case XED_REG_RAX: 
     *v3_reg = (addr_t)&(info->vm_regs.rax);
     *reg_len = 8;
-    break;
+    return GPR_REGISTER;
   case XED_REG_EAX:
     *v3_reg = (addr_t)&(info->vm_regs.rax);
     *reg_len = 4;
-    break;
+    return GPR_REGISTER;
   case XED_REG_AX:
     *v3_reg = (addr_t)&(info->vm_regs.rax);
     *reg_len = 2;
-    break;
+    return GPR_REGISTER;
   case XED_REG_AH:
     *v3_reg = (addr_t)(&(info->vm_regs.rax)) + 1;
     *reg_len = 1;
-    break;
+    return GPR_REGISTER;
   case XED_REG_AL:
     *v3_reg = (addr_t)&(info->vm_regs.rax);
     *reg_len = 1;
-    break;
+    return GPR_REGISTER;
 
   case XED_REG_RCX: 
     *v3_reg = (addr_t)&(info->vm_regs.rcx);
     *reg_len = 8;
-    break;
+    return GPR_REGISTER;
   case XED_REG_ECX:
     *v3_reg = (addr_t)&(info->vm_regs.rcx);
     *reg_len = 4;
-    break;
+    return GPR_REGISTER;
   case XED_REG_CX:
     *v3_reg = (addr_t)&(info->vm_regs.rcx);
     *reg_len = 2;
-    break;
+    return GPR_REGISTER;
   case XED_REG_CH:
     *v3_reg = (addr_t)(&(info->vm_regs.rcx)) + 1;
     *reg_len = 1;
-    break;
+    return GPR_REGISTER;
   case XED_REG_CL:
     *v3_reg = (addr_t)&(info->vm_regs.rcx);
     *reg_len = 1;
-    break;
+    return GPR_REGISTER;
 
   case XED_REG_RDX: 
     *v3_reg = (addr_t)&(info->vm_regs.rdx);
     *reg_len = 8;
-    break;
+    return GPR_REGISTER;
   case XED_REG_EDX:
     *v3_reg = (addr_t)&(info->vm_regs.rdx);
     *reg_len = 4;
-    break;
+    return GPR_REGISTER;
   case XED_REG_DX:
     *v3_reg = (addr_t)&(info->vm_regs.rdx);
     *reg_len = 2;
-    break;
+    return GPR_REGISTER;
   case XED_REG_DH:
     *v3_reg = (addr_t)(&(info->vm_regs.rdx)) + 1;
     *reg_len = 1;
-    break;
+    return GPR_REGISTER;
   case XED_REG_DL:
     *v3_reg = (addr_t)&(info->vm_regs.rdx);
     *reg_len = 1;
-    break;
+    return GPR_REGISTER;
 
   case XED_REG_RBX: 
     *v3_reg = (addr_t)&(info->vm_regs.rbx);
     *reg_len = 8;
-    break;
+    return GPR_REGISTER;
   case XED_REG_EBX:
     *v3_reg = (addr_t)&(info->vm_regs.rbx);
     *reg_len = 4;
-    break;
+    return GPR_REGISTER;
   case XED_REG_BX:
     *v3_reg = (addr_t)&(info->vm_regs.rbx);
     *reg_len = 2;
-    break;
+    return GPR_REGISTER;
   case XED_REG_BH:
     *v3_reg = (addr_t)(&(info->vm_regs.rbx)) + 1;
     *reg_len = 1;
-    break;
+    return GPR_REGISTER;
   case XED_REG_BL:
     *v3_reg = (addr_t)&(info->vm_regs.rbx);
     *reg_len = 1;
-    break;
+    return GPR_REGISTER;
 
 
   case XED_REG_RSP:
     *v3_reg = (addr_t)&(info->vm_regs.rsp);
     *reg_len = 8;
-    break;
+    return GPR_REGISTER;
   case XED_REG_ESP:
     *v3_reg = (addr_t)&(info->vm_regs.rsp);
     *reg_len = 4;
-    break;
+    return GPR_REGISTER;
   case XED_REG_SP:
     *v3_reg = (addr_t)&(info->vm_regs.rsp);
     *reg_len = 2;
-    break;
+    return GPR_REGISTER;
   case XED_REG_SPL:
     *v3_reg = (addr_t)&(info->vm_regs.rsp);
     *reg_len = 1;
-    break;
+    return GPR_REGISTER;
 
   case XED_REG_RBP:
     *v3_reg = (addr_t)&(info->vm_regs.rbp);
     *reg_len = 8;
-    break;
+    return GPR_REGISTER;
   case XED_REG_EBP:
     *v3_reg = (addr_t)&(info->vm_regs.rbp);
     *reg_len = 4;
-    break;
+    return GPR_REGISTER;
   case XED_REG_BP:
     *v3_reg = (addr_t)&(info->vm_regs.rbp);
     *reg_len = 2;
-    break;
+    return GPR_REGISTER;
   case XED_REG_BPL:
     *v3_reg = (addr_t)&(info->vm_regs.rbp);
     *reg_len = 1;
-    break;
+    return GPR_REGISTER;
 
 
 
   case XED_REG_RSI:
     *v3_reg = (addr_t)&(info->vm_regs.rsi);
     *reg_len = 8;
-    break;
+    return GPR_REGISTER;
   case XED_REG_ESI:
     *v3_reg = (addr_t)&(info->vm_regs.rsi);
     *reg_len = 4;
-    break;
+    return GPR_REGISTER;
   case XED_REG_SI:
     *v3_reg = (addr_t)&(info->vm_regs.rsi);
     *reg_len = 2;
-    break;
+    return GPR_REGISTER;
   case XED_REG_SIL:
     *v3_reg = (addr_t)&(info->vm_regs.rsi);
     *reg_len = 1;
-    break;
+    return GPR_REGISTER;
 
 
   case XED_REG_RDI:
     *v3_reg = (addr_t)&(info->vm_regs.rdi);
     *reg_len = 8;
-    break;
+    return GPR_REGISTER;
   case XED_REG_EDI:
     *v3_reg = (addr_t)&(info->vm_regs.rdi);
     *reg_len = 4;
-    break;
+    return GPR_REGISTER;
   case XED_REG_DI:
     *v3_reg = (addr_t)&(info->vm_regs.rdi);
     *reg_len = 2;
-    break;
+    return GPR_REGISTER;
   case XED_REG_DIL:
     *v3_reg = (addr_t)&(info->vm_regs.rdi);
     *reg_len = 1;
-    break;
+    return GPR_REGISTER;
 
 
     /* 
@@ -386,49 +689,49 @@ static int xed_reg_to_v3_reg(struct guest_info * info, xed_reg_enum_t xed_reg, a
   case XED_REG_RIP:
     *v3_reg = (addr_t)&(info->rip);
     *reg_len = 8;
-    break;
+    return CTRL_REGISTER;
   case XED_REG_EIP:
     *v3_reg = (addr_t)&(info->rip);
     *reg_len = 4;
-    break;  
+    return CTRL_REGISTER;  
   case XED_REG_IP:
     *v3_reg = (addr_t)&(info->rip);
     *reg_len = 2;
-    break;
+    return CTRL_REGISTER;
 
   case XED_REG_FLAGS:
     *v3_reg = (addr_t)&(info->ctrl_regs.rflags);
     *reg_len = 2;
-    break;
+    return CTRL_REGISTER;
   case XED_REG_EFLAGS:
     *v3_reg = (addr_t)&(info->ctrl_regs.rflags);
     *reg_len = 4;
-    break;
+    return CTRL_REGISTER;
   case XED_REG_RFLAGS:
     *v3_reg = (addr_t)&(info->ctrl_regs.rflags);
     *reg_len = 8;
-    break;
+    return CTRL_REGISTER;
 
   case XED_REG_CR0:
     *v3_reg = (addr_t)&(info->ctrl_regs.cr0);
     *reg_len = 4;
-    break;
+    return CTRL_REGISTER;
   case XED_REG_CR2:
     *v3_reg = (addr_t)&(info->ctrl_regs.cr2);
     *reg_len = 4;
-    break;
+    return CTRL_REGISTER;
   case XED_REG_CR3:
     *v3_reg = (addr_t)&(info->ctrl_regs.cr3);
     *reg_len = 4;
-    break;
+    return CTRL_REGISTER;
   case XED_REG_CR4:
     *v3_reg = (addr_t)&(info->ctrl_regs.cr4);
     *reg_len = 4;
-    break;
+    return CTRL_REGISTER;
   case XED_REG_CR8:
     *v3_reg = (addr_t)&(info->ctrl_regs.cr8);
     *reg_len = 4;
-    break;
+    return CTRL_REGISTER;
 
   case XED_REG_CR1:
   case XED_REG_CR5:
@@ -450,29 +753,23 @@ static int xed_reg_to_v3_reg(struct guest_info * info, xed_reg_enum_t xed_reg, a
      * SEGMENT REGS
      */
   case XED_REG_CS:
-    *v3_reg = (addr_t)&(info->segments.cs.selector);
-    *reg_len = 16;
-    break;
+    *v3_reg = (addr_t)&(info->segments.cs);
+    return SEGMENT_REGISTER;
   case XED_REG_DS:
-    *v3_reg = (addr_t)&(info->segments.ds.selector);
-    *reg_len = 16;
-    break;
+    *v3_reg = (addr_t)&(info->segments.ds);
+    return SEGMENT_REGISTER;
   case XED_REG_ES:
-    *v3_reg = (addr_t)&(info->segments.es.selector);
-    *reg_len = 16;
-    break;
+    *v3_reg = (addr_t)&(info->segments.es);
+    return SEGMENT_REGISTER;
   case XED_REG_SS:
-    *v3_reg = (addr_t)&(info->segments.ss.selector);
-    *reg_len = 16;
-    break;
+    *v3_reg = (addr_t)&(info->segments.ss);
+    return SEGMENT_REGISTER;
   case XED_REG_FS:
-    *v3_reg = (addr_t)&(info->segments.fs.selector);
-    *reg_len = 16;
-    break;
+    *v3_reg = (addr_t)&(info->segments.fs);
+    return SEGMENT_REGISTER;
   case XED_REG_GS:
-    *v3_reg = (addr_t)&(info->segments.fs.selector);
-    *reg_len = 16;
-    break;
+    *v3_reg = (addr_t)&(info->segments.gs);
+    return SEGMENT_REGISTER;
 
 
   case XED_REG_GDTR: