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 updates
[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
23 /* .... Giant fucking switch tables */
24
25
26
27
28
29
30
31 typedef enum {
32     INVALID_INSTR,
33     LMSW,
34     SMSW,
35     CLTS,
36     INVLPG,
37
38     MOV_CR2,
39     MOV_2CR,
40     MOV_DR2,
41     MOV_2DR,
42     MOV_SR2,
43     MOV_2SR,
44
45     MOV_MEM2_8,
46     MOV_MEM2,
47     MOV_2MEM_8,
48     MOV_2MEM,
49     MOV_MEM2AL_8,
50     MOV_MEM2AX,
51     MOV_AL2MEM_8,
52     MOV_AX2MEM,
53     MOV_IMM2_8,
54     MOV_IMM2,
55
56     MOVS_8,
57     MOVS,
58     MOVSX_8,
59     MOVSX,
60     MOVZX_8,
61     MOVZX,
62
63     HLT,
64     PUSHF,
65     POPF,
66
67     ADC_2MEM_8,
68     ADC_2MEM,
69     ADC_MEM2_8,
70     ADC_MEM2,
71     ADC_IMM2_8,
72     ADC_IMM2,
73     ADC_IMM2SX_8,
74     ADD_IMM2_8,
75     ADD_IMM2,
76     ADD_IMM2SX_8,
77     ADD_2MEM_8,
78     ADD_2MEM,
79     ADD_MEM2_8,
80     ADD_MEM2,
81     AND_MEM2_8,
82     AND_MEM2,
83     AND_2MEM_8,
84     AND_2MEM,
85     AND_IMM2_8,
86     AND_IMM2,
87     AND_IMM2SX_8,
88     OR_2MEM_8,
89     OR_2MEM,
90     OR_MEM2_8,
91     OR_MEM2,
92     OR_IMM2_8,
93     OR_IMM2,
94     OR_IMM2SX_8,
95     SUB_2MEM_8,
96     SUB_2MEM,
97     SUB_MEM2_8,
98     SUB_MEM2,
99     SUB_IMM2_8,
100     SUB_IMM2,
101     SUB_IMM2SX_8,
102     XOR_2MEM_8,
103     XOR_2MEM,
104     XOR_MEM2_8,
105     XOR_MEM2,
106     XOR_IMM2_8,
107     XOR_IMM2,
108     XOR_IMM2SX_8,
109
110     INC_8,
111     INC,
112     DEC_8,
113     DEC,
114     NEG_8,
115     NEG, 
116     NOT_8,
117     NOT,
118     XCHG_8,
119     XCHG,
120
121     SETB,
122     SETBE,
123     SETL,
124     SETLE,
125     SETNB,
126     SETNBE,
127     SETNL,
128     SETNLE,
129     SETNO,
130     SETNP,
131     SETNS,
132     SETNZ,
133     SETP,
134     SETS,
135     SETZ,
136     SETO,
137
138     STOS_8,
139     STOS
140 } op_form_t;
141
142
143
144
145 static int get_operand_width(struct guest_info * info, struct x86_instr * instr, op_form_t form) {
146     switch (form) {
147
148         case CLTS:
149         case HLT:
150             return 0;
151
152
153         case MOV_MEM2_8:
154         case MOV_2MEM_8:
155         case MOV_MEM2AL_8:
156         case MOV_AL2MEM_8:
157         case MOV_IMM2_8:
158         case MOVS_8:
159         case MOVSX_8:
160         case MOVZX_8:
161         case ADC_2MEM_8:
162         case ADC_MEM2_8:
163         case ADC_IMM2_8:
164         case ADD_IMM2_8:
165         case ADD_2MEM_8:
166         case ADD_MEM2_8:
167         case AND_MEM2_8:
168         case AND_2MEM_8:
169         case AND_IMM2_8:
170         case OR_2MEM_8:
171         case OR_MEM2_8:
172         case OR_IMM2_8:
173         case SUB_2MEM_8:
174         case XOR_2MEM_8:
175         case SUB_MEM2_8:
176         case SUB_IMM2_8:
177         case XOR_MEM2_8:
178         case XOR_IMM2_8:
179         case INC_8:
180         case DEC_8:
181         case NEG_8:
182         case NOT_8:
183         case XCHG_8:
184         case STOS_8:
185         case SETB:
186         case SETBE:
187         case SETL:
188         case SETLE:
189         case SETNB:
190         case SETNBE:
191         case SETNL:
192         case SETNLE:
193         case SETNO:
194         case SETNP:
195         case SETNS:
196         case SETNZ:
197         case SETP:
198         case SETS:
199         case SETZ:
200         case SETO:
201             return 1;
202
203
204         case LMSW:
205         case SMSW:
206             return 2;
207
208         case MOV_MEM2:
209         case MOV_2MEM:
210         case MOV_MEM2AX:
211         case MOV_AX2MEM:
212         case MOV_IMM2:      
213         case MOVS:
214         case MOVSX:
215         case MOVZX:
216         case ADC_2MEM:
217         case ADC_MEM2:
218         case ADC_IMM2:
219         case ADD_IMM2:
220         case ADD_2MEM:
221         case ADD_MEM2:
222         case AND_MEM2:
223         case AND_2MEM:
224         case AND_IMM2:
225         case OR_2MEM:
226         case OR_MEM2:
227         case OR_IMM2:
228         case SUB_2MEM:
229         case SUB_MEM2:
230         case SUB_IMM2:
231         case XOR_2MEM:
232         case XOR_MEM2:
233         case XOR_IMM2:
234         case INC:
235         case DEC:
236         case NEG: 
237         case NOT:
238         case STOS:
239         case XCHG:
240         case ADC_IMM2SX_8:
241         case AND_IMM2SX_8:
242         case ADD_IMM2SX_8:
243         case OR_IMM2SX_8:
244         case SUB_IMM2SX_8:
245         case XOR_IMM2SX_8:
246             switch (v3_get_vm_cpu_mode(info)) {
247                 case REAL:
248                     return (instr->prefixes.op_size) ? 4 : 2;
249                 case PROTECTED:
250                 case PROTECTED_PAE:
251                     return (instr->prefixes.op_size) ? 2 : 4;
252                 case LONG_32_COMPAT:
253                 case LONG:
254                 default:
255                     PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
256                     return -1;
257             }
258
259
260         case INVLPG:
261             switch (v3_get_vm_cpu_mode(info)) {
262                 case REAL:
263                     PrintError("Invalid instruction given operating mode (%d)\n", form);
264                     return 0;
265                 case PROTECTED:
266                 case PROTECTED_PAE:
267                     return 4;
268                 case LONG_32_COMPAT:
269                 case LONG:
270                 default:
271                     PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
272                     return -1;
273             }
274
275
276         case PUSHF:
277         case POPF:
278             switch (v3_get_vm_cpu_mode(info)) {
279                 case REAL:
280                     return 2;
281                 case PROTECTED:
282                 case PROTECTED_PAE:
283                     return 4;
284                 case LONG_32_COMPAT:
285                 case LONG:
286                 default:
287                     PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
288                     return -1;
289             }
290
291         case MOV_DR2:
292         case MOV_2DR:
293         case MOV_CR2:
294         case MOV_2CR:
295             switch (v3_get_vm_cpu_mode(info)) {
296                 case REAL:
297                 case PROTECTED:
298                 case PROTECTED_PAE:
299                     return 4;
300                 case LONG_32_COMPAT:
301                 case LONG:
302                 default:
303                     PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
304                     return -1;
305             }
306
307
308         case MOV_SR2:
309         case MOV_2SR:
310         default:
311             PrintError("Unsupported instruction form %d\n", form);
312             return -1;
313         
314     }
315     return 0;
316 }
317
318
319
320 typedef enum {INVALID_ADDR_TYPE, REG, DISP0, DISP8, DISP16, DISP32} modrm_mode_t;
321 typedef enum {INVALID_REG_SIZE, REG64, REG32, REG16, REG8} reg_size_t;
322
323
324 struct modrm_byte {
325     uint_t rm   :   3;
326     uint_t reg  :   3;
327     uint_t mod  :   2;
328 } __attribute__((packed));
329
330
331 struct sib_byte {
332     uint_t base     :   3;
333     uint_t index    :   3;
334     uint_t scale    :   2;
335 } __attribute__((packed));
336
337
338
339
340 struct v3_gprs;
341
342 static inline int decode_gpr(struct v3_gprs * gprs,                     
343                              uint8_t reg_code,
344                              struct x86_operand * reg) {
345
346     switch (reg_code) {
347         case 0:
348             reg->operand = (addr_t)&(gprs->rax);
349             break;
350         case 1:
351             reg->operand = (addr_t)&(gprs->rcx);
352             break;
353         case 2:
354             reg->operand = (addr_t)&(gprs->rdx);
355             break;
356         case 3:
357             reg->operand = (addr_t)&(gprs->rbx);
358             break;
359         case 4:
360             if (reg->size == 1) {
361                 reg->operand = (addr_t)&(gprs->rax) + 1;
362             } else {
363                 reg->operand = (addr_t)&(gprs->rsp);
364             }
365             break;
366         case 5:
367             if (reg->size == 1) {
368                 reg->operand = (addr_t)&(gprs->rcx) + 1;
369             } else {
370                 reg->operand = (addr_t)&(gprs->rbp);
371             }
372             break;
373         case 6:
374             if (reg->size == 1) {
375                 reg->operand = (addr_t)&(gprs->rdx) + 1;
376             } else {
377                 reg->operand = (addr_t)&(gprs->rsi);
378             }
379             break;
380         case 7:
381             if (reg->size == 1) {
382                 reg->operand = (addr_t)&(gprs->rbx) + 1;
383             } else {
384                 reg->operand = (addr_t)&(gprs->rdi);
385             }
386             break;
387         default:
388             reg->operand = 0;
389             break;
390     }
391
392     return 0;
393 }
394
395
396 // This converts the displacement into the appropriate masked value
397 /* 
398    QUESTION: Are the register Values signed ?????
399  */
400 #define MASK_DISPLACEMENT(reg, mode) ({                                 \
401             sint64_t val = 0;                                           \
402             if (mode == DISP8) {                                        \
403                 val = (sint8_t)(reg & 0xff);                            \
404             } else if (mode == DISP16) {                                \
405                 val = (sint16_t)(reg & 0xffff);                         \
406             } else if (mode == DISP32) {                                \
407                 val = (sint32_t)(reg & 0xffffffff);                     \
408             } else {                                                    \
409                 PrintError("Error invalid displacement size (%d)\n", mode); \
410                 V3_ASSERT(0);                                           \
411             }                                                           \
412             val;                                                        \
413         })
414
415 static  int decode_rm_operand16(struct v3_gprs * gprs, 
416                                       char * modrm_instr, 
417                                       struct x86_operand * operand, 
418                                       uint8_t * reg_code) { 
419
420     
421     struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
422     addr_t base_addr = 0;
423     modrm_mode_t mod_mode = 0;
424     char * instr_cursor = modrm_instr;
425
426     //  PrintDebug("ModRM mod=%d\n", modrm->mod);
427     
428     *reg_code = modrm->reg;
429
430     instr_cursor += 1;
431
432     if (modrm->mod == 3) {
433         //PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
434         operand->type = REG_OPERAND;
435
436         decode_gpr(gprs, modrm->rm, operand);
437
438     } else {
439
440         operand->type = MEM_OPERAND;
441
442         if (modrm->mod == 0) {
443             mod_mode = DISP0;
444         } else if (modrm->mod == 1) {
445             mod_mode = DISP8;
446         } else if (modrm->mod == 2) {
447             mod_mode = DISP16;
448         }
449
450         switch (modrm->rm) {
451             case 0:
452                 base_addr = gprs->rbx + MASK_DISPLACEMENT(gprs->rsi, mod_mode);
453                 break;
454             case 1:
455                 base_addr = gprs->rbx + MASK_DISPLACEMENT(gprs->rdi, mod_mode);
456                 break;
457             case 2:
458                 base_addr = gprs->rbp + MASK_DISPLACEMENT(gprs->rsi, mod_mode);
459                 break;
460             case 3:
461                 base_addr = gprs->rbp + MASK_DISPLACEMENT(gprs->rdi, mod_mode);
462                 break;
463             case 4:
464                 base_addr = gprs->rsi;
465                 break;
466             case 5:
467                 base_addr = gprs->rdi;
468                 break;
469             case 6:
470                 if (modrm->mod == 0) {
471                     base_addr = 0;
472                     mod_mode = DISP16;
473                 } else {
474                     base_addr = gprs->rbp;
475                 }
476                 break;
477             case 7:
478                 base_addr = gprs->rbx;
479                 break;
480         }
481
482
483
484         if (mod_mode == DISP8) {
485             base_addr += *(sint8_t *)instr_cursor;
486             instr_cursor += 1;
487         } else if (mod_mode == DISP16) {
488             base_addr += *(sint16_t *)instr_cursor;
489             instr_cursor += 2;
490         }
491     
492         operand->operand = base_addr;
493     }
494
495
496     return (instr_cursor - modrm_instr);
497 }
498
499
500 // returns num_bytes parsed
501 static int decode_rm_operand32(struct v3_gprs * gprs,      // input/output
502                                uint8_t * modrm_instr,        // input
503                                struct x86_operand * operand, 
504                                uint8_t * reg_code) {
505     
506     uchar_t * instr_cursor = modrm_instr;
507     struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
508     addr_t base_addr = 0;
509     modrm_mode_t mod_mode = 0;
510     uint_t has_sib_byte = 0;
511
512
513     *reg_code = modrm->reg;
514
515     instr_cursor += 1;
516
517     if (modrm->mod == 3) {
518         operand->type = REG_OPERAND;
519         //    PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
520
521         decode_gpr(gprs, modrm->rm, operand);
522
523     } else {
524
525         operand->type = MEM_OPERAND;
526
527         if (modrm->mod == 0) {
528             mod_mode = DISP0;
529         } else if (modrm->mod == 1) {
530             mod_mode = DISP8;
531         } else if (modrm->mod == 2) {
532             mod_mode = DISP32;
533         }
534     
535         switch (modrm->rm) {
536             case 0:
537                 base_addr = gprs->rax;
538                 break;
539             case 1:
540                 base_addr = gprs->rcx;
541                 break;
542             case 2:
543                 base_addr = gprs->rdx;
544                 break;
545             case 3:
546                 base_addr = gprs->rbx;
547                 break;
548             case 4:
549                 has_sib_byte = 1;
550                 break;
551             case 5:
552                 if (modrm->mod == 0) {
553                     base_addr = 0;
554                     mod_mode = DISP32;
555                 } else {
556                     base_addr = gprs->rbp;
557                 }
558                 break;
559             case 6:
560                 base_addr = gprs->rsi;
561                 break;
562             case 7:
563                 base_addr = gprs->rdi;
564                 break;
565         }
566
567         if (has_sib_byte) {
568             instr_cursor += 1;
569             struct sib_byte * sib = (struct sib_byte *)(instr_cursor);
570             int scale = 0x1 << sib->scale;
571
572             instr_cursor += 1;
573
574             switch (sib->index) {
575                 case 0:
576                     base_addr = gprs->rax;
577                     break;
578                 case 1:
579                     base_addr = gprs->rcx;
580                     break;
581                 case 2:
582                     base_addr = gprs->rdx;
583                     break;
584                 case 3:
585                     base_addr = gprs->rbx;
586                     break;
587                 case 4:
588                     base_addr = 0;
589                     break;
590                 case 5:
591                     base_addr = gprs->rbp;
592                     break;
593                 case 6:
594                     base_addr = gprs->rsi;
595                     break;
596                 case 7:
597                     base_addr = gprs->rdi;
598                     break;
599             }
600
601             base_addr *= scale;
602
603
604             switch (sib->base) {
605                 case 0:
606                     base_addr += MASK_DISPLACEMENT(gprs->rax, mod_mode);
607                     break;
608                 case 1:
609                     base_addr += MASK_DISPLACEMENT(gprs->rcx, mod_mode);
610                     break;
611                 case 2:
612                     base_addr += MASK_DISPLACEMENT(gprs->rdx, mod_mode);
613                     break;
614                 case 3:
615                     base_addr += MASK_DISPLACEMENT(gprs->rbx, mod_mode);
616                     break;
617                 case 4:
618                     base_addr += MASK_DISPLACEMENT(gprs->rsp, mod_mode);
619                     break;
620                 case 5:
621                     if (modrm->mod != 0) {
622                         base_addr += MASK_DISPLACEMENT(gprs->rbp, mod_mode);
623                     }
624                     break;
625                 case 6:
626                     base_addr += MASK_DISPLACEMENT(gprs->rsi, mod_mode);
627                     break;
628                 case 7:
629                     base_addr += MASK_DISPLACEMENT(gprs->rdi, mod_mode);
630                     break;
631             }
632
633         } 
634
635
636         if (mod_mode == DISP8) {
637             base_addr += *(sint8_t *)instr_cursor;
638             instr_cursor += 1;
639         } else if (mod_mode == DISP32) {
640             base_addr += *(sint32_t *)instr_cursor;
641             instr_cursor += 4;
642         }
643     
644
645         operand->operand = base_addr;
646     }
647
648
649     return (instr_cursor - modrm_instr);
650 }
651
652
653
654
655
656 static int decode_rm_operand(struct guest_info * core, 
657                              uint8_t * instr_ptr,        // input
658                              struct x86_operand * operand, 
659                              uint8_t * reg_code) {
660     
661     v3_cpu_mode_t mode = v3_get_vm_cpu_mode(core);
662
663     if (mode == REAL) {
664         return decode_rm_operand16(&(core->vm_regs), instr_ptr, operand, reg_code);
665     } else if ((mode == PROTECTED) || (mode == PROTECTED_PAE)) {
666         return decode_rm_operand32(&(core->vm_regs), instr_ptr, operand, reg_code);
667     } else {
668         PrintError("Invalid CPU_MODE (%d)\n", mode);
669         return -1;
670     }
671 }
672                              
673
674
675 static inline op_form_t op_code_to_form_0f(uint8_t * instr) {
676     switch (instr[1]) {
677         case 0x01: {
678             struct modrm_byte * modrm = (struct modrm_byte *)&(instr[2]);
679
680             switch (modrm->reg) {
681                 case 4:
682                     return SMSW;
683                 case 6:
684                     return LMSW;
685                 case 7:
686                     return INVLPG;
687                 default:
688                     return INVALID_INSTR;
689             }
690         }
691
692         case 0x06:
693             return CLTS;
694         case 0x20:
695             return MOV_CR2;
696         case 0x21:
697             return MOV_DR2;
698
699         case 0x22:
700             return MOV_2CR;
701         case 0x23:
702             return MOV_2DR;
703
704         case 0x90:
705             return SETO;
706         case 0x91:
707             return SETNO;
708         case 0x92:
709             return SETB;
710         case 0x93:
711             return SETNB;
712         case 0x94:
713             return SETZ;
714         case 0x95:
715             return SETNZ;
716         case 0x96:
717             return SETBE;
718         case 0x97:
719             return SETNBE;
720         case 0x98:
721             return SETS;
722         case 0x99:
723             return SETNS;
724         case 0x9a:
725             return SETP;
726         case 0x9b:
727             return SETNP;
728         case 0x9c:
729             return SETL;
730         case 0x9d:
731             return SETNL;
732         case 0x9e:
733             return SETLE;
734         case 0x9f:
735             return SETNLE;
736
737         case 0xb6:
738             return MOVZX_8;
739         case 0xb7:
740             return MOVZX;
741
742         case 0xbe:
743             return MOVSX_8;
744         case 0xbf:
745             return MOVSX;
746             
747
748         default:
749             return INVALID_INSTR;
750     }
751 }
752
753
754 static op_form_t op_code_to_form(uint8_t * instr) {
755     switch (instr[0]) {
756         case 0x00:
757             return ADD_2MEM_8;
758         case 0x01:
759             return ADD_2MEM;
760         case 0x02:
761             return ADD_MEM2_8;
762         case 0x03:
763             return ADD_MEM2;
764
765         case 0x08:
766             return OR_2MEM_8;
767         case 0x09:
768             return OR_2MEM;
769         case 0x0a:
770             return OR_MEM2_8;
771         case 0x0b:
772             return OR_MEM2;
773
774
775         case 0x0f:
776             return op_code_to_form_0f(instr);
777
778         case 0x10:
779             return ADC_2MEM_8;
780         case 0x11:
781             return ADC_2MEM;
782         case 0x12:
783             return ADC_MEM2_8;
784         case 0x13:
785             return ADC_MEM2;
786
787         case 0x20:
788             return AND_2MEM_8; 
789         case 0x21:
790             return AND_2MEM;
791         case 0x22:
792             return AND_MEM2_8;
793         case 0x23:
794             return AND_MEM2;
795
796         case 0x28:
797             return SUB_2MEM_8;
798         case 0x29:
799             return SUB_2MEM;
800         case 0x2a:
801             return SUB_MEM2_8;
802         case 0x2b:
803             return SUB_MEM2;
804
805
806         case 0x30:
807             return XOR_2MEM_8;
808         case 0x31:
809             return XOR_2MEM;
810         case 0x32:
811             return XOR_MEM2_8;
812         case 0x33:
813             return XOR_MEM2;
814
815         case 0x80:{
816             struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
817
818             switch (modrm->reg) {
819                 case 0:
820                     return ADD_IMM2_8;
821                 case 1:
822                     return OR_IMM2_8;
823                 case 2:
824                     return ADC_IMM2_8;
825                 case 4:
826                     return AND_IMM2_8;
827                 case 5:
828                     return SUB_IMM2_8;
829                 case 6:
830                     return XOR_IMM2_8;
831                 default:
832                     return INVALID_INSTR;
833             }
834         }
835         case 0x81: {
836             struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
837             
838             switch (modrm->reg) {
839                 case 0:
840                     return ADD_IMM2;
841                 case 1:
842                     return OR_IMM2;
843                 case 2:
844                     return ADC_IMM2;
845                 case 4:
846                     return AND_IMM2;
847                 case 5:
848                     return SUB_IMM2;
849                 case 6:
850                     return XOR_IMM2;
851                 default:
852                     return INVALID_INSTR;
853             }
854         }
855         case 0x83: {
856             struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
857
858             switch (modrm->reg) {
859                 case 0:
860                     return ADD_IMM2SX_8;
861                 case 1:
862                     return OR_IMM2SX_8;
863                 case 2:
864                     return ADC_IMM2SX_8;
865                 case 4:
866                     return AND_IMM2SX_8;
867                 case 5:
868                     return SUB_IMM2SX_8;
869                 case 6:
870                     return XOR_IMM2SX_8;
871                 default:
872                     return INVALID_INSTR;
873             }
874         }
875
876         case 0x86:
877             return XCHG_8;
878         case 0x87:
879             return XCHG;
880         case 0x88:
881             return MOV_2MEM_8;
882         case 0x89:
883             return MOV_2MEM;
884         case 0x8a:
885             return MOV_MEM2_8;
886         case 0x8b:
887             return MOV_MEM2;
888             
889         case 0x8c:
890             return MOV_SR2;
891         case 0x8e:
892             return MOV_2SR;
893
894
895         case 0x9c:
896             return PUSHF;
897         case 0x9d:
898             return POPF;
899
900         case 0xa0:
901             return MOV_MEM2AL_8;
902         case 0xa1:
903             return MOV_MEM2AX;
904         case 0xa2:
905             return MOV_AL2MEM_8;
906         case 0xa3:
907             return MOV_AX2MEM;
908
909         case 0xa4:
910             return MOVS_8;
911         case 0xa5:
912             return MOVS;
913
914         case 0xaa:
915             return STOS_8;
916         case 0xab:
917             return STOS;
918
919         case 0xc6:
920             return MOV_IMM2_8;
921         case 0xc7:
922             return MOV_IMM2;
923
924         case 0xf4:
925             return HLT;
926
927
928         case 0xf6: {
929             struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
930
931             switch (modrm->reg) {
932                 case 2:
933                     return NOT_8;
934                 case 3:
935                     return NEG_8;
936                 default:
937                     return INVALID_INSTR;
938             }
939         }
940         case 0xf7: {
941             struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
942
943             switch (modrm->reg) {
944                 case 2:
945                     return NOT;
946                 case 3:
947                     return NEG;
948                 default:
949                     return INVALID_INSTR;
950             }
951         }
952             
953
954         case 0xfe: {
955             struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
956
957             switch (modrm->reg) {
958                 case 0:
959                     return INC_8;
960                 case 1:
961                     return DEC_8;
962                 default:
963                     return INVALID_INSTR;
964             }
965         }
966
967         case 0xff: {
968             struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
969
970             switch (modrm->reg) {
971                 case 0:
972                     return INC;
973                 case 1:
974                     return DEC;
975                 default:
976                     return INVALID_INSTR;
977             }
978         }
979
980         default:
981             return INVALID_INSTR;
982     }
983 }