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.


1b783f007ad4a6ad56c4afb973eb577e72277394
[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             *v3_reg = (addr_t)&(info->ctrl_regs.apic_tpr);
1101             *reg_len = 4;
1102             return CTRL_REGISTER;
1103
1104         case XED_REG_CR1:
1105         case XED_REG_CR5:
1106         case XED_REG_CR6:
1107         case XED_REG_CR7:
1108         case XED_REG_CR9:
1109         case XED_REG_CR10:
1110         case XED_REG_CR11:
1111         case XED_REG_CR12:
1112         case XED_REG_CR13:
1113         case XED_REG_CR14:
1114         case XED_REG_CR15:
1115             return -1;
1116
1117
1118
1119
1120             /* 
1121              * SEGMENT REGS
1122              */
1123         case XED_REG_CS:
1124             *v3_reg = (addr_t)&(info->segments.cs);
1125             *reg_len = 8;
1126             return SEGMENT_REGISTER;
1127         case XED_REG_DS:
1128             *v3_reg = (addr_t)&(info->segments.ds);
1129             *reg_len = 8;
1130             return SEGMENT_REGISTER;
1131         case XED_REG_ES:
1132             *v3_reg = (addr_t)&(info->segments.es);
1133             *reg_len = 8;
1134             return SEGMENT_REGISTER;
1135         case XED_REG_SS:
1136             *v3_reg = (addr_t)&(info->segments.ss);
1137             *reg_len = 8;
1138             return SEGMENT_REGISTER;
1139         case XED_REG_FS:
1140             *v3_reg = (addr_t)&(info->segments.fs);
1141             *reg_len = 8;
1142             return SEGMENT_REGISTER;
1143         case XED_REG_GS:
1144             *v3_reg = (addr_t)&(info->segments.gs);
1145             *reg_len = 8;
1146             return SEGMENT_REGISTER;
1147
1148
1149         case XED_REG_GDTR:
1150         case XED_REG_LDTR:
1151         case XED_REG_IDTR:
1152         case XED_REG_TR:
1153             PrintError(info->vm_info, info, "Segment selector operand... Don't know how to handle this...\n");
1154             return -1;
1155
1156             /* 
1157              *  DEBUG REGS
1158              */
1159         case XED_REG_DR0:
1160         case XED_REG_DR1:
1161         case XED_REG_DR2:
1162         case XED_REG_DR3:
1163         case XED_REG_DR4:
1164         case XED_REG_DR5:
1165         case XED_REG_DR6:
1166         case XED_REG_DR7:
1167         case XED_REG_DR8:
1168         case XED_REG_DR9:
1169         case XED_REG_DR10:
1170         case XED_REG_DR11:
1171         case XED_REG_DR12:
1172         case XED_REG_DR13:
1173         case XED_REG_DR14:
1174         case XED_REG_DR15:
1175             return -1;
1176
1177
1178
1179
1180
1181
1182         case XED_REG_XMM0:
1183         case XED_REG_XMM1:
1184         case XED_REG_XMM2:
1185         case XED_REG_XMM3:
1186         case XED_REG_XMM4:
1187         case XED_REG_XMM5:
1188         case XED_REG_XMM6:
1189         case XED_REG_XMM7:
1190         case XED_REG_XMM8:
1191         case XED_REG_XMM9:
1192         case XED_REG_XMM10:
1193         case XED_REG_XMM11:
1194         case XED_REG_XMM12:
1195         case XED_REG_XMM13:
1196         case XED_REG_XMM14:
1197         case XED_REG_XMM15:
1198
1199         case XED_REG_MMX0:
1200         case XED_REG_MMX1:
1201         case XED_REG_MMX2:
1202         case XED_REG_MMX3:
1203         case XED_REG_MMX4:
1204         case XED_REG_MMX5:
1205         case XED_REG_MMX6:
1206         case XED_REG_MMX7:
1207
1208         case XED_REG_ST0:
1209         case XED_REG_ST1:
1210         case XED_REG_ST2:
1211         case XED_REG_ST3:
1212         case XED_REG_ST4:
1213         case XED_REG_ST5:
1214         case XED_REG_ST6:
1215         case XED_REG_ST7:
1216
1217         case XED_REG_ONE:
1218         case XED_REG_STACKPUSH:
1219         case XED_REG_STACKPOP:
1220     
1221         case XED_REG_TSC:
1222         case XED_REG_TSCAUX:
1223         case XED_REG_MSRS:
1224
1225         case XED_REG_X87CONTROL:
1226         case XED_REG_X87STATUS:
1227         case XED_REG_X87TOP:
1228         case XED_REG_X87TAG:
1229         case XED_REG_X87PUSH:
1230         case XED_REG_X87POP:
1231         case XED_REG_X87POP2:
1232
1233         case XED_REG_MXCSR:
1234
1235         case XED_REG_TMP0:
1236         case XED_REG_TMP1:
1237         case XED_REG_TMP2:
1238         case XED_REG_TMP3:
1239         case XED_REG_TMP4:
1240         case XED_REG_TMP5:
1241         case XED_REG_TMP6:
1242         case XED_REG_TMP7:
1243         case XED_REG_TMP8:
1244         case XED_REG_TMP9:
1245         case XED_REG_TMP10:
1246         case XED_REG_TMP11:
1247         case XED_REG_TMP12:
1248         case XED_REG_TMP13:
1249         case XED_REG_TMP14:
1250         case XED_REG_TMP15:
1251
1252         case XED_REG_LAST:
1253
1254         case XED_REG_ERROR:
1255             // error??
1256             return -1;
1257
1258     }
1259
1260
1261     return 0;
1262 }
1263
1264
1265
1266 static v3_op_type_t get_opcode(xed_iform_enum_t iform) {
1267
1268     switch (iform) {
1269
1270         /* Control Instructions */
1271
1272         case XED_IFORM_MOV_CR_GPR64_CR:
1273         case XED_IFORM_MOV_CR_GPR32_CR:
1274             return V3_OP_MOVCR2;
1275
1276         case XED_IFORM_MOV_CR_CR_GPR64:
1277         case XED_IFORM_MOV_CR_CR_GPR32:
1278             return V3_OP_MOV2CR;
1279
1280         case XED_IFORM_SMSW_GPRv:
1281             return V3_OP_SMSW;
1282
1283         case XED_IFORM_LMSW_GPR16:
1284             return V3_OP_LMSW;
1285
1286         case XED_IFORM_CLTS:
1287             return V3_OP_CLTS;
1288
1289         case XED_IFORM_INVLPG_MEMb:
1290             return V3_OP_INVLPG;
1291
1292     case XED_IFORM_INT_IMM:
1293         return V3_OP_INT;
1294
1295
1296             /* Data Instructions */
1297
1298             // Write
1299         case XED_IFORM_ADC_MEMv_GPRv:
1300         case XED_IFORM_ADC_MEMv_IMM:
1301         case XED_IFORM_ADC_MEMb_GPR8:
1302         case XED_IFORM_ADC_MEMb_IMM:
1303             // Read
1304         case XED_IFORM_ADC_GPRv_MEMv:
1305         case XED_IFORM_ADC_GPR8_MEMb:
1306             return V3_OP_ADC;
1307
1308             // Write
1309         case XED_IFORM_ADD_MEMv_GPRv:
1310         case XED_IFORM_ADD_MEMb_IMM:
1311         case XED_IFORM_ADD_MEMb_GPR8:
1312         case XED_IFORM_ADD_MEMv_IMM:
1313             // Read
1314         case XED_IFORM_ADD_GPRv_MEMv:
1315         case XED_IFORM_ADD_GPR8_MEMb:
1316             return V3_OP_ADD;
1317
1318             // Write
1319         case XED_IFORM_AND_MEMv_IMM:
1320         case XED_IFORM_AND_MEMb_GPR8:
1321         case XED_IFORM_AND_MEMv_GPRv:
1322         case XED_IFORM_AND_MEMb_IMM:
1323             // Read
1324         case XED_IFORM_AND_GPR8_MEMb:
1325         case XED_IFORM_AND_GPRv_MEMv:
1326             return V3_OP_AND;
1327
1328             // Write
1329         case XED_IFORM_SUB_MEMv_IMM:
1330         case XED_IFORM_SUB_MEMb_GPR8:
1331         case XED_IFORM_SUB_MEMb_IMM:
1332         case XED_IFORM_SUB_MEMv_GPRv:
1333             // Read
1334         case XED_IFORM_SUB_GPR8_MEMb:
1335         case XED_IFORM_SUB_GPRv_MEMv:
1336             return V3_OP_SUB;
1337
1338             // Write
1339         case XED_IFORM_MOV_MEMv_GPRv:
1340         case XED_IFORM_MOV_MEMb_GPR8:
1341         case XED_IFORM_MOV_MEMv_OrAX:
1342         case XED_IFORM_MOV_MEMb_AL:
1343         case XED_IFORM_MOV_MEMv_IMM:
1344         case XED_IFORM_MOV_MEMb_IMM:
1345             // Read 
1346         case XED_IFORM_MOV_GPRv_MEMv:
1347         case XED_IFORM_MOV_GPR8_MEMb:
1348         case XED_IFORM_MOV_OrAX_MEMv:
1349         case XED_IFORM_MOV_AL_MEMb:
1350             return V3_OP_MOV;
1351
1352
1353             // Read 
1354         case XED_IFORM_MOVZX_GPRv_MEMb:
1355         case XED_IFORM_MOVZX_GPRv_MEMw:
1356             return V3_OP_MOVZX;
1357
1358             // Read 
1359         case XED_IFORM_MOVSX_GPRv_MEMb:
1360         case XED_IFORM_MOVSX_GPRv_MEMw:
1361             return V3_OP_MOVSX;
1362
1363
1364
1365         case XED_IFORM_DEC_MEMv:
1366         case XED_IFORM_DEC_MEMb:
1367             return V3_OP_DEC;
1368
1369         case XED_IFORM_INC_MEMb:
1370         case XED_IFORM_INC_MEMv:
1371             return V3_OP_INC;
1372
1373             // Write
1374         case XED_IFORM_OR_MEMv_IMM:
1375         case XED_IFORM_OR_MEMb_IMM:
1376         case XED_IFORM_OR_MEMv_GPRv:
1377         case XED_IFORM_OR_MEMb_GPR8:
1378             // Read
1379         case XED_IFORM_OR_GPRv_MEMv:
1380         case XED_IFORM_OR_GPR8_MEMb:
1381             return V3_OP_OR;
1382
1383             // Write
1384         case XED_IFORM_XOR_MEMv_GPRv:
1385         case XED_IFORM_XOR_MEMb_IMM:
1386         case XED_IFORM_XOR_MEMb_GPR8:
1387         case XED_IFORM_XOR_MEMv_IMM:
1388             // Read
1389         case XED_IFORM_XOR_GPRv_MEMv:
1390         case XED_IFORM_XOR_GPR8_MEMb:
1391             return V3_OP_XOR;
1392
1393         case XED_IFORM_NEG_MEMb:
1394         case XED_IFORM_NEG_MEMv:
1395             return V3_OP_NEG;
1396
1397         case XED_IFORM_NOT_MEMv:
1398         case XED_IFORM_NOT_MEMb:
1399             return V3_OP_NOT;
1400
1401         case XED_IFORM_XCHG_MEMv_GPRv:
1402         case XED_IFORM_XCHG_MEMb_GPR8:
1403             return V3_OP_XCHG;
1404
1405         case XED_IFORM_SETB_MEMb:
1406             return V3_OP_SETB;
1407
1408         case XED_IFORM_SETBE_MEMb:
1409             return V3_OP_SETBE;
1410
1411         case XED_IFORM_SETL_MEMb:
1412             return V3_OP_SETL;
1413
1414         case XED_IFORM_SETLE_MEMb:
1415             return V3_OP_SETLE;
1416
1417         case XED_IFORM_SETNB_MEMb:
1418             return V3_OP_SETNB;
1419
1420         case XED_IFORM_SETNBE_MEMb:
1421             return V3_OP_SETNBE;
1422
1423         case XED_IFORM_SETNL_MEMb:
1424             return V3_OP_SETNL;
1425
1426         case XED_IFORM_SETNLE_MEMb:
1427             return V3_OP_SETNLE;
1428
1429         case XED_IFORM_SETNO_MEMb:
1430             return V3_OP_SETNO;
1431     
1432         case XED_IFORM_SETNP_MEMb:
1433             return V3_OP_SETNP;
1434
1435         case XED_IFORM_SETNS_MEMb:
1436             return V3_OP_SETNS;
1437
1438         case XED_IFORM_SETNZ_MEMb:
1439             return V3_OP_SETNZ;
1440
1441         case XED_IFORM_SETO_MEMb:
1442             return V3_OP_SETO;
1443     
1444         case XED_IFORM_SETP_MEMb:
1445             return V3_OP_SETP;
1446
1447         case XED_IFORM_SETS_MEMb:
1448             return V3_OP_SETS;
1449
1450         case XED_IFORM_SETZ_MEMb:
1451             return V3_OP_SETZ;
1452
1453         case XED_IFORM_MOVSB:
1454         case XED_IFORM_MOVSW:
1455         case XED_IFORM_MOVSD:
1456         case XED_IFORM_MOVSQ:
1457             return V3_OP_MOVS;
1458
1459         case XED_IFORM_STOSB:
1460         case XED_IFORM_STOSW:
1461         case XED_IFORM_STOSD:
1462         case XED_IFORM_STOSQ:
1463             return V3_OP_STOS;
1464
1465
1466         default:
1467             return V3_INVALID_OP;
1468     }
1469 }