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.


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