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.


Corrected handling of decode of memory operands that have a
[palacios.git] / palacios / src / palacios / vmm_xed.c
1 /* 
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20 #ifdef __DECODER_TEST__
21 #include "vmm_decoder.h"
22 #include "vmm_xed.h"
23 #include <xed/xed-interface.h>
24 #include "vm_guest.h"
25 #include "test.h"
26
27 #else
28
29 #include <palacios/vmm_decoder.h>
30 #include <palacios/vmm_xed.h>
31 #include <xed/xed-interface.h>
32 #include <palacios/vm_guest.h>
33 #include <palacios/vmm.h>
34 #endif
35
36
37
38 #ifndef CONFIG_DEBUG_XED
39 #undef PrintDebug
40 #define PrintDebug(fmt, args...)
41 #endif
42
43
44
45
46 static uint_t tables_inited = 0;
47
48
49 #define GPR_REGISTER     0
50 #define SEGMENT_REGISTER 1
51 #define CTRL_REGISTER    2
52 #define DEBUG_REGISTER   3
53
54
55
56 /* Disgusting mask hack...
57    I can't think right now, so we'll do it this way...
58 */
59 static const ullong_t mask_1 = 0x00000000000000ffLL;
60 static const ullong_t mask_2 = 0x000000000000ffffLL;
61 static const ullong_t mask_4 = 0x00000000ffffffffLL;
62 static const ullong_t mask_8 = 0xffffffffffffffffLL;
63
64
65 #define MASK(val, length) ({                    \
66             ullong_t mask = 0x0LL;              \
67             switch (length) {                   \
68                 case 1:                         \
69                     mask = mask_1;              \
70                     break;                      \
71                 case 2:                         \
72                     mask = mask_2;              \
73                     break;                      \
74                 case 4:                         \
75                     mask = mask_4;              \
76                     break;                      \
77                 case 8:                         \
78                     mask = mask_8;              \
79                     break;                      \
80             }                                   \
81             val & mask;                         \
82         })
83                                                 
84 struct memory_operand {
85     uint_t segment_size;
86     addr_t segment;
87     uint_t base_size;
88     addr_t base;
89     uint_t index_size;
90     addr_t index;
91     addr_t scale;
92     uint_t displacement_size;
93     ullong_t displacement;
94 };
95
96
97
98
99 static v3_op_type_t get_opcode(xed_iform_enum_t iform);
100
101 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);
102 static int get_memory_operand(struct guest_info * info,  xed_decoded_inst_t * xed_instr, uint_t index, struct x86_operand * operand);
103
104 static int set_decoder_mode(struct guest_info * info, xed_state_t * state) {
105     switch (v3_get_vm_cpu_mode(info)) {
106         case REAL:
107             if (state->mmode != XED_MACHINE_MODE_LEGACY_16) {
108                 xed_state_init(state,
109                                XED_MACHINE_MODE_LEGACY_16, 
110                                XED_ADDRESS_WIDTH_16b, 
111                                XED_ADDRESS_WIDTH_16b); 
112             }
113             break;
114         case PROTECTED:
115         case PROTECTED_PAE:
116             if (state->mmode != XED_MACHINE_MODE_LEGACY_32) {
117                 xed_state_init(state,
118                                XED_MACHINE_MODE_LEGACY_32, 
119                                XED_ADDRESS_WIDTH_32b, 
120                                XED_ADDRESS_WIDTH_32b);
121             }
122             break;
123         case LONG_32_COMPAT:
124             if (state->mmode != XED_MACHINE_MODE_LONG_COMPAT_32) {
125                 xed_state_init(state,
126                                XED_MACHINE_MODE_LONG_COMPAT_32, 
127                                XED_ADDRESS_WIDTH_32b, 
128                                XED_ADDRESS_WIDTH_32b);
129             }
130             break;
131         case LONG:
132             if (state->mmode != XED_MACHINE_MODE_LONG_64) {
133                 PrintDebug("Setting decoder to long mode\n");
134                 //      state->mmode = XED_MACHINE_MODE_LONG_64;
135                 //xed_state_set_machine_mode(state, XED_MACHINE_MODE_LONG_64);
136                 xed_state_init(state,
137                                XED_MACHINE_MODE_LONG_64, 
138                                XED_ADDRESS_WIDTH_64b, 
139                                XED_ADDRESS_WIDTH_64b);
140             }
141             break;
142         default:
143             PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
144             return -1;
145     }
146     return 0;
147 }
148
149 /*
150   static int is_flags_reg(xed_reg_enum_t xed_reg) {
151   switch (xed_reg) {
152   case XED_REG_FLAGS:
153   case XED_REG_EFLAGS:
154   case XED_REG_RFLAGS:
155   return 1;
156   default:
157   return 0;
158   }
159   }
160 */
161
162 int v3_init_decoder(struct guest_info * info) {
163     // Global library initialization, only do it once
164     if (tables_inited == 0) {
165         xed_tables_init();
166         tables_inited = 1;
167     }
168
169     xed_state_t * decoder_state = (xed_state_t *)V3_Malloc(sizeof(xed_state_t));
170     xed_state_zero(decoder_state);
171     xed_state_init(decoder_state,
172                    XED_MACHINE_MODE_LEGACY_32, 
173                    XED_ADDRESS_WIDTH_32b, 
174                    XED_ADDRESS_WIDTH_32b);
175
176     info->decoder_state = decoder_state;
177
178     return 0;
179 }
180
181
182
183 int v3_deinit_decoder(struct guest_info * core) {
184     V3_Free(core->decoder_state);
185
186     return 0;
187 }
188
189
190 int v3_basic_mem_decode(struct guest_info * info, addr_t instr_ptr, struct basic_instr_info * instr_info) {
191     xed_decoded_inst_t xed_instr;
192     xed_error_enum_t xed_error;
193   
194
195     if (set_decoder_mode(info, info->decoder_state) == -1) {
196         PrintError("Could not set decoder mode\n");
197         return -1;
198     }
199
200
201     xed_decoded_inst_zero_set_mode(&xed_instr, info->decoder_state);
202
203     xed_error = xed_decode(&xed_instr, 
204                            REINTERPRET_CAST(const xed_uint8_t *, instr_ptr), 
205                            XED_MAX_INSTRUCTION_BYTES);
206
207     if (xed_error != XED_ERROR_NONE) {
208         PrintError("Xed error: %s\n", xed_error_enum_t2str(xed_error));
209         return -1;
210     }
211
212     instr_info->instr_length = xed_decoded_inst_get_length(&xed_instr);
213
214
215     if (xed_decoded_inst_number_of_memory_operands(&xed_instr) == 0) {
216         PrintError("Tried to decode memory operation with no memory operands\n");
217         return -1;
218     }
219
220     instr_info->op_size = xed_decoded_inst_get_memory_operand_length(&xed_instr, 0);
221
222
223     xed_category_enum_t cat = xed_decoded_inst_get_category(&xed_instr);
224     if (cat == XED_CATEGORY_STRINGOP) {
225         instr_info->str_op = 1;
226     } else {
227         instr_info->str_op = 0;
228     }
229
230     xed_operand_values_t * operands = xed_decoded_inst_operands(&xed_instr);
231     if (xed_operand_values_has_real_rep(operands)) {
232         instr_info->has_rep = 1;
233     } else {
234         instr_info->has_rep = 0;
235     }
236
237     return 0;
238 }
239
240
241 static int decode_string_op(struct guest_info * info, 
242                             xed_decoded_inst_t * xed_instr,  const xed_inst_t * xi,
243                             struct x86_instr * instr) {
244
245     PrintDebug("String operation\n");
246
247     if (instr->op_type == V3_OP_MOVS) {
248         instr->num_operands = 2;
249
250         if (get_memory_operand(info, xed_instr, 0, &(instr->dst_operand)) == -1) {
251             PrintError("Could not get Destination memory operand\n");
252             return -1;
253         }
254
255         if (get_memory_operand(info, xed_instr, 1, &(instr->src_operand)) == -1) {
256             PrintError("Could not get Source memory operand\n");
257             return -1;
258         }
259
260         if (instr->prefixes.rep == 1) {
261             addr_t reg_addr = 0;
262             uint_t reg_length = 0;
263
264             xed_reg_to_v3_reg(info, xed_decoded_inst_get_reg(xed_instr, XED_OPERAND_REG0), &reg_addr, &reg_length);
265             instr->str_op_length = MASK(*(addr_t *)reg_addr, reg_length);
266         } else {
267             instr->str_op_length = 1;
268         }
269
270     } else if (instr->op_type == V3_OP_STOS) {
271         instr->num_operands = 2;
272
273         if (get_memory_operand(info, xed_instr, 0, &(instr->dst_operand)) == -1) {
274             PrintError("Could not get Destination memory operand\n");
275             return -1;
276         }
277
278         // STOS reads from rax
279         xed_reg_to_v3_reg(info, xed_decoded_inst_get_reg(xed_instr, XED_OPERAND_REG0), 
280                           &(instr->src_operand.operand), 
281                           &(instr->src_operand.size));
282         instr->src_operand.type = REG_OPERAND;
283     
284         if (instr->prefixes.rep == 1) {
285             addr_t reg_addr = 0;
286             uint_t reg_length = 0;
287
288             xed_reg_to_v3_reg(info, xed_decoded_inst_get_reg(xed_instr, XED_OPERAND_REG1), &reg_addr, &reg_length);
289             instr->str_op_length = MASK(*(addr_t *)reg_addr, reg_length);
290         } else {
291             instr->str_op_length = 1;
292         }
293
294     } else {
295         PrintError("Unhandled String OP\n");
296         return -1;
297     }
298
299     return 0;
300 }
301
302
303
304 int v3_disasm(struct guest_info * info, void *instr_ptr, addr_t * rip, int mark) {
305     char buffer[256];
306     int i;
307     unsigned length;
308     xed_decoded_inst_t xed_instr;
309     xed_error_enum_t xed_error;
310
311     /* disassemble the specified instruction */
312     if (set_decoder_mode(info, info->decoder_state) == -1) {
313         PrintError("Could not set decoder mode\n");
314         return -1;
315     }
316
317     xed_decoded_inst_zero_set_mode(&xed_instr, info->decoder_state);
318
319     xed_error = xed_decode(&xed_instr, 
320                            REINTERPRET_CAST(const xed_uint8_t *, instr_ptr), 
321                            XED_MAX_INSTRUCTION_BYTES);
322
323     if (xed_error != XED_ERROR_NONE) {
324         PrintError("Xed error: %s\n", xed_error_enum_t2str(xed_error));
325         return -1;
326     }
327
328     /* obtain string representation in AT&T syntax */
329     if (!xed_format_att(&xed_instr, buffer, sizeof(buffer), *rip)) {
330         PrintError("Xed error: cannot disaaemble\n");
331         return -1;
332     }
333
334     /* print address, opcode bytes and the disassembled instruction */
335     length = xed_decoded_inst_get_length(&xed_instr);
336     V3_Print("0x%p %c ", (void *) *rip, mark ? '*' : ' ');
337     for (i = 0; i < length; i++) {
338         unsigned char b = ((unsigned char *) instr_ptr)[i];
339         V3_Print("%x%x ", b >> 4, b & 0xf);
340     }
341     while (i++ < 8) {
342         V3_Print("   ");
343     }
344     V3_Print("%s\n", buffer);
345
346     /* move on to next instruction */
347     *rip += length;
348     return 0;
349 }
350
351
352
353 int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * instr) {
354     xed_decoded_inst_t xed_instr;
355     xed_error_enum_t xed_error;
356
357
358     v3_get_prefixes((uchar_t *)instr_ptr, &(instr->prefixes));
359
360     if (set_decoder_mode(info, info->decoder_state) == -1) {
361         PrintError("Could not set decoder mode\n");
362         return -1;
363     }
364
365     xed_decoded_inst_zero_set_mode(&xed_instr, info->decoder_state);
366
367     xed_error = xed_decode(&xed_instr, 
368                            REINTERPRET_CAST(const xed_uint8_t *, instr_ptr), 
369                            XED_MAX_INSTRUCTION_BYTES);
370
371
372     if (xed_error != XED_ERROR_NONE) {
373         PrintError("Xed error: %s\n", xed_error_enum_t2str(xed_error));
374         return -1;
375     }
376
377     const xed_inst_t * xi = xed_decoded_inst_inst(&xed_instr);
378   
379     instr->instr_length = xed_decoded_inst_get_length(&xed_instr);
380
381
382     xed_iform_enum_t iform = xed_decoded_inst_get_iform_enum(&xed_instr);
383
384 #ifdef CONFIG_DEBUG_XED
385     xed_iclass_enum_t iclass = xed_decoded_inst_get_iclass(&xed_instr);
386
387     PrintDebug("iform=%s, iclass=%s\n", xed_iform_enum_t2str(iform), xed_iclass_enum_t2str(iclass));
388 #endif
389
390
391     if ((instr->op_type = get_opcode(iform)) == V3_INVALID_OP) {
392         PrintError("Could not get opcode. (iform=%s)\n", xed_iform_enum_t2str(iform));
393         return -1;
394     }
395
396
397     // We special case the string operations...
398     if (xed_decoded_inst_get_category(&xed_instr) == XED_CATEGORY_STRINGOP) {
399         instr->is_str_op = 1;
400         return decode_string_op(info, &xed_instr, xi, instr); 
401     } else {
402         instr->is_str_op = 0;
403         instr->str_op_length = 0;
404     }
405
406     instr->num_operands = xed_decoded_inst_noperands(&xed_instr);
407
408     /*
409       if (instr->num_operands > 3) {
410       PrintDebug("Special Case Not Handled (more than 3 operands) (iform=%s)\n", xed_iform_enum_t2str(iform)
411       return -1;
412       // special case
413       } else if (instr->num_operands == 3) {
414       const xed_operand_t * op = xed_inst_operand(xi, 2);
415       xed_operand_enum_t op_enum = xed_operand_name(op);
416       
417       if ((!xed_operand_is_register(op_enum)) ||
418       (!is_flags_reg(xed_decoded_inst_get_reg(&xed_instr, op_enum)))) {
419       // special case
420       PrintError("Special Case not handled (iform=%s)\n", xed_iform_enum_t2str(iform));
421       return -1;
422       }
423       }
424     */
425
426     //PrintDebug("Number of operands: %d\n", instr->num_operands);
427     //PrintDebug("INSTR length: %d\n", instr->instr_length);
428
429     // set first operand
430     if (instr->num_operands >= 1) {
431         const xed_operand_t * op = xed_inst_operand(xi, 0);
432         xed_operand_enum_t op_enum = xed_operand_name(op);
433
434         struct x86_operand * v3_op = NULL;
435
436         /*
437           if (xed_operand_written(op)) {
438           v3_op = &(instr->dst_operand);
439           } else {
440           v3_op = &(instr->src_operand);
441           }
442         */
443
444         v3_op = &(instr->dst_operand);
445
446         if (xed_operand_is_register(op_enum)) {
447             xed_reg_enum_t xed_reg =  xed_decoded_inst_get_reg(&xed_instr, op_enum);
448             int v3_reg_type = xed_reg_to_v3_reg(info, 
449                                                 xed_reg, 
450                                                 &(v3_op->operand), 
451                                                 &(v3_op->size));
452
453             if (v3_reg_type == -1) {
454                 PrintError("First operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg));
455                 v3_op->type = INVALID_OPERAND;
456                 return -1;
457             } else if (v3_reg_type == SEGMENT_REGISTER) {
458                 struct v3_segment * seg_reg = (struct v3_segment *)(v3_op->operand);
459                 v3_op->operand = (addr_t)&(seg_reg->selector);
460             }
461
462             v3_op->type = REG_OPERAND;
463         } else {
464
465             switch (op_enum) {
466
467                 case XED_OPERAND_MEM0:
468                     {
469                         PrintDebug("Memory operand (1)\n");
470                         if (get_memory_operand(info, &xed_instr, 0, v3_op) == -1) {
471                             PrintError("Could not get first memory operand\n");
472                             return -1;
473                         }
474                     }
475                     break;
476
477                 case XED_OPERAND_MEM1:
478                 case XED_OPERAND_IMM1:
479                     // illegal
480                     PrintError("Illegal Operand Order\n");
481                     return -1;
482
483
484                 case XED_OPERAND_IMM0:
485                 case XED_OPERAND_AGEN:
486                 case XED_OPERAND_PTR:
487                 case XED_OPERAND_RELBR:
488                 default:
489                     PrintError("Unhandled Operand Type\n");
490                     return -1;
491             }
492         }
493     }
494
495     // set second operand
496     if (instr->num_operands >= 2) {
497         const xed_operand_t * op = xed_inst_operand(xi, 1);
498         //   xed_operand_type_enum_t op_type = xed_operand_type(op);
499         xed_operand_enum_t op_enum = xed_operand_name(op);
500     
501         struct x86_operand * v3_op;
502
503         /*
504           if (xed_operand_written(op)) {
505           v3_op = &(instr->dst_operand);
506           } else {
507           v3_op = &(instr->src_operand);
508           }
509         */
510         v3_op = &(instr->src_operand);
511
512         if (xed_operand_is_register(op_enum)) {
513             xed_reg_enum_t xed_reg =  xed_decoded_inst_get_reg(&xed_instr, op_enum);
514             int v3_reg_type = xed_reg_to_v3_reg(info, 
515                                                 xed_reg, 
516                                                 &(v3_op->operand), 
517                                                 &(v3_op->size));
518             if (v3_reg_type == -1) {
519                 PrintError("Second operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg));
520                 v3_op->type = INVALID_OPERAND;
521                 return -1;
522             } else if (v3_reg_type == SEGMENT_REGISTER) {
523                 struct v3_segment * seg_reg = (struct v3_segment *)(v3_op->operand);
524                 v3_op->operand = (addr_t)&(seg_reg->selector);
525             }
526
527             v3_op->type = REG_OPERAND;
528         } else {
529             switch (op_enum) {
530
531                 case XED_OPERAND_MEM0:
532                     {
533                         PrintDebug("Memory operand (2)\n");
534                         if (get_memory_operand(info, &xed_instr, 0, v3_op) == -1) {
535                             PrintError("Could not get first memory operand\n");
536                             return -1;
537                         }
538                     }
539                     break;
540
541                 case XED_OPERAND_IMM0:
542                     {
543                         instr->src_operand.size = xed_decoded_inst_get_immediate_width(&xed_instr);
544
545                         if (instr->src_operand.size > 4) {
546                             PrintError("Unhandled 64 bit immediates\n");
547                             return -1;
548                         }
549                         instr->src_operand.operand = xed_decoded_inst_get_unsigned_immediate(&xed_instr);
550
551                         instr->src_operand.type = IMM_OPERAND;
552
553                     }
554                     break;
555
556                 case XED_OPERAND_MEM1:
557                 case XED_OPERAND_IMM1:
558                     // illegal
559                     PrintError("Illegal Operand Order\n");
560                     return -1;
561         
562                 case XED_OPERAND_AGEN:
563                 case XED_OPERAND_PTR:
564                 case XED_OPERAND_RELBR:
565                 default:
566                     PrintError("Unhandled Operand Type\n");
567                     return -1;
568             }
569         }
570     }
571
572     // set third operand
573     if (instr->num_operands >= 3) {
574         const xed_operand_t * op = xed_inst_operand(xi, 2);
575         xed_operand_type_enum_t op_type = xed_operand_type(op);
576         xed_operand_enum_t op_enum = xed_operand_name(op);
577
578         if (xed_operand_is_register(op_enum)) {
579             xed_reg_enum_t xed_reg =  xed_decoded_inst_get_reg(&xed_instr, op_enum);
580             int v3_reg_type = xed_reg_to_v3_reg(info, 
581                                                 xed_reg, 
582                                                 &(instr->third_operand.operand), 
583                                                 &(instr->third_operand.size));
584
585             if (v3_reg_type == -1) {
586                 PrintError("Third operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg));
587                 instr->third_operand.type = INVALID_OPERAND;
588                 return -1;
589             } else if (v3_reg_type == SEGMENT_REGISTER) {
590                 struct v3_segment * seg_reg = (struct v3_segment *)(instr->third_operand.operand);
591                 instr->third_operand.operand = (addr_t)&(seg_reg->selector);
592             }
593
594
595             instr->third_operand.type = REG_OPERAND;
596
597         } else {
598             PrintError("Unhandled third operand type %s\n", xed_operand_type_enum_t2str(op_type));
599             instr->num_operands = 2;
600         }
601     }
602
603     return 0;
604 }
605
606
607 int v3_encode(struct guest_info * info, struct x86_instr * instr, char * instr_buf) {
608
609     return -1;
610 }
611
612
613
614
615
616 static int get_memory_operand(struct guest_info * info,  xed_decoded_inst_t * xed_instr, uint_t op_index, struct x86_operand * operand) {
617     struct memory_operand mem_op;
618
619     addr_t seg;
620     addr_t base;
621     addr_t scale;
622     addr_t index;
623     ullong_t displacement;
624     int addr_width = v3_get_addr_width(info);
625     v3_cpu_mode_t cpu_mode = v3_get_vm_cpu_mode(info);
626     // struct v3_segment * seg_reg;
627
628     PrintDebug("Xed mode = %s\n", xed_machine_mode_enum_t2str(xed_state_get_machine_mode(info->decoder_state)));
629     PrintDebug("Address width: %s\n",
630                xed_address_width_enum_t2str(xed_state_get_address_width(info->decoder_state)));
631     PrintDebug("Stack Address width: %s\n",
632                xed_address_width_enum_t2str(xed_state_get_stack_address_width(info->decoder_state)));
633
634   
635
636     memset((void*)&mem_op, '\0', sizeof(struct memory_operand));
637
638     xed_reg_enum_t xed_seg = xed_decoded_inst_get_seg_reg(xed_instr, op_index);
639     if (xed_seg != XED_REG_INVALID) {
640         struct v3_segment *tmp_segment;
641         if (xed_reg_to_v3_reg(info, xed_seg, (addr_t *)&tmp_segment, &(mem_op.segment_size)) == -1) {
642             PrintError("Unhandled Segment Register\n");
643             return -1;
644         }
645         mem_op.segment = tmp_segment->base;
646     }
647
648     xed_reg_enum_t xed_base = xed_decoded_inst_get_base_reg(xed_instr, op_index);
649     if (xed_base != XED_REG_INVALID) {
650         addr_t base_reg;
651         if (xed_reg_to_v3_reg(info, xed_base, &base_reg, &(mem_op.base_size)) == -1) {
652             PrintError("Unhandled Base register\n");
653             return -1;
654         }
655         mem_op.base = *(addr_t *)base_reg;
656     }
657
658   
659
660     xed_reg_enum_t xed_idx = xed_decoded_inst_get_index_reg(xed_instr, op_index);
661     if ((op_index == 0) && (xed_idx != XED_REG_INVALID)) {
662         addr_t index_reg;
663     
664         if (xed_reg_to_v3_reg(info, xed_idx, &index_reg, &(mem_op.index_size)) == -1) {
665             PrintError("Unhandled Index Register\n");
666             return -1;
667         }
668
669         mem_op.index= *(addr_t *)index_reg;
670
671         xed_uint_t xed_scale = xed_decoded_inst_get_scale(xed_instr, op_index);
672         if (xed_scale != 0) {
673             mem_op.scale = xed_scale;
674         }
675     }
676
677
678     xed_uint_t disp_bits = xed_decoded_inst_get_memory_displacement_width(xed_instr, op_index);
679     if (disp_bits) {
680         xed_int64_t xed_disp = xed_decoded_inst_get_memory_displacement(xed_instr, op_index);
681
682         mem_op.displacement_size = disp_bits;
683         mem_op.displacement = xed_disp;
684     }
685
686     operand->type = MEM_OPERAND;
687     operand->size = xed_decoded_inst_get_memory_operand_length(xed_instr, op_index);
688   
689   
690
691     PrintDebug("Struct: Seg=%p (size=%d), base=%p, index=%p, scale=%p, displacement=%p (size=%d)\n", 
692                (void *)mem_op.segment, mem_op.segment_size, (void*)mem_op.base, (void *)mem_op.index, 
693                (void *)mem_op.scale, (void *)(addr_t)mem_op.displacement, mem_op.displacement_size);
694
695
696     PrintDebug("operand size: %d\n", operand->size);
697
698     seg = MASK(mem_op.segment, mem_op.segment_size);
699     base = MASK(mem_op.base, mem_op.base_size);
700     index = MASK(mem_op.index, mem_op.index_size);
701     scale = mem_op.scale;
702
703     // XED returns the displacement as a 2s complement signed number, but it can
704     // have different sizes, depending on the instruction encoding.
705     // we put that into a 64 bit unsigned (the unsigned doesn't matter since
706     // we only ever do 2s complement arithmetic on it.   However, this means we
707     // need to sign-extend what XED provides through 64 bits.
708     displacement = mem_op.displacement;
709     displacement <<= 64 - mem_op.displacement_size * 8;
710     displacement = ((sllong_t)displacement) >> (64 - mem_op.displacement_size * 8);
711     
712
713     PrintDebug("Seg=%p, base=%p, index=%p, scale=%p, displacement=%p\n", 
714                (void *)seg, (void *)base, (void *)index, (void *)scale, (void *)(addr_t)displacement);
715   
716     if (cpu_mode == REAL) {
717         operand->operand = seg +  MASK((base + (scale * index) + displacement), addr_width);
718     } else {
719         operand->operand = MASK((seg + base + (scale * index) + displacement), addr_width);
720     }
721
722     return 0;
723 }
724
725
726 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) {
727
728     PrintDebug("Xed Register: %s\n", xed_reg_enum_t2str(xed_reg));
729
730     switch (xed_reg) {
731         case XED_REG_INVALID:
732             *v3_reg = 0;
733             *reg_len = 0;
734             return -1;
735
736             /* 
737              * GPRs
738              */
739         case XED_REG_RAX: 
740             *v3_reg = (addr_t)&(info->vm_regs.rax);
741             *reg_len = 8;
742             return GPR_REGISTER;
743         case XED_REG_EAX:
744             *v3_reg = (addr_t)&(info->vm_regs.rax);
745             *reg_len = 4;
746             return GPR_REGISTER;
747         case XED_REG_AX:
748             *v3_reg = (addr_t)&(info->vm_regs.rax);
749             *reg_len = 2;
750             return GPR_REGISTER;
751         case XED_REG_AH:
752             *v3_reg = (addr_t)(&(info->vm_regs.rax)) + 1;
753             *reg_len = 1;
754             return GPR_REGISTER;
755         case XED_REG_AL:
756             *v3_reg = (addr_t)&(info->vm_regs.rax);
757             *reg_len = 1;
758             return GPR_REGISTER;
759
760         case XED_REG_RCX: 
761             *v3_reg = (addr_t)&(info->vm_regs.rcx);
762             *reg_len = 8;
763             return GPR_REGISTER;
764         case XED_REG_ECX:
765             *v3_reg = (addr_t)&(info->vm_regs.rcx);
766             *reg_len = 4;
767             return GPR_REGISTER;
768         case XED_REG_CX:
769             *v3_reg = (addr_t)&(info->vm_regs.rcx);
770             *reg_len = 2;
771             return GPR_REGISTER;
772         case XED_REG_CH:
773             *v3_reg = (addr_t)(&(info->vm_regs.rcx)) + 1;
774             *reg_len = 1;
775             return GPR_REGISTER;
776         case XED_REG_CL:
777             *v3_reg = (addr_t)&(info->vm_regs.rcx);
778             *reg_len = 1;
779             return GPR_REGISTER;
780
781         case XED_REG_RDX: 
782             *v3_reg = (addr_t)&(info->vm_regs.rdx);
783             *reg_len = 8;
784             return GPR_REGISTER;
785         case XED_REG_EDX:
786             *v3_reg = (addr_t)&(info->vm_regs.rdx);
787             *reg_len = 4;
788             return GPR_REGISTER;
789         case XED_REG_DX:
790             *v3_reg = (addr_t)&(info->vm_regs.rdx);
791             *reg_len = 2;
792             return GPR_REGISTER;
793         case XED_REG_DH:
794             *v3_reg = (addr_t)(&(info->vm_regs.rdx)) + 1;
795             *reg_len = 1;
796             return GPR_REGISTER;
797         case XED_REG_DL:
798             *v3_reg = (addr_t)&(info->vm_regs.rdx);
799             *reg_len = 1;
800             return GPR_REGISTER;
801
802         case XED_REG_RBX: 
803             *v3_reg = (addr_t)&(info->vm_regs.rbx);
804             *reg_len = 8;
805             return GPR_REGISTER;
806         case XED_REG_EBX:
807             *v3_reg = (addr_t)&(info->vm_regs.rbx);
808             *reg_len = 4;
809             return GPR_REGISTER;
810         case XED_REG_BX:
811             *v3_reg = (addr_t)&(info->vm_regs.rbx);
812             *reg_len = 2;
813             return GPR_REGISTER;
814         case XED_REG_BH:
815             *v3_reg = (addr_t)(&(info->vm_regs.rbx)) + 1;
816             *reg_len = 1;
817             return GPR_REGISTER;
818         case XED_REG_BL:
819             *v3_reg = (addr_t)&(info->vm_regs.rbx);
820             *reg_len = 1;
821             return GPR_REGISTER;
822
823
824         case XED_REG_RSP:
825             *v3_reg = (addr_t)&(info->vm_regs.rsp);
826             *reg_len = 8;
827             return GPR_REGISTER;
828         case XED_REG_ESP:
829             *v3_reg = (addr_t)&(info->vm_regs.rsp);
830             *reg_len = 4;
831             return GPR_REGISTER;
832         case XED_REG_SP:
833             *v3_reg = (addr_t)&(info->vm_regs.rsp);
834             *reg_len = 2;
835             return GPR_REGISTER;
836         case XED_REG_SPL:
837             *v3_reg = (addr_t)&(info->vm_regs.rsp);
838             *reg_len = 1;
839             return GPR_REGISTER;
840
841         case XED_REG_RBP:
842             *v3_reg = (addr_t)&(info->vm_regs.rbp);
843             *reg_len = 8;
844             return GPR_REGISTER;
845         case XED_REG_EBP:
846             *v3_reg = (addr_t)&(info->vm_regs.rbp);
847             *reg_len = 4;
848             return GPR_REGISTER;
849         case XED_REG_BP:
850             *v3_reg = (addr_t)&(info->vm_regs.rbp);
851             *reg_len = 2;
852             return GPR_REGISTER;
853         case XED_REG_BPL:
854             *v3_reg = (addr_t)&(info->vm_regs.rbp);
855             *reg_len = 1;
856             return GPR_REGISTER;
857
858
859
860         case XED_REG_RSI:
861             *v3_reg = (addr_t)&(info->vm_regs.rsi);
862             *reg_len = 8;
863             return GPR_REGISTER;
864         case XED_REG_ESI:
865             *v3_reg = (addr_t)&(info->vm_regs.rsi);
866             *reg_len = 4;
867             return GPR_REGISTER;
868         case XED_REG_SI:
869             *v3_reg = (addr_t)&(info->vm_regs.rsi);
870             *reg_len = 2;
871             return GPR_REGISTER;
872         case XED_REG_SIL:
873             *v3_reg = (addr_t)&(info->vm_regs.rsi);
874             *reg_len = 1;
875             return GPR_REGISTER;
876
877
878         case XED_REG_RDI:
879             *v3_reg = (addr_t)&(info->vm_regs.rdi);
880             *reg_len = 8;
881             return GPR_REGISTER;
882         case XED_REG_EDI:
883             *v3_reg = (addr_t)&(info->vm_regs.rdi);
884             *reg_len = 4;
885             return GPR_REGISTER;
886         case XED_REG_DI:
887             *v3_reg = (addr_t)&(info->vm_regs.rdi);
888             *reg_len = 2;
889             return GPR_REGISTER;
890         case XED_REG_DIL:
891             *v3_reg = (addr_t)&(info->vm_regs.rdi);
892             *reg_len = 1;
893             return GPR_REGISTER;
894
895
896
897
898
899         case XED_REG_R8:
900             *v3_reg = (addr_t)&(info->vm_regs.r8);
901             *reg_len = 8;
902             return GPR_REGISTER;
903         case XED_REG_R8D:
904             *v3_reg = (addr_t)&(info->vm_regs.r8);
905             *reg_len = 4;
906             return GPR_REGISTER;
907         case XED_REG_R8W:
908             *v3_reg = (addr_t)&(info->vm_regs.r8);
909             *reg_len = 2;
910             return GPR_REGISTER;
911         case XED_REG_R8B:
912             *v3_reg = (addr_t)&(info->vm_regs.r8);
913             *reg_len = 1;
914             return GPR_REGISTER;
915
916         case XED_REG_R9:
917             *v3_reg = (addr_t)&(info->vm_regs.r9);
918             *reg_len = 8;
919             return GPR_REGISTER;
920         case XED_REG_R9D:
921             *v3_reg = (addr_t)&(info->vm_regs.r9);
922             *reg_len = 4;
923             return GPR_REGISTER;
924         case XED_REG_R9W:
925             *v3_reg = (addr_t)&(info->vm_regs.r9);
926             *reg_len = 2;
927             return GPR_REGISTER;
928         case XED_REG_R9B:
929             *v3_reg = (addr_t)&(info->vm_regs.r9);
930             *reg_len = 1;
931             return GPR_REGISTER;
932
933         case XED_REG_R10:
934             *v3_reg = (addr_t)&(info->vm_regs.r10);
935             *reg_len = 8;
936             return GPR_REGISTER;
937         case XED_REG_R10D:
938             *v3_reg = (addr_t)&(info->vm_regs.r10);
939             *reg_len = 4;
940             return GPR_REGISTER;
941         case XED_REG_R10W:
942             *v3_reg = (addr_t)&(info->vm_regs.r10);
943             *reg_len = 2;
944             return GPR_REGISTER;
945         case XED_REG_R10B:
946             *v3_reg = (addr_t)&(info->vm_regs.r10);
947             *reg_len = 1;
948             return GPR_REGISTER;
949
950         case XED_REG_R11:
951             *v3_reg = (addr_t)&(info->vm_regs.r11);
952             *reg_len = 8;
953             return GPR_REGISTER;
954         case XED_REG_R11D:
955             *v3_reg = (addr_t)&(info->vm_regs.r11);
956             *reg_len = 4;
957             return GPR_REGISTER;
958         case XED_REG_R11W:
959             *v3_reg = (addr_t)&(info->vm_regs.r11);
960             *reg_len = 2;
961             return GPR_REGISTER;
962         case XED_REG_R11B:
963             *v3_reg = (addr_t)&(info->vm_regs.r11);
964             *reg_len = 1;
965             return GPR_REGISTER;
966
967         case XED_REG_R12:
968             *v3_reg = (addr_t)&(info->vm_regs.r12);
969             *reg_len = 8;
970             return GPR_REGISTER;
971         case XED_REG_R12D:
972             *v3_reg = (addr_t)&(info->vm_regs.r12);
973             *reg_len = 4;
974             return GPR_REGISTER;
975         case XED_REG_R12W:
976             *v3_reg = (addr_t)&(info->vm_regs.r12);
977             *reg_len = 2;
978             return GPR_REGISTER;
979         case XED_REG_R12B:
980             *v3_reg = (addr_t)&(info->vm_regs.r12);
981             *reg_len = 1;
982             return GPR_REGISTER;
983
984         case XED_REG_R13:
985             *v3_reg = (addr_t)&(info->vm_regs.r13);
986             *reg_len = 8;
987             return GPR_REGISTER;
988         case XED_REG_R13D:
989             *v3_reg = (addr_t)&(info->vm_regs.r13);
990             *reg_len = 4;
991             return GPR_REGISTER;
992         case XED_REG_R13W:
993             *v3_reg = (addr_t)&(info->vm_regs.r13);
994             *reg_len = 2;
995             return GPR_REGISTER;
996         case XED_REG_R13B:
997             *v3_reg = (addr_t)&(info->vm_regs.r13);
998             *reg_len = 1;
999             return GPR_REGISTER;
1000
1001         case XED_REG_R14:
1002             *v3_reg = (addr_t)&(info->vm_regs.r14);
1003             *reg_len = 8;
1004             return GPR_REGISTER;
1005         case XED_REG_R14D:
1006             *v3_reg = (addr_t)&(info->vm_regs.r14);
1007             *reg_len = 4;
1008             return GPR_REGISTER;
1009         case XED_REG_R14W:
1010             *v3_reg = (addr_t)&(info->vm_regs.r14);
1011             *reg_len = 2;
1012             return GPR_REGISTER;
1013         case XED_REG_R14B:
1014             *v3_reg = (addr_t)&(info->vm_regs.r14);
1015             *reg_len = 1;
1016             return GPR_REGISTER;
1017
1018         case XED_REG_R15:
1019             *v3_reg = (addr_t)&(info->vm_regs.r15);
1020             *reg_len = 8;
1021             return GPR_REGISTER;
1022         case XED_REG_R15D:
1023             *v3_reg = (addr_t)&(info->vm_regs.r15);
1024             *reg_len = 4;
1025             return GPR_REGISTER;
1026         case XED_REG_R15W:
1027             *v3_reg = (addr_t)&(info->vm_regs.r15);
1028             *reg_len = 2;
1029             return GPR_REGISTER;
1030         case XED_REG_R15B:
1031             *v3_reg = (addr_t)&(info->vm_regs.r15);
1032             *reg_len = 1;
1033             return GPR_REGISTER;
1034
1035
1036             /* 
1037              *  CTRL REGS
1038              */
1039         case XED_REG_RIP:
1040             *v3_reg = (addr_t)&(info->rip);
1041             *reg_len = 8;
1042             return CTRL_REGISTER;
1043         case XED_REG_EIP:
1044             *v3_reg = (addr_t)&(info->rip);
1045             *reg_len = 4;
1046             return CTRL_REGISTER;  
1047         case XED_REG_IP:
1048             *v3_reg = (addr_t)&(info->rip);
1049             *reg_len = 2;
1050             return CTRL_REGISTER;
1051
1052         case XED_REG_FLAGS:
1053             *v3_reg = (addr_t)&(info->ctrl_regs.rflags);
1054             *reg_len = 2;
1055             return CTRL_REGISTER;
1056         case XED_REG_EFLAGS:
1057             *v3_reg = (addr_t)&(info->ctrl_regs.rflags);
1058             *reg_len = 4;
1059             return CTRL_REGISTER;
1060         case XED_REG_RFLAGS:
1061             *v3_reg = (addr_t)&(info->ctrl_regs.rflags);
1062             *reg_len = 8;
1063             return CTRL_REGISTER;
1064
1065         case XED_REG_CR0:
1066             *v3_reg = (addr_t)&(info->ctrl_regs.cr0);
1067             *reg_len = 4;
1068             return CTRL_REGISTER;
1069         case XED_REG_CR2:
1070             *v3_reg = (addr_t)&(info->ctrl_regs.cr2);
1071             *reg_len = 4;
1072             return CTRL_REGISTER;
1073         case XED_REG_CR3:
1074             *v3_reg = (addr_t)&(info->ctrl_regs.cr3);
1075             *reg_len = 4;
1076             return CTRL_REGISTER;
1077         case XED_REG_CR4:
1078             *v3_reg = (addr_t)&(info->ctrl_regs.cr4);
1079             *reg_len = 4;
1080             return CTRL_REGISTER;
1081         case XED_REG_CR8:
1082             *v3_reg = (addr_t)&(info->ctrl_regs.cr8);
1083             *reg_len = 4;
1084             return CTRL_REGISTER;
1085
1086         case XED_REG_CR1:
1087         case XED_REG_CR5:
1088         case XED_REG_CR6:
1089         case XED_REG_CR7:
1090         case XED_REG_CR9:
1091         case XED_REG_CR10:
1092         case XED_REG_CR11:
1093         case XED_REG_CR12:
1094         case XED_REG_CR13:
1095         case XED_REG_CR14:
1096         case XED_REG_CR15:
1097             return -1;
1098
1099
1100
1101
1102             /* 
1103              * SEGMENT REGS
1104              */
1105         case XED_REG_CS:
1106             *v3_reg = (addr_t)&(info->segments.cs);
1107             *reg_len = 8;
1108             return SEGMENT_REGISTER;
1109         case XED_REG_DS:
1110             *v3_reg = (addr_t)&(info->segments.ds);
1111             *reg_len = 8;
1112             return SEGMENT_REGISTER;
1113         case XED_REG_ES:
1114             *v3_reg = (addr_t)&(info->segments.es);
1115             *reg_len = 8;
1116             return SEGMENT_REGISTER;
1117         case XED_REG_SS:
1118             *v3_reg = (addr_t)&(info->segments.ss);
1119             *reg_len = 8;
1120             return SEGMENT_REGISTER;
1121         case XED_REG_FS:
1122             *v3_reg = (addr_t)&(info->segments.fs);
1123             *reg_len = 8;
1124             return SEGMENT_REGISTER;
1125         case XED_REG_GS:
1126             *v3_reg = (addr_t)&(info->segments.gs);
1127             *reg_len = 8;
1128             return SEGMENT_REGISTER;
1129
1130
1131         case XED_REG_GDTR:
1132         case XED_REG_LDTR:
1133         case XED_REG_IDTR:
1134         case XED_REG_TR:
1135             PrintError("Segment selector operand... Don't know how to handle this...\n");
1136             return -1;
1137
1138             /* 
1139              *  DEBUG REGS
1140              */
1141         case XED_REG_DR0:
1142         case XED_REG_DR1:
1143         case XED_REG_DR2:
1144         case XED_REG_DR3:
1145         case XED_REG_DR4:
1146         case XED_REG_DR5:
1147         case XED_REG_DR6:
1148         case XED_REG_DR7:
1149         case XED_REG_DR8:
1150         case XED_REG_DR9:
1151         case XED_REG_DR10:
1152         case XED_REG_DR11:
1153         case XED_REG_DR12:
1154         case XED_REG_DR13:
1155         case XED_REG_DR14:
1156         case XED_REG_DR15:
1157             return -1;
1158
1159
1160
1161
1162
1163
1164         case XED_REG_XMM0:
1165         case XED_REG_XMM1:
1166         case XED_REG_XMM2:
1167         case XED_REG_XMM3:
1168         case XED_REG_XMM4:
1169         case XED_REG_XMM5:
1170         case XED_REG_XMM6:
1171         case XED_REG_XMM7:
1172         case XED_REG_XMM8:
1173         case XED_REG_XMM9:
1174         case XED_REG_XMM10:
1175         case XED_REG_XMM11:
1176         case XED_REG_XMM12:
1177         case XED_REG_XMM13:
1178         case XED_REG_XMM14:
1179         case XED_REG_XMM15:
1180
1181         case XED_REG_MMX0:
1182         case XED_REG_MMX1:
1183         case XED_REG_MMX2:
1184         case XED_REG_MMX3:
1185         case XED_REG_MMX4:
1186         case XED_REG_MMX5:
1187         case XED_REG_MMX6:
1188         case XED_REG_MMX7:
1189
1190         case XED_REG_ST0:
1191         case XED_REG_ST1:
1192         case XED_REG_ST2:
1193         case XED_REG_ST3:
1194         case XED_REG_ST4:
1195         case XED_REG_ST5:
1196         case XED_REG_ST6:
1197         case XED_REG_ST7:
1198
1199         case XED_REG_ONE:
1200         case XED_REG_STACKPUSH:
1201         case XED_REG_STACKPOP:
1202     
1203         case XED_REG_TSC:
1204         case XED_REG_TSCAUX:
1205         case XED_REG_MSRS:
1206
1207         case XED_REG_X87CONTROL:
1208         case XED_REG_X87STATUS:
1209         case XED_REG_X87TOP:
1210         case XED_REG_X87TAG:
1211         case XED_REG_X87PUSH:
1212         case XED_REG_X87POP:
1213         case XED_REG_X87POP2:
1214
1215         case XED_REG_MXCSR:
1216
1217         case XED_REG_TMP0:
1218         case XED_REG_TMP1:
1219         case XED_REG_TMP2:
1220         case XED_REG_TMP3:
1221         case XED_REG_TMP4:
1222         case XED_REG_TMP5:
1223         case XED_REG_TMP6:
1224         case XED_REG_TMP7:
1225         case XED_REG_TMP8:
1226         case XED_REG_TMP9:
1227         case XED_REG_TMP10:
1228         case XED_REG_TMP11:
1229         case XED_REG_TMP12:
1230         case XED_REG_TMP13:
1231         case XED_REG_TMP14:
1232         case XED_REG_TMP15:
1233
1234         case XED_REG_LAST:
1235
1236         case XED_REG_ERROR:
1237             // error??
1238             return -1;
1239
1240     }
1241
1242
1243     return 0;
1244 }
1245
1246
1247
1248 static v3_op_type_t get_opcode(xed_iform_enum_t iform) {
1249
1250     switch (iform) {
1251
1252         /* Control Instructions */
1253
1254         case XED_IFORM_MOV_CR_GPR64_CR:
1255         case XED_IFORM_MOV_CR_GPR32_CR:
1256             return V3_OP_MOVCR2;
1257
1258         case XED_IFORM_MOV_CR_CR_GPR64:
1259         case XED_IFORM_MOV_CR_CR_GPR32:
1260             return V3_OP_MOV2CR;
1261
1262         case XED_IFORM_SMSW_GPRv:
1263             return V3_OP_SMSW;
1264
1265         case XED_IFORM_LMSW_GPR16:
1266             return V3_OP_LMSW;
1267
1268         case XED_IFORM_CLTS:
1269             return V3_OP_CLTS;
1270
1271         case XED_IFORM_INVLPG_MEMb:
1272             return V3_OP_INVLPG;
1273
1274
1275             /* Data Instructions */
1276
1277             // Write
1278         case XED_IFORM_ADC_MEMv_GPRv:
1279         case XED_IFORM_ADC_MEMv_IMM:
1280         case XED_IFORM_ADC_MEMb_GPR8:
1281         case XED_IFORM_ADC_MEMb_IMM:
1282             // Read
1283         case XED_IFORM_ADC_GPRv_MEMv:
1284         case XED_IFORM_ADC_GPR8_MEMb:
1285             return V3_OP_ADC;
1286
1287             // Write
1288         case XED_IFORM_ADD_MEMv_GPRv:
1289         case XED_IFORM_ADD_MEMb_IMM:
1290         case XED_IFORM_ADD_MEMb_GPR8:
1291         case XED_IFORM_ADD_MEMv_IMM:
1292             // Read
1293         case XED_IFORM_ADD_GPRv_MEMv:
1294         case XED_IFORM_ADD_GPR8_MEMb:
1295             return V3_OP_ADD;
1296
1297             // Write
1298         case XED_IFORM_AND_MEMv_IMM:
1299         case XED_IFORM_AND_MEMb_GPR8:
1300         case XED_IFORM_AND_MEMv_GPRv:
1301         case XED_IFORM_AND_MEMb_IMM:
1302             // Read
1303         case XED_IFORM_AND_GPR8_MEMb:
1304         case XED_IFORM_AND_GPRv_MEMv:
1305             return V3_OP_AND;
1306
1307             // Write
1308         case XED_IFORM_SUB_MEMv_IMM:
1309         case XED_IFORM_SUB_MEMb_GPR8:
1310         case XED_IFORM_SUB_MEMb_IMM:
1311         case XED_IFORM_SUB_MEMv_GPRv:
1312             // Read
1313         case XED_IFORM_SUB_GPR8_MEMb:
1314         case XED_IFORM_SUB_GPRv_MEMv:
1315             return V3_OP_SUB;
1316
1317             // Write
1318         case XED_IFORM_MOV_MEMv_GPRv:
1319         case XED_IFORM_MOV_MEMb_GPR8:
1320         case XED_IFORM_MOV_MEMv_OrAX:
1321         case XED_IFORM_MOV_MEMb_AL:
1322         case XED_IFORM_MOV_MEMv_IMM:
1323         case XED_IFORM_MOV_MEMb_IMM:
1324             // Read 
1325         case XED_IFORM_MOV_GPRv_MEMv:
1326         case XED_IFORM_MOV_GPR8_MEMb:
1327         case XED_IFORM_MOV_OrAX_MEMv:
1328         case XED_IFORM_MOV_AL_MEMb:
1329             return V3_OP_MOV;
1330
1331
1332             // Read 
1333         case XED_IFORM_MOVZX_GPRv_MEMb:
1334         case XED_IFORM_MOVZX_GPRv_MEMw:
1335             return V3_OP_MOVZX;
1336
1337             // Read 
1338         case XED_IFORM_MOVSX_GPRv_MEMb:
1339         case XED_IFORM_MOVSX_GPRv_MEMw:
1340             return V3_OP_MOVSX;
1341
1342
1343
1344         case XED_IFORM_DEC_MEMv:
1345         case XED_IFORM_DEC_MEMb:
1346             return V3_OP_DEC;
1347
1348         case XED_IFORM_INC_MEMb:
1349         case XED_IFORM_INC_MEMv:
1350             return V3_OP_INC;
1351
1352             // Write
1353         case XED_IFORM_OR_MEMv_IMM:
1354         case XED_IFORM_OR_MEMb_IMM:
1355         case XED_IFORM_OR_MEMv_GPRv:
1356         case XED_IFORM_OR_MEMb_GPR8:
1357             // Read
1358         case XED_IFORM_OR_GPRv_MEMv:
1359         case XED_IFORM_OR_GPR8_MEMb:
1360             return V3_OP_OR;
1361
1362             // Write
1363         case XED_IFORM_XOR_MEMv_GPRv:
1364         case XED_IFORM_XOR_MEMb_IMM:
1365         case XED_IFORM_XOR_MEMb_GPR8:
1366         case XED_IFORM_XOR_MEMv_IMM:
1367             // Read
1368         case XED_IFORM_XOR_GPRv_MEMv:
1369         case XED_IFORM_XOR_GPR8_MEMb:
1370             return V3_OP_XOR;
1371
1372         case XED_IFORM_NEG_MEMb:
1373         case XED_IFORM_NEG_MEMv:
1374             return V3_OP_NEG;
1375
1376         case XED_IFORM_NOT_MEMv:
1377         case XED_IFORM_NOT_MEMb:
1378             return V3_OP_NOT;
1379
1380         case XED_IFORM_XCHG_MEMv_GPRv:
1381         case XED_IFORM_XCHG_MEMb_GPR8:
1382             return V3_OP_XCHG;
1383
1384         case XED_IFORM_SETB_MEMb:
1385             return V3_OP_SETB;
1386
1387         case XED_IFORM_SETBE_MEMb:
1388             return V3_OP_SETBE;
1389
1390         case XED_IFORM_SETL_MEMb:
1391             return V3_OP_SETL;
1392
1393         case XED_IFORM_SETLE_MEMb:
1394             return V3_OP_SETLE;
1395
1396         case XED_IFORM_SETNB_MEMb:
1397             return V3_OP_SETNB;
1398
1399         case XED_IFORM_SETNBE_MEMb:
1400             return V3_OP_SETNBE;
1401
1402         case XED_IFORM_SETNL_MEMb:
1403             return V3_OP_SETNL;
1404
1405         case XED_IFORM_SETNLE_MEMb:
1406             return V3_OP_SETNLE;
1407
1408         case XED_IFORM_SETNO_MEMb:
1409             return V3_OP_SETNO;
1410     
1411         case XED_IFORM_SETNP_MEMb:
1412             return V3_OP_SETNP;
1413
1414         case XED_IFORM_SETNS_MEMb:
1415             return V3_OP_SETNS;
1416
1417         case XED_IFORM_SETNZ_MEMb:
1418             return V3_OP_SETNZ;
1419
1420         case XED_IFORM_SETO_MEMb:
1421             return V3_OP_SETO;
1422     
1423         case XED_IFORM_SETP_MEMb:
1424             return V3_OP_SETP;
1425
1426         case XED_IFORM_SETS_MEMb:
1427             return V3_OP_SETS;
1428
1429         case XED_IFORM_SETZ_MEMb:
1430             return V3_OP_SETZ;
1431
1432         case XED_IFORM_MOVSB:
1433         case XED_IFORM_MOVSW:
1434         case XED_IFORM_MOVSD:
1435         case XED_IFORM_MOVSQ:
1436             return V3_OP_MOVS;
1437
1438         case XED_IFORM_STOSB:
1439         case XED_IFORM_STOSW:
1440         case XED_IFORM_STOSD:
1441         case XED_IFORM_STOSQ:
1442             return V3_OP_STOS;
1443
1444
1445         default:
1446             return V3_INVALID_OP;
1447     }
1448 }