Palacios Public Git Repository

To checkout Palacios execute

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


decoder fixes
[palacios.git] / palacios / include / palacios / vmm_instr_decoder.h
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 #include <palacios/vmm_types.h>
21
22 /* .... Giant fucking switch tables */
23
24
25 typedef enum {
26     INVALID_INSTR,
27     LMSW,
28     SMSW,
29     CLTS,
30     INVLPG,
31     INT, 
32
33     MOV_CR2,
34     MOV_2CR,
35     MOV_DR2,
36     MOV_2DR,
37     MOV_SR2,
38     MOV_2SR,
39
40     MOV_MEM2_8,
41     MOV_MEM2,
42     MOV_2MEM_8,
43     MOV_2MEM,
44     MOV_MEM2AL_8,
45     MOV_MEM2AX,
46     MOV_AL2MEM_8,
47     MOV_AX2MEM,
48     MOV_IMM2_8,
49     MOV_IMM2,
50
51     MOVS_8,
52     MOVS,
53     MOVSX_8,
54     MOVSX,
55     MOVZX_8,
56     MOVZX,
57
58     HLT,
59     PUSHF,
60     POPF,
61
62     ADC_2MEM_8,
63     ADC_2MEM,
64     ADC_MEM2_8,
65     ADC_MEM2,
66     ADC_IMM2_8,
67     ADC_IMM2,
68     ADC_IMM2SX_8,
69     ADD_IMM2_8,
70     ADD_IMM2,
71     ADD_IMM2SX_8,
72     ADD_2MEM_8,
73     ADD_2MEM,
74     ADD_MEM2_8,
75     ADD_MEM2,
76     AND_MEM2_8,
77     AND_MEM2,
78     AND_2MEM_8,
79     AND_2MEM,
80     AND_IMM2_8,
81     AND_IMM2,
82     AND_IMM2SX_8,
83     OR_2MEM_8,
84     OR_2MEM,
85     OR_MEM2_8,
86     OR_MEM2,
87     OR_IMM2_8,
88     OR_IMM2,
89     OR_IMM2SX_8,
90     SUB_2MEM_8,
91     SUB_2MEM,
92     SUB_MEM2_8,
93     SUB_MEM2,
94     SUB_IMM2_8,
95     SUB_IMM2,
96     SUB_IMM2SX_8,
97     XOR_2MEM_8,
98     XOR_2MEM,
99     XOR_MEM2_8,
100     XOR_MEM2,
101     XOR_IMM2_8,
102     XOR_IMM2,
103     XOR_IMM2SX_8,
104
105     INC_8,
106     INC,
107     DEC_8,
108     DEC,
109     NEG_8,
110     NEG, 
111     NOT_8,
112     NOT,
113     XCHG_8,
114     XCHG,
115
116     SETB,
117     SETBE,
118     SETL,
119     SETLE,
120     SETNB,
121     SETNBE,
122     SETNL,
123     SETNLE,
124     SETNO,
125     SETNP,
126     SETNS,
127     SETNZ,
128     SETP,
129     SETS,
130     SETZ,
131     SETO,
132
133     STOS_8,
134     STOS
135 } op_form_t;
136
137
138 static int get_addr_width(struct guest_info * info, struct x86_instr * instr) {
139
140     switch (v3_get_vm_cpu_mode(info)) {
141         case REAL:
142             return (instr->prefixes.addr_size) ? 4 : 2;
143         case LONG:
144                 return 8;
145         case PROTECTED:
146         case PROTECTED_PAE:
147         case LONG_32_COMPAT:
148                 if (info->segments.cs.db) {
149                         return (instr->prefixes.addr_size) ? 2 : 4;
150                 } else {
151                         return (instr->prefixes.addr_size) ? 4 : 2;
152                 }                       
153         default:
154             PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
155             return -1;
156     }
157 }
158
159 static int get_operand_width(struct guest_info * info, struct x86_instr * instr, 
160                              op_form_t form) {
161     switch (form) {
162
163         case CLTS:
164         case HLT:
165             return 0;
166
167         case MOV_MEM2_8:
168         case MOV_2MEM_8:
169         case MOV_MEM2AL_8:
170         case MOV_AL2MEM_8:
171         case MOV_IMM2_8:
172         case MOVS_8:
173         case MOVSX_8:
174         case MOVZX_8:
175         case ADC_2MEM_8:
176         case ADC_MEM2_8:
177         case ADC_IMM2_8:
178         case ADD_IMM2_8:
179         case ADD_2MEM_8:
180         case ADD_MEM2_8:
181         case AND_MEM2_8:
182         case AND_2MEM_8:
183         case AND_IMM2_8:
184         case OR_2MEM_8:
185         case OR_MEM2_8:
186         case OR_IMM2_8:
187         case SUB_2MEM_8:
188         case XOR_2MEM_8:
189         case SUB_MEM2_8:
190         case SUB_IMM2_8:
191         case XOR_MEM2_8:
192         case XOR_IMM2_8:
193         case INC_8:
194         case DEC_8:
195         case NEG_8:
196         case NOT_8:
197         case XCHG_8:
198         case STOS_8:
199         case SETB:
200         case SETBE:
201         case SETL:
202         case SETLE:
203         case SETNB:
204         case SETNBE:
205         case SETNL:
206         case SETNLE:
207         case SETNO:
208         case SETNP:
209         case SETNS:
210         case SETNZ:
211         case SETP:
212         case SETS:
213         case SETZ:
214         case SETO:
215             return 1;
216
217         case LMSW:
218         case SMSW:
219             return 2;
220
221         case MOV_MEM2:
222         case MOV_2MEM:
223         case MOV_MEM2AX:
224         case MOV_AX2MEM: 
225         case MOVS:
226         case MOVSX:
227         case MOVZX:
228         case ADC_2MEM:
229         case ADC_MEM2:
230         case ADC_IMM2:
231         case ADD_IMM2:
232         case ADD_2MEM:
233         case ADD_MEM2:
234         case AND_MEM2:
235         case AND_2MEM:
236         case AND_IMM2:
237         case OR_2MEM:
238         case OR_MEM2:
239         case OR_IMM2:
240         case SUB_2MEM:
241         case SUB_MEM2:
242         case SUB_IMM2:
243         case XOR_2MEM:
244         case XOR_MEM2:
245         case XOR_IMM2:
246         case INC:
247         case DEC:
248         case NEG: 
249         case NOT:
250         case STOS:
251         case XCHG:
252         case ADC_IMM2SX_8:
253         case AND_IMM2SX_8:
254         case ADD_IMM2SX_8:
255         case OR_IMM2SX_8:
256         case SUB_IMM2SX_8:
257         case XOR_IMM2SX_8:
258         case MOV_IMM2:
259             switch (v3_get_vm_cpu_mode(info)) {
260                 case REAL:
261                     return (instr->prefixes.op_size) ? 4 : 2;
262                 case LONG:
263                     if (instr->prefixes.rex_op_size) {
264                         return 8;
265                     } else {
266                         return (instr->prefixes.op_size) ? 2 : 4;
267                     }
268                 case PROTECTED:
269                 case PROTECTED_PAE:
270                 case LONG_32_COMPAT:
271                     if (info->segments.cs.db) {
272                         // default is 32
273                         return (instr->prefixes.op_size) ? 2 : 4;
274                     } else {
275                         return (instr->prefixes.op_size) ? 4 : 2;
276                     }
277                 default:
278                     PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
279                     return -1;
280             }
281         case INVLPG:
282             switch (v3_get_vm_cpu_mode(info)) {
283                 case REAL:
284                     PrintError("Invalid instruction given operating mode (%d)\n", form);
285                     return 0;
286                 case PROTECTED:
287                 case PROTECTED_PAE:
288                 case LONG_32_COMPAT:
289                         return 4;
290                 case LONG:
291                         return 8;
292                 default:
293                     PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
294                     return -1;
295             }
296
297         case PUSHF:
298         case POPF:
299             switch (v3_get_vm_cpu_mode(info)) {
300                 case REAL:
301                     return 2;
302                 case PROTECTED:
303                 case PROTECTED_PAE:
304                 case LONG_32_COMPAT:
305                         return 4;
306                 case LONG:
307                         return 8;
308                 default:
309                     PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
310                     return -1;
311             }
312
313         case INT:
314         case MOV_DR2:
315         case MOV_2DR:
316         case MOV_CR2:
317         case MOV_2CR:
318             switch (v3_get_vm_cpu_mode(info)) {
319                 case REAL:
320                 case PROTECTED:
321                 case PROTECTED_PAE:
322                 case LONG_32_COMPAT:
323
324                         return 4;
325                 case LONG:
326                         return 8;
327                 default:
328                     PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
329                     return -1;
330             }
331
332         case MOV_SR2:
333         case MOV_2SR:
334         default:
335             PrintError("Unsupported instruction form %d\n", form);
336             return -1;
337         
338     }
339
340     return 0;
341 }
342
343
344
345 typedef enum {INVALID_ADDR_TYPE, REG, DISP0, DISP8, DISP16, DISP32} modrm_mode_t;
346 typedef enum {INVALID_REG_SIZE, REG64, REG32, REG16, REG8} reg_size_t;
347
348
349 struct modrm_byte {
350     uint_t rm   :   3;
351     uint_t reg  :   3;
352     uint_t mod  :   2;
353 } __attribute__((packed));
354
355
356 struct sib_byte {
357     uint_t base     :   3;
358     uint_t index    :   3;
359     uint_t scale    :   2;
360 } __attribute__((packed));
361
362
363
364
365 struct v3_gprs;
366
367 static inline int decode_gpr(struct guest_info * core,
368                              uint8_t reg_code,
369                              struct x86_operand * reg) {
370
371     struct v3_gprs * gprs = &(core->vm_regs);
372
373     switch (reg_code) {
374         case 0:
375             reg->operand = (addr_t)&(gprs->rax);
376             break;
377         case 1:
378             reg->operand = (addr_t)&(gprs->rcx);
379             break;
380         case 2:
381             reg->operand = (addr_t)&(gprs->rdx);
382             break;
383         case 3:
384             reg->operand = (addr_t)&(gprs->rbx);
385             break;
386         case 4:
387             if (reg->size == 1) {
388                 reg->operand = (addr_t)&(gprs->rax) + 1;
389             } else {
390                 reg->operand = (addr_t)&(gprs->rsp);
391             }
392             break;
393         case 5:
394             if (reg->size == 1) {
395                 reg->operand = (addr_t)&(gprs->rcx) + 1;
396             } else {
397                 reg->operand = (addr_t)&(gprs->rbp);
398             }
399             break;
400         case 6:
401             if (reg->size == 1) {
402                 reg->operand = (addr_t)&(gprs->rdx) + 1;
403             } else {
404                 reg->operand = (addr_t)&(gprs->rsi);
405             }
406             break;
407         case 7:
408             if (reg->size == 1) {
409                 reg->operand = (addr_t)&(gprs->rbx) + 1;
410             } else {
411                 reg->operand = (addr_t)&(gprs->rdi);
412             }
413             break;
414         case 8:
415             reg->operand = (addr_t)&(gprs->r8);
416             break;
417         case 9:
418             reg->operand = (addr_t)&(gprs->r9);
419             break;
420         case 10:
421             reg->operand = (addr_t)&(gprs->r10);
422             break;
423         case 11:
424             reg->operand = (addr_t)&(gprs->r11);
425             break;
426         case 12:
427             reg->operand = (addr_t)&(gprs->r12);
428             break;
429         case 13:
430             reg->operand = (addr_t)&(gprs->r13);
431             break;
432         case 14:
433             reg->operand = (addr_t)&(gprs->r14);
434             break;
435         case 15:
436             reg->operand = (addr_t)&(gprs->r15);
437             break;
438         default:
439             PrintError("Invalid Reg Code (%d)\n", reg_code);
440             reg->operand = 0;
441             return -1;
442     }
443
444     return 0;
445 }
446
447
448
449
450 static inline int decode_cr(struct guest_info * core,                   
451                              uint8_t reg_code,
452                              struct x86_operand * reg) {
453
454     struct v3_ctrl_regs * crs = &(core->ctrl_regs);
455
456 //    PrintDebug("\t Ctrl regs %d\n", reg_code);
457
458     switch (reg_code) {
459         case 0:
460             reg->operand = (addr_t)&(crs->cr0);
461             break;
462         case 2:
463             reg->operand = (addr_t)&(crs->cr2);
464             break;
465         case 3:
466             reg->operand = (addr_t)&(crs->cr3);
467             break;
468         case 4:
469             reg->operand = (addr_t)&(crs->cr4);
470             break;
471         default:
472             reg->operand = 0;
473             PrintError("Invalid Reg Code (%d)\n", reg_code);
474             return -1;
475     }
476
477     return 0;
478 }
479
480
481
482 #define ADDR_MASK(val, length) ({                             \
483             ullong_t mask = 0x0LL;                            \
484             switch (length) {                                 \
485                 case 2:                                       \
486                     mask = 0x00000000000fffffLL;              \
487                     break;                                    \
488                 case 4:                                       \
489                     mask = 0x00000000ffffffffLL;              \
490                     break;                                    \
491                 case 8:                                       \
492                     mask = 0xffffffffffffffffLL;              \
493                     break;                                    \
494             }                                                 \
495             val & mask;                                       \
496         })
497
498
499
500 static  int decode_rm_operand16(struct guest_info * core,
501                                 uint8_t * modrm_instr, 
502                                 struct x86_instr * instr,
503                                 struct x86_operand * operand, 
504                                 uint8_t * reg_code) { 
505
506     struct v3_gprs * gprs = &(core->vm_regs);
507     struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
508     addr_t base_addr = 0;
509     modrm_mode_t mod_mode = 0;
510     uint8_t * instr_cursor = modrm_instr;
511
512     //  PrintDebug("ModRM mod=%d\n", modrm->mod);
513     
514     *reg_code = modrm->reg;
515
516     instr_cursor += 1;
517
518     if (modrm->mod == 3) {
519         //PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
520         operand->type = REG_OPERAND;
521
522         decode_gpr(core, modrm->rm, operand);
523
524     } else {
525         struct v3_segment * seg = NULL;
526
527         operand->type = MEM_OPERAND;
528
529         if (modrm->mod == 0) {
530             mod_mode = DISP0;
531         } else if (modrm->mod == 1) {
532             mod_mode = DISP8;
533         } else if (modrm->mod == 2) {
534             mod_mode = DISP16;
535         } else {
536             PrintError("Instruction format error: Invalid mod_rm mode (%d)\n", modrm->mod);
537             v3_print_instr(instr);
538             return -1;
539         }
540
541         switch (modrm->rm) {
542             case 0:
543                 base_addr = gprs->rbx + ADDR_MASK(gprs->rsi, 2);
544                 break;
545             case 1:
546                 base_addr = gprs->rbx + ADDR_MASK(gprs->rdi, 2);
547                 break;
548             case 2:
549                 base_addr = gprs->rbp + ADDR_MASK(gprs->rsi, 2);
550                 break;
551             case 3:
552                 base_addr = gprs->rbp + ADDR_MASK(gprs->rdi, 2);
553                 break;
554             case 4:
555                 base_addr = ADDR_MASK(gprs->rsi, 2);
556                 break;
557             case 5:
558                 base_addr = ADDR_MASK(gprs->rdi, 2);
559                 break;
560             case 6:
561                 if (modrm->mod == 0) {
562                     base_addr = 0;
563                     mod_mode = DISP16;
564                 } else {
565                     base_addr = ADDR_MASK(gprs->rbp, 2);
566                 }
567                 break;
568             case 7:
569                 base_addr = ADDR_MASK(gprs->rbx, 2);
570                 break;
571         }
572
573
574
575         if (mod_mode == DISP8) {
576             base_addr += *(sint8_t *)instr_cursor;
577             instr_cursor += 1;
578         } else if (mod_mode == DISP16) {
579             base_addr += *(sint16_t *)instr_cursor;
580             instr_cursor += 2;
581         }
582     
583         
584         // get appropriate segment
585         if (instr->prefixes.cs_override) {
586             seg = &(core->segments.cs);
587         } else if (instr->prefixes.es_override) {
588             seg = &(core->segments.es);
589         } else if (instr->prefixes.ss_override) {
590             seg = &(core->segments.ss);
591         } else if (instr->prefixes.fs_override) {
592             seg = &(core->segments.fs);
593         } else if (instr->prefixes.gs_override) {
594             seg = &(core->segments.gs);
595         } else {
596             seg = &(core->segments.ds);
597         }
598         
599         operand->operand = ADDR_MASK(get_addr_linear(core, base_addr, seg), 
600                                      get_addr_width(core, instr));
601     }
602
603
604     return (instr_cursor - modrm_instr);
605 }
606
607
608 // returns num_bytes parsed
609 static int decode_rm_operand32(struct guest_info * core, 
610                                uint8_t * modrm_instr,  
611                                struct x86_instr * instr,
612                                struct x86_operand * operand, 
613                                uint8_t * reg_code) {
614
615     struct v3_gprs * gprs = &(core->vm_regs);
616     uint8_t * instr_cursor = modrm_instr;
617     struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
618     addr_t base_addr = 0;
619     modrm_mode_t mod_mode = 0;
620     uint_t has_sib_byte = 0;
621
622
623     *reg_code = modrm->reg;
624
625     instr_cursor += 1;
626
627     if (modrm->mod == 3) {
628         operand->type = REG_OPERAND;
629         //    PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
630
631         decode_gpr(core, modrm->rm, operand);
632
633     } else {
634         struct v3_segment * seg = NULL;
635
636         operand->type = MEM_OPERAND;
637
638         if (modrm->mod == 0) {
639             mod_mode = DISP0;
640         } else if (modrm->mod == 1) {
641             mod_mode = DISP8;
642         } else if (modrm->mod == 2) {
643             mod_mode = DISP32;
644         } else {
645             PrintError("Instruction format error: Invalid mod_rm mode (%d)\n", modrm->mod);
646             v3_print_instr(instr);
647             return -1;
648         }
649     
650         switch (modrm->rm) {
651             case 0:
652                 base_addr = gprs->rax;
653                 break;
654             case 1:
655                 base_addr = gprs->rcx;
656                 break;
657             case 2:
658                 base_addr = gprs->rdx;
659                 break;
660             case 3:
661                 base_addr = gprs->rbx;
662                 break;
663             case 4:
664                 has_sib_byte = 1;
665                 break;
666             case 5:
667                 if (modrm->mod == 0) {
668                     base_addr = 0;
669                     mod_mode = DISP32;
670                 } else {
671                     base_addr = gprs->rbp;
672                 }
673                 break;
674             case 6:
675                 base_addr = gprs->rsi;
676                 break;
677             case 7:
678                 base_addr = gprs->rdi;
679                 break;
680         }
681
682         if (has_sib_byte) {
683             instr_cursor += 1;
684             struct sib_byte * sib = (struct sib_byte *)(instr_cursor);
685             int scale = 0x1 << sib->scale;
686
687             instr_cursor += 1;
688
689             switch (sib->index) {
690                 case 0:
691                     base_addr = gprs->rax;
692                     break;
693                 case 1:
694                     base_addr = gprs->rcx;
695                     break;
696                 case 2:
697                     base_addr = gprs->rdx;
698                     break;
699                 case 3:
700                     base_addr = gprs->rbx;
701                     break;
702                 case 4:
703                     base_addr = 0;
704                     break;
705                 case 5:
706                     base_addr = gprs->rbp;
707                     break;
708                 case 6:
709                     base_addr = gprs->rsi;
710                     break;
711                 case 7:
712                     base_addr = gprs->rdi;
713                     break;
714             }
715
716             base_addr *= scale;
717
718
719             switch (sib->base) {
720                 case 0:
721                     base_addr += ADDR_MASK(gprs->rax, 4);
722                     break;
723                 case 1:
724                     base_addr += ADDR_MASK(gprs->rcx, 4);
725                     break;
726                 case 2:
727                     base_addr += ADDR_MASK(gprs->rdx, 4);
728                     break;
729                 case 3:
730                     base_addr += ADDR_MASK(gprs->rbx, 4);
731                     break;
732                 case 4:
733                     base_addr += ADDR_MASK(gprs->rsp, 4);
734                     break;
735                 case 5:
736                     if (modrm->mod != 0) {
737                         base_addr += ADDR_MASK(gprs->rbp, 4);
738                     }
739                     break;
740                 case 6:
741                     base_addr += ADDR_MASK(gprs->rsi, 4);
742                     break;
743                 case 7:
744                     base_addr += ADDR_MASK(gprs->rdi, 4);
745                     break;
746             }
747
748         } 
749
750
751         if (mod_mode == DISP8) {
752             base_addr += *(sint8_t *)instr_cursor;
753             instr_cursor += 1;
754         } else if (mod_mode == DISP32) {
755             base_addr += *(sint32_t *)instr_cursor;
756             instr_cursor += 4;
757         }
758     
759         // get appropriate segment
760         if (instr->prefixes.cs_override) {
761             seg = &(core->segments.cs);
762         } else if (instr->prefixes.es_override) {
763             seg = &(core->segments.es);
764         } else if (instr->prefixes.ss_override) {
765             seg = &(core->segments.ss);
766         } else if (instr->prefixes.fs_override) {
767             seg = &(core->segments.fs);
768         } else if (instr->prefixes.gs_override) {
769             seg = &(core->segments.gs);
770         } else {
771             seg = &(core->segments.ds);
772         }
773         
774         operand->operand = ADDR_MASK(get_addr_linear(core, base_addr, seg), 
775                                      get_addr_width(core, instr));
776     }
777
778
779     return (instr_cursor - modrm_instr);
780 }
781
782
783 int decode_rm_operand64(struct guest_info * core, uint8_t * modrm_instr, 
784                         struct x86_instr * instr, struct x86_operand * operand, 
785                         uint8_t * reg_code) {
786     
787     struct v3_gprs * gprs = &(core->vm_regs);
788     uint8_t * instr_cursor = modrm_instr;
789     struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
790     addr_t base_addr = 0;
791     modrm_mode_t mod_mode = 0;
792     uint_t has_sib_byte = 0;
793
794
795     instr_cursor += 1;
796
797     *reg_code = modrm->reg;
798     *reg_code |= (instr->prefixes.rex_reg << 3);
799
800     if (modrm->mod == 3) {
801         uint8_t rm_val = modrm->rm;
802         
803         rm_val |= (instr->prefixes.rex_rm << 3);
804         
805         operand->type = REG_OPERAND;
806         //    PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
807         
808         decode_gpr(core, rm_val, operand);
809     } else {
810         struct v3_segment * seg = NULL;
811         uint8_t rm_val = modrm->rm;
812
813         operand->type = MEM_OPERAND;
814
815
816         if (modrm->mod == 0) {
817             mod_mode = DISP0;
818         } else if (modrm->mod == 1) {
819             mod_mode = DISP8;
820         } else if (modrm->mod == 2) {
821             mod_mode = DISP32;
822         } else {
823             PrintError("Instruction format error: Invalid mod_rm mode (%d)\n", modrm->mod);
824             v3_print_instr(instr);
825             return -1;
826         }
827     
828         if (rm_val == 4) {
829             has_sib_byte = 1;
830         } else {
831             rm_val |= (instr->prefixes.rex_rm << 3);
832             
833             switch (rm_val) {
834                 case 0:
835                     base_addr = gprs->rax;
836                     break;
837                 case 1:
838                     base_addr = gprs->rcx;
839                     break;
840                 case 2:
841                     base_addr = gprs->rdx;
842                     break;
843                 case 3:
844                     base_addr = gprs->rbx;
845                     break;
846                 case 5:
847                     if (modrm->mod == 0) {
848                         base_addr = 0;
849                         mod_mode = DISP32;
850                     } else {
851                         base_addr = gprs->rbp;
852                     }
853                     break;
854                 case 6:
855                     base_addr = gprs->rsi;
856                     break;
857                 case 7:
858                     base_addr = gprs->rdi;
859                     break;
860                 case 8:
861                     base_addr = gprs->r8;
862                     break;
863                 case 9:
864                     base_addr = gprs->r9;
865                     break;
866                 case 10:
867                     base_addr = gprs->r10;
868                     break;
869                 case 11:
870                     base_addr = gprs->r11;
871                     break;
872                 case 12:
873                     base_addr = gprs->r12;
874                     break;
875                 case 13:
876                     base_addr = gprs->r13;
877                     break;
878                 case 14:
879                     base_addr = gprs->r14;
880                     break;
881                 case 15:
882                     base_addr = gprs->r15;
883                     break;
884                 default:
885                     return -1;
886             }
887         }
888
889         if (has_sib_byte) {
890             instr_cursor += 1;
891             struct sib_byte * sib = (struct sib_byte *)(instr_cursor);
892             int scale = 0x1 << sib->scale;
893             uint8_t index_val = sib->index;
894             uint8_t base_val = sib->base;
895
896             index_val |= (instr->prefixes.rex_sib_idx << 3);
897             base_val |= (instr->prefixes.rex_rm << 3);
898
899             instr_cursor += 1;
900
901             switch (index_val) {
902                 case 0:
903                     base_addr = gprs->rax;
904                     break;
905                 case 1:
906                     base_addr = gprs->rcx;
907                     break;
908                 case 2:
909                     base_addr = gprs->rdx;
910                     break;
911                 case 3:
912                     base_addr = gprs->rbx;
913                     break;
914                 case 4:
915                     base_addr = 0;
916                     break;
917                 case 5:
918                     base_addr = gprs->rbp;
919                     break;
920                 case 6:
921                     base_addr = gprs->rsi;
922                     break;
923                 case 7:
924                     base_addr = gprs->rdi;
925                     break;
926                 case 8:
927                     base_addr = gprs->r8;
928                     break;
929                 case 9:
930                     base_addr = gprs->r9;
931                     break;
932                 case 10:
933                     base_addr = gprs->r10;
934                     break;
935                 case 11:
936                     base_addr = gprs->r11;
937                     break;
938                 case 12:
939                     base_addr = gprs->r12;
940                     break;
941                 case 13:
942                     base_addr = gprs->r13;
943                     break;
944                 case 14:
945                     base_addr = gprs->r14;
946                     break;
947                 case 15:
948                     base_addr = gprs->r15;
949                     break;
950             }
951
952             base_addr *= scale;
953
954
955             switch (base_val) {
956                 case 0:
957                     base_addr += gprs->rax;
958                     break;
959                 case 1:
960                     base_addr += gprs->rcx;
961                     break;
962                 case 2:
963                     base_addr += gprs->rdx;
964                     break;
965                 case 3:
966                     base_addr += gprs->rbx;
967                     break;
968                 case 4:
969                     base_addr += gprs->rsp;
970                     break;
971                 case 5:
972                     if (modrm->mod != 0) {
973                         base_addr += gprs->rbp;
974                     }
975                     break;
976                 case 6:
977                     base_addr += gprs->rsi;
978                     break;
979                 case 7:
980                     base_addr += gprs->rdi;
981                     break;
982                 case 8:
983                     base_addr += gprs->r8;
984                     break;
985                 case 9:
986                     base_addr += gprs->r9;
987                     break;
988                 case 10:
989                     base_addr += gprs->r10;
990                     break;
991                 case 11:
992                     base_addr += gprs->r11;
993                     break;
994                 case 12:
995                     base_addr += gprs->r12;
996                     break;
997                 case 13:
998                     base_addr += gprs->r13;
999                     break;
1000                 case 14:
1001                     base_addr += gprs->r14;
1002                     break;
1003                 case 15:
1004                     base_addr += gprs->r15;
1005                     break;
1006             }
1007
1008         } 
1009
1010
1011         if (mod_mode == DISP8) {
1012             base_addr += *(sint8_t *)instr_cursor;
1013             instr_cursor += 1;
1014         } else if (mod_mode == DISP32) {
1015             base_addr += *(sint32_t *)instr_cursor;
1016             instr_cursor += 4;
1017         }
1018     
1019
1020         /* 
1021            Segments should be ignored 
1022            // get appropriate segment
1023            if (instr->prefixes.cs_override) {
1024            seg = &(core->segments.cs);
1025            } else if (instr->prefixes.es_override) {
1026            seg = &(core->segments.es);
1027            } else if (instr->prefixes.ss_override) {
1028            seg = &(core->segments.ss);
1029            } else if (instr->prefixes.fs_override) {
1030            seg = &(core->segments.fs);
1031            } else if (instr->prefixes.gs_override) {
1032            seg = &(core->segments.gs);
1033            } else {
1034            seg = &(core->segments.ds);
1035            }
1036         */
1037
1038         operand->operand = ADDR_MASK(get_addr_linear(core, base_addr, seg), 
1039                                      get_addr_width(core, instr));
1040     }
1041
1042
1043     return (instr_cursor - modrm_instr);
1044
1045
1046 }
1047
1048
1049 static int decode_rm_operand(struct guest_info * core, 
1050                              uint8_t * instr_ptr,        // input
1051                              op_form_t form, 
1052                              struct x86_instr * instr,
1053                              struct x86_operand * operand, 
1054                              uint8_t * reg_code) {
1055     
1056     v3_cpu_mode_t mode = v3_get_vm_cpu_mode(core);
1057
1058     operand->size = get_operand_width(core, instr, form);
1059
1060     switch (mode) {
1061         case REAL:
1062             return decode_rm_operand16(core, instr_ptr, instr, operand, reg_code);
1063         case LONG:
1064             if (instr->prefixes.rex_op_size) {
1065                 return decode_rm_operand64(core, instr_ptr, instr, operand, reg_code);
1066             }
1067         case PROTECTED:
1068         case PROTECTED_PAE:
1069         case LONG_32_COMPAT:
1070             return decode_rm_operand32(core, instr_ptr, instr, operand, reg_code);
1071         default:
1072             PrintError("Invalid CPU_MODE (%d)\n", mode);
1073             return -1;
1074     }
1075 }
1076                              
1077
1078
1079 static inline op_form_t op_code_to_form_0f(uint8_t * instr, int * length) {
1080     *length += 1;
1081
1082     switch (instr[1]) {
1083         case 0x01: {
1084             struct modrm_byte * modrm = (struct modrm_byte *)&(instr[2]);
1085
1086             switch (modrm->reg) {
1087                 case 4:
1088                     return SMSW;
1089                 case 6:
1090                     return LMSW;
1091                 case 7:
1092                     return INVLPG;
1093                 default:
1094                     return INVALID_INSTR;
1095             }
1096         }
1097
1098         case 0x06:
1099             return CLTS;
1100         case 0x20:
1101             return MOV_CR2;
1102         case 0x21:
1103             return MOV_DR2;
1104
1105         case 0x22:
1106             return MOV_2CR;
1107         case 0x23:
1108             return MOV_2DR;
1109
1110         case 0x90:
1111             return SETO;
1112         case 0x91:
1113             return SETNO;
1114         case 0x92:
1115             return SETB;
1116         case 0x93:
1117             return SETNB;
1118         case 0x94:
1119             return SETZ;
1120         case 0x95:
1121             return SETNZ;
1122         case 0x96:
1123             return SETBE;
1124         case 0x97:
1125             return SETNBE;
1126         case 0x98:
1127             return SETS;
1128         case 0x99:
1129             return SETNS;
1130         case 0x9a:
1131             return SETP;
1132         case 0x9b:
1133             return SETNP;
1134         case 0x9c:
1135             return SETL;
1136         case 0x9d:
1137             return SETNL;
1138         case 0x9e:
1139             return SETLE;
1140         case 0x9f:
1141             return SETNLE;
1142
1143         case 0xb6:
1144             return MOVZX_8;
1145         case 0xb7:
1146             return MOVZX;
1147
1148         case 0xbe:
1149             return MOVSX_8;
1150         case 0xbf:
1151             return MOVSX;
1152             
1153
1154         default:
1155             return INVALID_INSTR;
1156     }
1157 }
1158
1159
1160 static op_form_t op_code_to_form(uint8_t * instr, int * length) {
1161     *length += 1;
1162
1163     switch (instr[0]) {
1164         case 0x00:
1165             return ADD_2MEM_8;
1166         case 0x01:
1167             return ADD_2MEM;
1168         case 0x02:
1169             return ADD_MEM2_8;
1170         case 0x03:
1171             return ADD_MEM2;
1172
1173         case 0x08:
1174             return OR_2MEM_8;
1175         case 0x09:
1176             return OR_2MEM;
1177         case 0x0a:
1178             return OR_MEM2_8;
1179         case 0x0b:
1180             return OR_MEM2;
1181
1182
1183         case 0x0f:
1184             return op_code_to_form_0f(instr, length);
1185
1186         case 0x10:
1187             return ADC_2MEM_8;
1188         case 0x11:
1189             return ADC_2MEM;
1190         case 0x12:
1191             return ADC_MEM2_8;
1192         case 0x13:
1193             return ADC_MEM2;
1194
1195         case 0x20:
1196             return AND_2MEM_8; 
1197         case 0x21:
1198             return AND_2MEM;
1199         case 0x22:
1200             return AND_MEM2_8;
1201         case 0x23:
1202             return AND_MEM2;
1203
1204         case 0x28:
1205             return SUB_2MEM_8;
1206         case 0x29:
1207             return SUB_2MEM;
1208         case 0x2a:
1209             return SUB_MEM2_8;
1210         case 0x2b:
1211             return SUB_MEM2;
1212
1213
1214         case 0x30:
1215             return XOR_2MEM_8;
1216         case 0x31:
1217             return XOR_2MEM;
1218         case 0x32:
1219             return XOR_MEM2_8;
1220         case 0x33:
1221             return XOR_MEM2;
1222
1223         case 0x80:{
1224             struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1225
1226             switch (modrm->reg) {
1227                 case 0:
1228                     return ADD_IMM2_8;
1229                 case 1:
1230                     return OR_IMM2_8;
1231                 case 2:
1232                     return ADC_IMM2_8;
1233                 case 4:
1234                     return AND_IMM2_8;
1235                 case 5:
1236                     return SUB_IMM2_8;
1237                 case 6:
1238                     return XOR_IMM2_8;
1239                 default:
1240                     return INVALID_INSTR;
1241             }
1242         }
1243         case 0x81: {
1244             struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1245             
1246             switch (modrm->reg) {
1247                 case 0:
1248                     return ADD_IMM2;
1249                 case 1:
1250                     return OR_IMM2;
1251                 case 2:
1252                     return ADC_IMM2;
1253                 case 4:
1254                     return AND_IMM2;
1255                 case 5:
1256                     return SUB_IMM2;
1257                 case 6:
1258                     return XOR_IMM2;
1259                 default:
1260                     return INVALID_INSTR;
1261             }
1262         }
1263         case 0x83: {
1264             struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1265
1266             switch (modrm->reg) {
1267                 case 0:
1268                     return ADD_IMM2SX_8;
1269                 case 1:
1270                     return OR_IMM2SX_8;
1271                 case 2:
1272                     return ADC_IMM2SX_8;
1273                 case 4:
1274                     return AND_IMM2SX_8;
1275                 case 5:
1276                     return SUB_IMM2SX_8;
1277                 case 6:
1278                     return XOR_IMM2SX_8;
1279                 default:
1280                     return INVALID_INSTR;
1281             }
1282         }
1283
1284         case 0x86:
1285             return XCHG_8;
1286         case 0x87:
1287             return XCHG;
1288         case 0x88:
1289             return MOV_2MEM_8;
1290         case 0x89:
1291             return MOV_2MEM;
1292         case 0x8a:
1293             return MOV_MEM2_8;
1294         case 0x8b:
1295             return MOV_MEM2;
1296             
1297         case 0x8c:
1298             return MOV_SR2;
1299         case 0x8e:
1300             return MOV_2SR;
1301
1302
1303         case 0x9c:
1304             return PUSHF;
1305         case 0x9d:
1306             return POPF;
1307
1308         case 0xa0:
1309             return MOV_MEM2AL_8;
1310         case 0xa1:
1311             return MOV_MEM2AX;
1312         case 0xa2:
1313             return MOV_AL2MEM_8;
1314         case 0xa3:
1315             return MOV_AX2MEM;
1316
1317         case 0xa4:
1318             return MOVS_8;
1319         case 0xa5:
1320             return MOVS;
1321
1322         case 0xaa:
1323             return STOS_8;
1324         case 0xab:
1325             return STOS;
1326
1327         case 0xc6:
1328             return MOV_IMM2_8;
1329         case 0xc7:
1330             return MOV_IMM2;
1331
1332         case 0xf4:
1333             return HLT;
1334
1335         case 0xcd:
1336                 return INT;
1337
1338         case 0xf6: {
1339             struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1340
1341             switch (modrm->reg) {
1342                 case 2:
1343                     return NOT_8;
1344                 case 3:
1345                     return NEG_8;
1346                 default:
1347                     return INVALID_INSTR;
1348             }
1349         }
1350         case 0xf7: {
1351             struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1352
1353             switch (modrm->reg) {
1354                 case 2:
1355                     return NOT;
1356                 case 3:
1357                     return NEG;
1358                 default:
1359                     return INVALID_INSTR;
1360             }
1361         }
1362             
1363
1364         case 0xfe: {
1365             struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1366
1367             switch (modrm->reg) {
1368                 case 0:
1369                     return INC_8;
1370                 case 1:
1371                     return DEC_8;
1372                 default:
1373                     return INVALID_INSTR;
1374             }
1375         }
1376
1377         case 0xff: {
1378             struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1379
1380             switch (modrm->reg) {
1381                 case 0:
1382                     return INC;
1383                 case 1:
1384                     return DEC;
1385                 default:
1386                     return INVALID_INSTR;
1387             }
1388         }
1389
1390         default:
1391             return INVALID_INSTR;
1392     }
1393 }
1394
1395
1396
1397 static char * op_form_to_str(op_form_t form) {
1398
1399     switch (form) {
1400         case LMSW: return "LMSW";
1401         case SMSW: return "SMSW";
1402         case CLTS: return "CLTS";
1403         case INVLPG: return "INVLPG";
1404         case MOV_CR2: return "MOV_CR2";
1405         case MOV_2CR: return "MOV_2CR";
1406         case MOV_DR2: return "MOV_DR2";
1407         case MOV_2DR: return "MOV_2DR";
1408         case MOV_SR2: return "MOV_SR2";
1409         case MOV_2SR: return "MOV_2SR";
1410         case MOV_MEM2_8: return "MOV_MEM2_8";
1411         case MOV_MEM2: return "MOV_MEM2";
1412         case MOV_2MEM_8: return "MOV_2MEM_8";
1413         case MOV_2MEM: return "MOV_2MEM";
1414         case MOV_MEM2AL_8: return "MOV_MEM2AL_8";
1415         case MOV_MEM2AX: return "MOV_MEM2AX";
1416         case MOV_AL2MEM_8: return "MOV_AL2MEM_8";
1417         case MOV_AX2MEM: return "MOV_AX2MEM";
1418         case MOV_IMM2_8: return "MOV_IMM2_8";
1419         case MOV_IMM2: return "MOV_IMM2";
1420         case MOVS_8: return "MOVS_8";
1421         case MOVS: return "MOVS";
1422         case MOVSX_8: return "MOVSX_8";
1423         case MOVSX: return "MOVSX";
1424         case MOVZX_8: return "MOVZX_8";
1425         case MOVZX: return "MOVZX";
1426         case HLT: return "HLT";
1427         case PUSHF: return "PUSHF";
1428         case POPF: return "POPF";
1429         case ADC_2MEM_8: return "ADC_2MEM_8";
1430         case ADC_2MEM: return "ADC_2MEM";
1431         case ADC_MEM2_8: return "ADC_MEM2_8";
1432         case ADC_MEM2: return "ADC_MEM2";
1433         case ADC_IMM2_8: return "ADC_IMM2_8";
1434         case ADC_IMM2: return "ADC_IMM2";
1435         case ADC_IMM2SX_8: return "ADC_IMM2SX_8";
1436         case ADD_IMM2_8: return "ADD_IMM2_8";
1437         case ADD_IMM2: return "ADD_IMM2";
1438         case ADD_IMM2SX_8: return "ADD_IMM2SX_8";
1439         case ADD_2MEM_8: return "ADD_2MEM_8";
1440         case ADD_2MEM: return "ADD_2MEM";
1441         case ADD_MEM2_8: return "ADD_MEM2_8";
1442         case ADD_MEM2: return "ADD_MEM2";
1443         case AND_MEM2_8: return "AND_MEM2_8";
1444         case AND_MEM2: return "AND_MEM2";
1445         case AND_2MEM_8: return "AND_2MEM_8";
1446         case AND_2MEM: return "AND_2MEM";
1447         case AND_IMM2_8: return "AND_IMM2_8";
1448         case AND_IMM2: return "AND_IMM2";
1449         case AND_IMM2SX_8: return "AND_IMM2SX_8";
1450         case OR_2MEM_8: return "OR_2MEM_8";
1451         case OR_2MEM: return "OR_2MEM";
1452         case OR_MEM2_8: return "OR_MEM2_8";
1453         case OR_MEM2: return "OR_MEM2";
1454         case OR_IMM2_8: return "OR_IMM2_8";
1455         case OR_IMM2: return "OR_IMM2";
1456         case OR_IMM2SX_8: return "OR_IMM2SX_8";
1457         case SUB_2MEM_8: return "SUB_2MEM_8";
1458         case SUB_2MEM: return "SUB_2MEM";
1459         case SUB_MEM2_8: return "SUB_MEM2_8";
1460         case SUB_MEM2: return "SUB_MEM2";
1461         case SUB_IMM2_8: return "SUB_IMM2_8";
1462         case SUB_IMM2: return "SUB_IMM2";
1463         case SUB_IMM2SX_8: return "SUB_IMM2SX_8";
1464         case XOR_2MEM_8: return "XOR_2MEM_8";
1465         case XOR_2MEM: return "XOR_2MEM";
1466         case XOR_MEM2_8: return "XOR_MEM2_8";
1467         case XOR_MEM2: return "XOR_MEM2";
1468         case XOR_IMM2_8: return "XOR_IMM2_8";
1469         case XOR_IMM2: return "XOR_IMM2";
1470         case XOR_IMM2SX_8: return "XOR_IMM2SX_8";
1471         case INC_8: return "INC_8";
1472         case INC: return "INC";
1473         case DEC_8: return "DEC_8";
1474         case DEC: return "DEC";
1475         case NEG_8: return "NEG_8";
1476         case NEG: return "NEG"; 
1477         case NOT_8: return "NOT_8";
1478         case NOT: return "NOT";
1479         case XCHG_8: return "XCHG_8";
1480         case XCHG: return "XCHG";
1481         case SETB: return "SETB";
1482         case SETBE: return "SETBE";
1483         case SETL: return "SETL";
1484         case SETLE: return "SETLE";
1485         case SETNB: return "SETNB";
1486         case SETNBE: return "SETNBE";
1487         case SETNL: return "SETNL";
1488         case SETNLE: return "SETNLE";
1489         case SETNO: return "SETNO";
1490         case SETNP: return "SETNP";
1491         case SETNS: return "SETNS";
1492         case SETNZ: return "SETNZ";
1493         case SETP: return "SETP";
1494         case SETS: return "SETS";
1495         case SETZ: return "SETZ";
1496         case SETO: return "SETO";
1497         case STOS_8: return "STOS_8";
1498         case STOS: return "STOS";
1499         case INT: return "INT";
1500
1501         case INVALID_INSTR:
1502         default:
1503             return "INVALID_INSTR";
1504     }
1505 }