xref: /aosp_15_r20/external/coreboot/src/device/oprom/x86emu/ops2.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /****************************************************************************
2 *
3 *                       Realmode X86 Emulator Library
4 *
5 *               Copyright (C) 1991-2004 SciTech Software, Inc.
6 *                    Copyright (C) David Mosberger-Tang
7 *                      Copyright (C) 1999 Egbert Eich
8 *
9 *  ========================================================================
10 *
11 *  Permission to use, copy, modify, distribute, and sell this software and
12 *  its documentation for any purpose is hereby granted without fee,
13 *  provided that the above copyright notice appear in all copies and that
14 *  both that copyright notice and this permission notice appear in
15 *  supporting documentation, and that the name of the authors not be used
16 *  in advertising or publicity pertaining to distribution of the software
17 *  without specific, written prior permission.  The authors makes no
18 *  representations about the suitability of this software for any purpose.
19 *  It is provided "as is" without express or implied warranty.
20 *
21 *  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
22 *  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
23 *  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
24 *  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
25 *  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
26 *  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
27 *  PERFORMANCE OF THIS SOFTWARE.
28 *
29 *  ========================================================================
30 *
31 * Language:     ANSI C
32 * Environment:  Any
33 * Developer:    Kendall Bennett
34 *
35 * Description:  This file includes subroutines to implement the decoding
36 *               and emulation of all the x86 extended two-byte processor
37 *               instructions.
38 *
39 ****************************************************************************/
40 
41 #include "x86emui.h"
42 
43 /*----------------------------- Implementation ----------------------------*/
44 
45 /****************************************************************************
46 PARAMETERS:
47 op1 - Instruction op code
48 
49 REMARKS:
50 Handles illegal opcodes.
51 ****************************************************************************/
x86emuOp2_illegal_op(u8 op2)52 static void x86emuOp2_illegal_op(u8 op2)
53 {
54     START_OF_INSTR();
55     DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n");
56     TRACE_REGS();
57     printf("%04x:%04x: %02X ILLEGAL EXTENDED X86 OPCODE!\n",
58         M.x86.R_CS, M.x86.R_IP-2, op2);
59     HALT_SYS();
60     END_OF_INSTR();
61 }
62 
63 /****************************************************************************
64  * REMARKS:
65  * Handles opcode 0x0f,0x01
66  * ****************************************************************************/
67 
x86emuOp2_opc_01(u8 op2)68 static void x86emuOp2_opc_01(u8 op2)
69 {
70   int mod, rl, rh;
71   u16 *destreg;
72   uint destoffset;
73 
74   START_OF_INSTR();
75   FETCH_DECODE_MODRM(mod, rh, rl);
76 
77   switch(rh) {
78   case 4: // SMSW (Store Machine Status Word)
79           // Decode the mod byte to find the addressing
80           // Dummy implementation: Always returns 0x10 (initial value as per intel manual volume 3, figure 8-1)
81 #define SMSW_INITIAL_VALUE	0x10
82     DECODE_PRINTF("SMSW\t");
83     switch (mod) {
84     case 0:
85       destoffset = decode_rm00_address(rl);
86       store_data_word(destoffset, SMSW_INITIAL_VALUE);
87       break;
88     case 1:
89       destoffset = decode_rm01_address(rl);
90       store_data_word(destoffset, SMSW_INITIAL_VALUE);
91       break;
92     case 2:
93       destoffset = decode_rm10_address(rl);
94       store_data_word(destoffset, SMSW_INITIAL_VALUE);
95       break;
96     case 3:
97       destreg = DECODE_RM_WORD_REGISTER(rl);
98       *destreg = SMSW_INITIAL_VALUE;
99       break;
100     }
101     TRACE_AND_STEP();
102     DECODE_CLEAR_SEGOVR();
103     DECODE_PRINTF("\n");
104     break;
105   default:
106     DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE IN 0F 01\n");
107     TRACE_REGS();
108     printf("%04x:%04x: %02X ILLEGAL EXTENDED X86 OPCODE!\n",
109         M.x86.R_CS, M.x86.R_IP-2, op2);
110     HALT_SYS();
111     break;
112   }
113 
114   END_OF_INSTR();
115 }
116 
117 /****************************************************************************
118  * REMARKS:
119  * Handles opcode 0x0f,0x08
120  * ****************************************************************************/
x86emuOp2_invd(u8 op2)121 static void x86emuOp2_invd(u8 op2)
122 {
123   START_OF_INSTR();
124   DECODE_PRINTF("INVD\n");
125   TRACE_AND_STEP();
126   DECODE_CLEAR_SEGOVR();
127   END_OF_INSTR();
128 }
129 
130 /****************************************************************************
131  * REMARKS:
132  * Handles opcode 0x0f,0x09
133  * ****************************************************************************/
x86emuOp2_wbinvd(u8 op2)134 static void x86emuOp2_wbinvd(u8 op2)
135 {
136   START_OF_INSTR();
137   DECODE_PRINTF("WBINVD\n");
138   TRACE_AND_STEP();
139   DECODE_CLEAR_SEGOVR();
140   END_OF_INSTR();
141 }
142 
143 /****************************************************************************
144  * REMARKS:
145  * Handles opcode 0x0f,0x30
146  * ****************************************************************************/
x86emuOp2_wrmsr(u8 op2)147 static void x86emuOp2_wrmsr(u8 op2)
148 {
149   /* dummy implementation, does nothing */
150 
151   START_OF_INSTR();
152   DECODE_PRINTF("WRMSR\n");
153   TRACE_AND_STEP();
154   DECODE_CLEAR_SEGOVR();
155   END_OF_INSTR();
156 }
157 
158 /****************************************************************************
159 REMARKS:
160 Handles opcode 0x0f,0x31
161 ****************************************************************************/
x86emuOp2_rdtsc(u8 X86EMU_UNUSED (op2))162 static void x86emuOp2_rdtsc(u8 X86EMU_UNUSED(op2))
163 {
164 #ifdef __HAS_LONG_LONG__
165   static u64 counter = 0;
166 #else
167   static u32 counter = 0;
168 #endif
169 
170   counter += 0x10000;
171 
172   /* read timestamp counter */
173   /*
174    * Note that instead of actually trying to accurately measure this, we just
175    * increase the counter by a fixed amount every time we hit one of these
176    * instructions.  Feel free to come up with a better method.
177    */
178   START_OF_INSTR();
179   DECODE_PRINTF("RDTSC\n");
180   TRACE_AND_STEP();
181 #ifdef __HAS_LONG_LONG__
182   M.x86.R_EAX = counter & 0xffffffff;
183   M.x86.R_EDX = counter >> 32;
184 #else
185   M.x86.R_EAX = counter;
186   M.x86.R_EDX = 0;
187 #endif
188   DECODE_CLEAR_SEGOVR();
189   END_OF_INSTR();
190 }
191 
192 /****************************************************************************
193  * REMARKS:
194  * Handles opcode 0x0f,0x32
195  * ****************************************************************************/
x86emuOp2_rdmsr(u8 op2)196 static void x86emuOp2_rdmsr(u8 op2)
197 {
198   /* dummy implementation, always return 0 */
199 
200   START_OF_INSTR();
201   DECODE_PRINTF("RDMSR\n");
202   TRACE_AND_STEP();
203   M.x86.R_EDX = 0;
204   M.x86.R_EAX = 0;
205   DECODE_CLEAR_SEGOVR();
206   END_OF_INSTR();
207 }
208 
209 #define xorl(a,b)   (((a) && !(b)) || (!(a) && (b)))
210 
211 /****************************************************************************
212 REMARKS:
213 Handles opcode 0x0f,0x80-0x8F
214 ****************************************************************************/
x86emu_check_jump_condition(u8 op)215 int x86emu_check_jump_condition(u8 op)
216 {
217     switch (op) {
218       case 0x0:
219         DECODE_PRINTF("JO\t");
220         return ACCESS_FLAG(F_OF);
221       case 0x1:
222         DECODE_PRINTF("JNO\t");
223         return !ACCESS_FLAG(F_OF);
224         break;
225       case 0x2:
226         DECODE_PRINTF("JB\t");
227         return ACCESS_FLAG(F_CF);
228         break;
229       case 0x3:
230         DECODE_PRINTF("JNB\t");
231         return !ACCESS_FLAG(F_CF);
232         break;
233       case 0x4:
234         DECODE_PRINTF("JZ\t");
235         return ACCESS_FLAG(F_ZF);
236         break;
237       case 0x5:
238         DECODE_PRINTF("JNZ\t");
239         return !ACCESS_FLAG(F_ZF);
240         break;
241       case 0x6:
242         DECODE_PRINTF("JBE\t");
243         return ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF);
244         break;
245       case 0x7:
246         DECODE_PRINTF("JNBE\t");
247         return !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
248         break;
249       case 0x8:
250         DECODE_PRINTF("JS\t");
251         return ACCESS_FLAG(F_SF);
252         break;
253       case 0x9:
254         DECODE_PRINTF("JNS\t");
255         return !ACCESS_FLAG(F_SF);
256         break;
257       case 0xa:
258         DECODE_PRINTF("JP\t");
259         return ACCESS_FLAG(F_PF);
260         break;
261       case 0xb:
262         DECODE_PRINTF("JNP\t");
263         return !ACCESS_FLAG(F_PF);
264         break;
265       case 0xc:
266         DECODE_PRINTF("JL\t");
267         return xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
268         break;
269       case 0xd:
270         DECODE_PRINTF("JNL\t");
271         return !xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
272         break;
273       case 0xe:
274         DECODE_PRINTF("JLE\t");
275         return (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
276                 ACCESS_FLAG(F_ZF));
277         break;
278       default:
279         DECODE_PRINTF("JNLE\t");
280         return !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
281                  ACCESS_FLAG(F_ZF));
282     }
283 }
284 
x86emuOp2_long_jump(u8 op2)285 static void x86emuOp2_long_jump(u8 op2)
286 {
287     s32 target;
288     int cond;
289 
290     /* conditional jump to word offset. */
291     START_OF_INSTR();
292     cond = x86emu_check_jump_condition(op2 & 0xF);
293     target = (s16) fetch_word_imm();
294     target += (s16) M.x86.R_IP;
295     DECODE_PRINTF2("%04x\n", target);
296     TRACE_AND_STEP();
297     if (cond) {
298         M.x86.R_IP = (u16)target;
299 	JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, " LONG COND ");
300     }
301     DECODE_CLEAR_SEGOVR();
302     END_OF_INSTR();
303 }
304 
305 /****************************************************************************
306 REMARKS:
307 Handles opcode 0x0f,0xC8-0xCF
308 ****************************************************************************/
x86emu_bswap(s32 reg)309 static s32 x86emu_bswap(s32 reg)
310 {
311    // perform the byte swap
312    s32 temp = reg;
313    reg = (temp & 0xFF000000) >> 24 |
314          (temp & 0xFF0000) >> 8 |
315          (temp & 0xFF00) << 8 |
316          (temp & 0xFF) << 24;
317    return reg;
318 }
319 
x86emuOp2_bswap(u8 op2)320 static void x86emuOp2_bswap(u8 op2)
321 {
322     /* byte swap 32 bit register */
323     START_OF_INSTR();
324     DECODE_PRINTF("BSWAP\t");
325     switch (op2) {
326       case 0xc8:
327         DECODE_PRINTF("EAX\n");
328         M.x86.R_EAX = x86emu_bswap(M.x86.R_EAX);
329         break;
330       case 0xc9:
331         DECODE_PRINTF("ECX\n");
332         M.x86.R_ECX = x86emu_bswap(M.x86.R_ECX);
333         break;
334       case 0xca:
335         DECODE_PRINTF("EDX\n");
336         M.x86.R_EDX = x86emu_bswap(M.x86.R_EDX);
337         break;
338       case 0xcb:
339         DECODE_PRINTF("EBX\n");
340         M.x86.R_EBX = x86emu_bswap(M.x86.R_EBX);
341         break;
342       case 0xcc:
343         DECODE_PRINTF("ESP\n");
344         M.x86.R_ESP = x86emu_bswap(M.x86.R_ESP);
345         break;
346       case 0xcd:
347         DECODE_PRINTF("EBP\n");
348         M.x86.R_EBP = x86emu_bswap(M.x86.R_EBP);
349         break;
350       case 0xce:
351         DECODE_PRINTF("ESI\n");
352         M.x86.R_ESI = x86emu_bswap(M.x86.R_ESI);
353         break;
354       case 0xcf:
355         DECODE_PRINTF("EDI\n");
356         M.x86.R_EDI = x86emu_bswap(M.x86.R_EDI);
357         break;
358     }
359     TRACE_AND_STEP();
360     DECODE_CLEAR_SEGOVR();
361     END_OF_INSTR();
362 }
363 
364 /****************************************************************************
365 REMARKS:
366 Handles opcode 0x0f,0x90-0x9F
367 ****************************************************************************/
x86emuOp2_set_byte(u8 op2)368 static void x86emuOp2_set_byte(u8 op2)
369 {
370     int mod, rl, rh;
371     uint destoffset;
372     u8  *destreg;
373     const char *X86EMU_DEBUG_ONLY(name) = NULL;
374     int cond = 0;
375 
376     START_OF_INSTR();
377     switch (op2) {
378       case 0x90:
379         name = "SETO\t";
380         cond =  ACCESS_FLAG(F_OF);
381         break;
382       case 0x91:
383         name = "SETNO\t";
384         cond = !ACCESS_FLAG(F_OF);
385         break;
386       case 0x92:
387         name = "SETB\t";
388         cond = ACCESS_FLAG(F_CF);
389         break;
390       case 0x93:
391         name = "SETNB\t";
392         cond = !ACCESS_FLAG(F_CF);
393         break;
394       case 0x94:
395         name = "SETZ\t";
396         cond = ACCESS_FLAG(F_ZF);
397         break;
398       case 0x95:
399         name = "SETNZ\t";
400         cond = !ACCESS_FLAG(F_ZF);
401         break;
402       case 0x96:
403         name = "SETBE\t";
404         cond = ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF);
405         break;
406       case 0x97:
407         name = "SETNBE\t";
408         cond = !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
409         break;
410       case 0x98:
411         name = "SETS\t";
412         cond = ACCESS_FLAG(F_SF);
413         break;
414       case 0x99:
415         name = "SETNS\t";
416         cond = !ACCESS_FLAG(F_SF);
417         break;
418       case 0x9a:
419         name = "SETP\t";
420         cond = ACCESS_FLAG(F_PF);
421         break;
422       case 0x9b:
423         name = "SETNP\t";
424         cond = !ACCESS_FLAG(F_PF);
425         break;
426       case 0x9c:
427         name = "SETL\t";
428         cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
429         break;
430       case 0x9d:
431         name = "SETNL\t";
432         cond = !xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
433         break;
434       case 0x9e:
435         name = "SETLE\t";
436         cond = (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
437                 ACCESS_FLAG(F_ZF));
438         break;
439       case 0x9f:
440         name = "SETNLE\t";
441         cond = !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
442                  ACCESS_FLAG(F_ZF));
443         break;
444     }
445     DECODE_PRINTF(name);
446     FETCH_DECODE_MODRM(mod, rh, rl);
447     if (mod < 3) {
448         destoffset = decode_rmXX_address(mod, rl);
449         TRACE_AND_STEP();
450         store_data_byte(destoffset, cond ? 0x01 : 0x00);
451     } else {                     /* register to register */
452         destreg = DECODE_RM_BYTE_REGISTER(rl);
453         TRACE_AND_STEP();
454         *destreg = cond ? 0x01 : 0x00;
455     }
456     DECODE_CLEAR_SEGOVR();
457     END_OF_INSTR();
458 }
459 
460 /****************************************************************************
461 REMARKS:
462 Handles opcode 0x0f,0xa0
463 ****************************************************************************/
x86emuOp2_push_FS(u8 X86EMU_UNUSED (op2))464 static void x86emuOp2_push_FS(u8 X86EMU_UNUSED(op2))
465 {
466     START_OF_INSTR();
467     DECODE_PRINTF("PUSH\tFS\n");
468     TRACE_AND_STEP();
469     push_word(M.x86.R_FS);
470     DECODE_CLEAR_SEGOVR();
471     END_OF_INSTR();
472 }
473 
474 /****************************************************************************
475 REMARKS:
476 Handles opcode 0x0f,0xa1
477 ****************************************************************************/
x86emuOp2_pop_FS(u8 X86EMU_UNUSED (op2))478 static void x86emuOp2_pop_FS(u8 X86EMU_UNUSED(op2))
479 {
480     START_OF_INSTR();
481     DECODE_PRINTF("POP\tFS\n");
482     TRACE_AND_STEP();
483     M.x86.R_FS = pop_word();
484     DECODE_CLEAR_SEGOVR();
485     END_OF_INSTR();
486 }
487 
488 /****************************************************************************
489 REMARKS: CPUID takes EAX/ECX as inputs, writes EAX/EBX/ECX/EDX as output
490 Handles opcode 0x0f,0xa2
491 ****************************************************************************/
x86emuOp2_cpuid(u8 X86EMU_UNUSED (op2))492 static void x86emuOp2_cpuid(u8 X86EMU_UNUSED(op2))
493 {
494     START_OF_INSTR();
495     DECODE_PRINTF("CPUID\n");
496     TRACE_AND_STEP();
497     x86emu_cpuid();
498     DECODE_CLEAR_SEGOVR();
499     END_OF_INSTR();
500 }
501 
502 /****************************************************************************
503 REMARKS:
504 Handles opcode 0x0f,0xa3
505 ****************************************************************************/
x86emuOp2_bt_R(u8 X86EMU_UNUSED (op2))506 static void x86emuOp2_bt_R(u8 X86EMU_UNUSED(op2))
507 {
508     int mod, rl, rh;
509     uint srcoffset;
510     int bit,disp;
511 
512     START_OF_INSTR();
513     DECODE_PRINTF("BT\t");
514     FETCH_DECODE_MODRM(mod, rh, rl);
515     if (mod < 3) {
516         srcoffset = decode_rmXX_address(mod, rl);
517         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
518             u32 srcval;
519             u32 *shiftreg;
520 
521             DECODE_PRINTF(",");
522             shiftreg = DECODE_RM_LONG_REGISTER(rh);
523             TRACE_AND_STEP();
524             bit = *shiftreg & 0x1F;
525             disp = (s16)*shiftreg >> 5;
526             srcval = fetch_data_long(srcoffset+disp);
527             CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
528         } else {
529             u16 srcval;
530             u16 *shiftreg;
531 
532             DECODE_PRINTF(",");
533             shiftreg = DECODE_RM_WORD_REGISTER(rh);
534             TRACE_AND_STEP();
535             bit = *shiftreg & 0xF;
536             disp = (s16)*shiftreg >> 4;
537             srcval = fetch_data_word(srcoffset+disp);
538             CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
539         }
540     } else {                     /* register to register */
541         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
542             u32 *srcreg,*shiftreg;
543 
544             srcreg = DECODE_RM_LONG_REGISTER(rl);
545             DECODE_PRINTF(",");
546             shiftreg = DECODE_RM_LONG_REGISTER(rh);
547             TRACE_AND_STEP();
548             bit = *shiftreg & 0x1F;
549             CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit),F_CF);
550         } else {
551             u16 *srcreg,*shiftreg;
552 
553             srcreg = DECODE_RM_WORD_REGISTER(rl);
554             DECODE_PRINTF(",");
555             shiftreg = DECODE_RM_WORD_REGISTER(rh);
556             TRACE_AND_STEP();
557             bit = *shiftreg & 0xF;
558             CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit),F_CF);
559         }
560     }
561     DECODE_CLEAR_SEGOVR();
562     END_OF_INSTR();
563 }
564 
565 /****************************************************************************
566 REMARKS:
567 Handles opcode 0x0f,0xa4
568 ****************************************************************************/
x86emuOp2_shld_IMM(u8 X86EMU_UNUSED (op2))569 static void x86emuOp2_shld_IMM(u8 X86EMU_UNUSED(op2))
570 {
571     int mod, rl, rh;
572     uint destoffset;
573     u8 shift;
574 
575     START_OF_INSTR();
576     DECODE_PRINTF("SHLD\t");
577     FETCH_DECODE_MODRM(mod, rh, rl);
578     if (mod < 3) {
579         destoffset = decode_rmXX_address(mod, rl);
580         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
581             u32 destval;
582             u32 *shiftreg;
583 
584             DECODE_PRINTF(",");
585             shiftreg = DECODE_RM_LONG_REGISTER(rh);
586             DECODE_PRINTF(",");
587             shift = fetch_byte_imm();
588             DECODE_PRINTF2("%d\n", shift);
589             TRACE_AND_STEP();
590             destval = fetch_data_long(destoffset);
591             destval = shld_long(destval,*shiftreg,shift);
592             store_data_long(destoffset, destval);
593         } else {
594             u16 destval;
595             u16 *shiftreg;
596 
597             DECODE_PRINTF(",");
598             shiftreg = DECODE_RM_WORD_REGISTER(rh);
599             DECODE_PRINTF(",");
600             shift = fetch_byte_imm();
601             DECODE_PRINTF2("%d\n", shift);
602             TRACE_AND_STEP();
603             destval = fetch_data_word(destoffset);
604             destval = shld_word(destval,*shiftreg,shift);
605             store_data_word(destoffset, destval);
606         }
607     } else {                     /* register to register */
608         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
609             u32 *destreg,*shiftreg;
610 
611             destreg = DECODE_RM_LONG_REGISTER(rl);
612             DECODE_PRINTF(",");
613             shiftreg = DECODE_RM_LONG_REGISTER(rh);
614             DECODE_PRINTF(",");
615             shift = fetch_byte_imm();
616             DECODE_PRINTF2("%d\n", shift);
617             TRACE_AND_STEP();
618             *destreg = shld_long(*destreg,*shiftreg,shift);
619         } else {
620             u16 *destreg,*shiftreg;
621 
622             destreg = DECODE_RM_WORD_REGISTER(rl);
623             DECODE_PRINTF(",");
624             shiftreg = DECODE_RM_WORD_REGISTER(rh);
625             DECODE_PRINTF(",");
626             shift = fetch_byte_imm();
627             DECODE_PRINTF2("%d\n", shift);
628             TRACE_AND_STEP();
629             *destreg = shld_word(*destreg,*shiftreg,shift);
630         }
631     }
632     DECODE_CLEAR_SEGOVR();
633     END_OF_INSTR();
634 }
635 
636 /****************************************************************************
637 REMARKS:
638 Handles opcode 0x0f,0xa5
639 ****************************************************************************/
x86emuOp2_shld_CL(u8 X86EMU_UNUSED (op2))640 static void x86emuOp2_shld_CL(u8 X86EMU_UNUSED(op2))
641 {
642     int mod, rl, rh;
643     uint destoffset;
644 
645     START_OF_INSTR();
646     DECODE_PRINTF("SHLD\t");
647     FETCH_DECODE_MODRM(mod, rh, rl);
648     if (mod < 3) {
649         destoffset = decode_rmXX_address(mod, rl);
650         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
651             u32 destval;
652             u32 *shiftreg;
653 
654             DECODE_PRINTF(",");
655             shiftreg = DECODE_RM_LONG_REGISTER(rh);
656             DECODE_PRINTF(",CL\n");
657             TRACE_AND_STEP();
658             destval = fetch_data_long(destoffset);
659             destval = shld_long(destval,*shiftreg,M.x86.R_CL);
660             store_data_long(destoffset, destval);
661         } else {
662             u16 destval;
663             u16 *shiftreg;
664 
665             DECODE_PRINTF(",");
666             shiftreg = DECODE_RM_WORD_REGISTER(rh);
667             DECODE_PRINTF(",CL\n");
668             TRACE_AND_STEP();
669             destval = fetch_data_word(destoffset);
670             destval = shld_word(destval,*shiftreg,M.x86.R_CL);
671             store_data_word(destoffset, destval);
672         }
673     } else {                     /* register to register */
674         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
675             u32 *destreg,*shiftreg;
676 
677             destreg = DECODE_RM_LONG_REGISTER(rl);
678             DECODE_PRINTF(",");
679             shiftreg = DECODE_RM_LONG_REGISTER(rh);
680             DECODE_PRINTF(",CL\n");
681             TRACE_AND_STEP();
682             *destreg = shld_long(*destreg,*shiftreg,M.x86.R_CL);
683         } else {
684             u16 *destreg,*shiftreg;
685 
686             destreg = DECODE_RM_WORD_REGISTER(rl);
687             DECODE_PRINTF(",");
688             shiftreg = DECODE_RM_WORD_REGISTER(rh);
689             DECODE_PRINTF(",CL\n");
690             TRACE_AND_STEP();
691             *destreg = shld_word(*destreg,*shiftreg,M.x86.R_CL);
692         }
693     }
694     DECODE_CLEAR_SEGOVR();
695     END_OF_INSTR();
696 }
697 
698 /****************************************************************************
699 REMARKS:
700 Handles opcode 0x0f,0xa8
701 ****************************************************************************/
x86emuOp2_push_GS(u8 X86EMU_UNUSED (op2))702 static void x86emuOp2_push_GS(u8 X86EMU_UNUSED(op2))
703 {
704     START_OF_INSTR();
705     DECODE_PRINTF("PUSH\tGS\n");
706     TRACE_AND_STEP();
707     push_word(M.x86.R_GS);
708     DECODE_CLEAR_SEGOVR();
709     END_OF_INSTR();
710 }
711 
712 /****************************************************************************
713 REMARKS:
714 Handles opcode 0x0f,0xa9
715 ****************************************************************************/
x86emuOp2_pop_GS(u8 X86EMU_UNUSED (op2))716 static void x86emuOp2_pop_GS(u8 X86EMU_UNUSED(op2))
717 {
718     START_OF_INSTR();
719     DECODE_PRINTF("POP\tGS\n");
720     TRACE_AND_STEP();
721     M.x86.R_GS = pop_word();
722     DECODE_CLEAR_SEGOVR();
723     END_OF_INSTR();
724 }
725 
726 /****************************************************************************
727 REMARKS:
728 Handles opcode 0x0f,0xab
729 ****************************************************************************/
x86emuOp2_bts_R(u8 X86EMU_UNUSED (op2))730 static void x86emuOp2_bts_R(u8 X86EMU_UNUSED(op2))
731 {
732     int mod, rl, rh;
733     uint srcoffset;
734     int bit,disp;
735 
736     START_OF_INSTR();
737     DECODE_PRINTF("BTS\t");
738     FETCH_DECODE_MODRM(mod, rh, rl);
739     if (mod < 3) {
740         srcoffset = decode_rmXX_address(mod, rl);
741         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
742             u32 srcval,mask;
743             u32 *shiftreg;
744 
745             DECODE_PRINTF(",");
746             shiftreg = DECODE_RM_LONG_REGISTER(rh);
747             TRACE_AND_STEP();
748             bit = *shiftreg & 0x1F;
749             disp = (s16)*shiftreg >> 5;
750             srcval = fetch_data_long(srcoffset+disp);
751             mask = (0x1 << bit);
752             CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
753             store_data_long(srcoffset+disp, srcval | mask);
754         } else {
755             u16 srcval,mask;
756             u16 *shiftreg;
757 
758             DECODE_PRINTF(",");
759             shiftreg = DECODE_RM_WORD_REGISTER(rh);
760             TRACE_AND_STEP();
761             bit = *shiftreg & 0xF;
762             disp = (s16)*shiftreg >> 4;
763             srcval = fetch_data_word(srcoffset+disp);
764             mask = (u16)(0x1 << bit);
765             CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
766             store_data_word(srcoffset+disp, srcval | mask);
767         }
768     } else {                     /* register to register */
769         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
770             u32 *srcreg,*shiftreg;
771             u32 mask;
772 
773             srcreg = DECODE_RM_LONG_REGISTER(rl);
774             DECODE_PRINTF(",");
775             shiftreg = DECODE_RM_LONG_REGISTER(rh);
776             TRACE_AND_STEP();
777             bit = *shiftreg & 0x1F;
778             mask = (0x1 << bit);
779             CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
780             *srcreg |= mask;
781         } else {
782             u16 *srcreg,*shiftreg;
783             u16 mask;
784 
785             srcreg = DECODE_RM_WORD_REGISTER(rl);
786             DECODE_PRINTF(",");
787             shiftreg = DECODE_RM_WORD_REGISTER(rh);
788             TRACE_AND_STEP();
789             bit = *shiftreg & 0xF;
790             mask = (u16)(0x1 << bit);
791             CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
792             *srcreg |= mask;
793         }
794     }
795     DECODE_CLEAR_SEGOVR();
796     END_OF_INSTR();
797 }
798 
799 /****************************************************************************
800 REMARKS:
801 Handles opcode 0x0f,0xac
802 ****************************************************************************/
x86emuOp2_shrd_IMM(u8 X86EMU_UNUSED (op2))803 static void x86emuOp2_shrd_IMM(u8 X86EMU_UNUSED(op2))
804 {
805     int mod, rl, rh;
806     uint destoffset;
807     u8 shift;
808 
809     START_OF_INSTR();
810     DECODE_PRINTF("SHLD\t");
811     FETCH_DECODE_MODRM(mod, rh, rl);
812     if (mod < 3) {
813         destoffset = decode_rmXX_address(mod, rl);
814         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
815             u32 destval;
816             u32 *shiftreg;
817 
818             DECODE_PRINTF(",");
819             shiftreg = DECODE_RM_LONG_REGISTER(rh);
820             DECODE_PRINTF(",");
821             shift = fetch_byte_imm();
822             DECODE_PRINTF2("%d\n", shift);
823             TRACE_AND_STEP();
824             destval = fetch_data_long(destoffset);
825             destval = shrd_long(destval,*shiftreg,shift);
826             store_data_long(destoffset, destval);
827         } else {
828             u16 destval;
829             u16 *shiftreg;
830 
831             DECODE_PRINTF(",");
832             shiftreg = DECODE_RM_WORD_REGISTER(rh);
833             DECODE_PRINTF(",");
834             shift = fetch_byte_imm();
835             DECODE_PRINTF2("%d\n", shift);
836             TRACE_AND_STEP();
837             destval = fetch_data_word(destoffset);
838             destval = shrd_word(destval,*shiftreg,shift);
839             store_data_word(destoffset, destval);
840         }
841     } else {                     /* register to register */
842         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
843             u32 *destreg,*shiftreg;
844 
845             destreg = DECODE_RM_LONG_REGISTER(rl);
846             DECODE_PRINTF(",");
847             shiftreg = DECODE_RM_LONG_REGISTER(rh);
848             DECODE_PRINTF(",");
849             shift = fetch_byte_imm();
850             DECODE_PRINTF2("%d\n", shift);
851             TRACE_AND_STEP();
852             *destreg = shrd_long(*destreg,*shiftreg,shift);
853         } else {
854             u16 *destreg,*shiftreg;
855 
856             destreg = DECODE_RM_WORD_REGISTER(rl);
857             DECODE_PRINTF(",");
858             shiftreg = DECODE_RM_WORD_REGISTER(rh);
859             DECODE_PRINTF(",");
860             shift = fetch_byte_imm();
861             DECODE_PRINTF2("%d\n", shift);
862             TRACE_AND_STEP();
863             *destreg = shrd_word(*destreg,*shiftreg,shift);
864         }
865     }
866     DECODE_CLEAR_SEGOVR();
867     END_OF_INSTR();
868 }
869 
870 /****************************************************************************
871 REMARKS:
872 Handles opcode 0x0f,0xad
873 ****************************************************************************/
x86emuOp2_shrd_CL(u8 X86EMU_UNUSED (op2))874 static void x86emuOp2_shrd_CL(u8 X86EMU_UNUSED(op2))
875 {
876     int mod, rl, rh;
877     uint destoffset;
878 
879     START_OF_INSTR();
880     DECODE_PRINTF("SHLD\t");
881     FETCH_DECODE_MODRM(mod, rh, rl);
882     if (mod < 3) {
883         destoffset = decode_rmXX_address(mod, rl);
884         DECODE_PRINTF(",");
885         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
886             u32 destval;
887             u32 *shiftreg;
888 
889             shiftreg = DECODE_RM_LONG_REGISTER(rh);
890             DECODE_PRINTF(",CL\n");
891             TRACE_AND_STEP();
892             destval = fetch_data_long(destoffset);
893             destval = shrd_long(destval,*shiftreg,M.x86.R_CL);
894             store_data_long(destoffset, destval);
895         } else {
896             u16 destval;
897             u16 *shiftreg;
898 
899             shiftreg = DECODE_RM_WORD_REGISTER(rh);
900             DECODE_PRINTF(",CL\n");
901             TRACE_AND_STEP();
902             destval = fetch_data_word(destoffset);
903             destval = shrd_word(destval,*shiftreg,M.x86.R_CL);
904             store_data_word(destoffset, destval);
905         }
906     } else {                     /* register to register */
907         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
908             u32 *destreg,*shiftreg;
909 
910             destreg = DECODE_RM_LONG_REGISTER(rl);
911             DECODE_PRINTF(",");
912             shiftreg = DECODE_RM_LONG_REGISTER(rh);
913             DECODE_PRINTF(",CL\n");
914             TRACE_AND_STEP();
915             *destreg = shrd_long(*destreg,*shiftreg,M.x86.R_CL);
916         } else {
917             u16 *destreg,*shiftreg;
918 
919             destreg = DECODE_RM_WORD_REGISTER(rl);
920             DECODE_PRINTF(",");
921             shiftreg = DECODE_RM_WORD_REGISTER(rh);
922             DECODE_PRINTF(",CL\n");
923             TRACE_AND_STEP();
924             *destreg = shrd_word(*destreg,*shiftreg,M.x86.R_CL);
925         }
926     }
927     DECODE_CLEAR_SEGOVR();
928     END_OF_INSTR();
929 }
930 
931 /****************************************************************************
932 REMARKS:
933 Handles opcode 0x0f,0xaf
934 ****************************************************************************/
x86emuOp2_imul_R_RM(u8 X86EMU_UNUSED (op2))935 static void x86emuOp2_imul_R_RM(u8 X86EMU_UNUSED(op2))
936 {
937     int mod, rl, rh;
938     uint srcoffset;
939 
940     START_OF_INSTR();
941     DECODE_PRINTF("IMUL\t");
942     FETCH_DECODE_MODRM(mod, rh, rl);
943     if (mod < 3) {
944         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
945             u32 *destreg;
946             u32 srcval;
947             u32 res_lo,res_hi;
948 
949             destreg = DECODE_RM_LONG_REGISTER(rh);
950             DECODE_PRINTF(",");
951             srcoffset = decode_rmXX_address(mod, rl);
952             srcval = fetch_data_long(srcoffset);
953             TRACE_AND_STEP();
954             imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)srcval);
955             if (res_hi != 0) {
956                 SET_FLAG(F_CF);
957                 SET_FLAG(F_OF);
958             } else {
959                 CLEAR_FLAG(F_CF);
960                 CLEAR_FLAG(F_OF);
961             }
962             *destreg = (u32)res_lo;
963         } else {
964             u16 *destreg;
965             u16 srcval;
966             u32 res;
967 
968             destreg = DECODE_RM_WORD_REGISTER(rh);
969             DECODE_PRINTF(",");
970             srcoffset = decode_rmXX_address(mod, rl);
971             srcval = fetch_data_word(srcoffset);
972             TRACE_AND_STEP();
973             res = (s16)*destreg * (s16)srcval;
974             if (res > 0xFFFF) {
975                 SET_FLAG(F_CF);
976                 SET_FLAG(F_OF);
977             } else {
978                 CLEAR_FLAG(F_CF);
979                 CLEAR_FLAG(F_OF);
980             }
981             *destreg = (u16)res;
982         }
983     } else {                     /* register to register */
984         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
985             u32 *destreg,*srcreg;
986             u32 res_lo,res_hi;
987 
988             destreg = DECODE_RM_LONG_REGISTER(rh);
989             DECODE_PRINTF(",");
990             srcreg = DECODE_RM_LONG_REGISTER(rl);
991             TRACE_AND_STEP();
992             imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)*srcreg);
993             if (res_hi != 0) {
994                 SET_FLAG(F_CF);
995                 SET_FLAG(F_OF);
996             } else {
997                 CLEAR_FLAG(F_CF);
998                 CLEAR_FLAG(F_OF);
999             }
1000             *destreg = (u32)res_lo;
1001         } else {
1002             u16 *destreg,*srcreg;
1003             u32 res;
1004 
1005             destreg = DECODE_RM_WORD_REGISTER(rh);
1006             DECODE_PRINTF(",");
1007             srcreg = DECODE_RM_WORD_REGISTER(rl);
1008             res = (s16)*destreg * (s16)*srcreg;
1009             if (res > 0xFFFF) {
1010                 SET_FLAG(F_CF);
1011                 SET_FLAG(F_OF);
1012             } else {
1013                 CLEAR_FLAG(F_CF);
1014                 CLEAR_FLAG(F_OF);
1015             }
1016             *destreg = (u16)res;
1017         }
1018     }
1019     DECODE_CLEAR_SEGOVR();
1020     END_OF_INSTR();
1021 }
1022 
1023 /****************************************************************************
1024 REMARKS:
1025 Handles opcode 0x0f,0xb2
1026 ****************************************************************************/
x86emuOp2_lss_R_IMM(u8 X86EMU_UNUSED (op2))1027 static void x86emuOp2_lss_R_IMM(u8 X86EMU_UNUSED(op2))
1028 {
1029     int mod, rh, rl;
1030     u16 *dstreg;
1031     uint srcoffset;
1032 
1033     START_OF_INSTR();
1034     DECODE_PRINTF("LSS\t");
1035     FETCH_DECODE_MODRM(mod, rh, rl);
1036     if (mod < 3) {
1037         dstreg = DECODE_RM_WORD_REGISTER(rh);
1038         DECODE_PRINTF(",");
1039         srcoffset = decode_rmXX_address(mod, rl);
1040         DECODE_PRINTF("\n");
1041         TRACE_AND_STEP();
1042         *dstreg = fetch_data_word(srcoffset);
1043         M.x86.R_SS = fetch_data_word(srcoffset + 2);
1044     } else {                     /* register to register */
1045         /* UNDEFINED! */
1046         TRACE_AND_STEP();
1047     }
1048     DECODE_CLEAR_SEGOVR();
1049     END_OF_INSTR();
1050 }
1051 
1052 /****************************************************************************
1053 REMARKS:
1054 Handles opcode 0x0f,0xb3
1055 ****************************************************************************/
x86emuOp2_btr_R(u8 X86EMU_UNUSED (op2))1056 static void x86emuOp2_btr_R(u8 X86EMU_UNUSED(op2))
1057 {
1058     int mod, rl, rh;
1059     uint srcoffset;
1060     int bit,disp;
1061 
1062     START_OF_INSTR();
1063     DECODE_PRINTF("BTR\t");
1064     FETCH_DECODE_MODRM(mod, rh, rl);
1065     if (mod < 3) {
1066         srcoffset = decode_rmXX_address(mod, rl);
1067         DECODE_PRINTF(",");
1068         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1069             u32 srcval,mask;
1070             u32 *shiftreg;
1071 
1072             shiftreg = DECODE_RM_LONG_REGISTER(rh);
1073             TRACE_AND_STEP();
1074             bit = *shiftreg & 0x1F;
1075             disp = (s16)*shiftreg >> 5;
1076             srcval = fetch_data_long(srcoffset+disp);
1077             mask = (0x1 << bit);
1078             CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1079             store_data_long(srcoffset+disp, srcval & ~mask);
1080         } else {
1081             u16 srcval,mask;
1082             u16 *shiftreg;
1083 
1084             shiftreg = DECODE_RM_WORD_REGISTER(rh);
1085             TRACE_AND_STEP();
1086             bit = *shiftreg & 0xF;
1087             disp = (s16)*shiftreg >> 4;
1088             srcval = fetch_data_word(srcoffset+disp);
1089             mask = (u16)(0x1 << bit);
1090             CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1091             store_data_word(srcoffset+disp, (u16)(srcval & ~mask));
1092         }
1093     } else {                     /* register to register */
1094         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1095             u32 *srcreg,*shiftreg;
1096             u32 mask;
1097 
1098             srcreg = DECODE_RM_LONG_REGISTER(rl);
1099             DECODE_PRINTF(",");
1100             shiftreg = DECODE_RM_LONG_REGISTER(rh);
1101             TRACE_AND_STEP();
1102             bit = *shiftreg & 0x1F;
1103             mask = (0x1 << bit);
1104             CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1105             *srcreg &= ~mask;
1106         } else {
1107             u16 *srcreg,*shiftreg;
1108             u16 mask;
1109 
1110             srcreg = DECODE_RM_WORD_REGISTER(rl);
1111             DECODE_PRINTF(",");
1112             shiftreg = DECODE_RM_WORD_REGISTER(rh);
1113             TRACE_AND_STEP();
1114             bit = *shiftreg & 0xF;
1115             mask = (u16)(0x1 << bit);
1116             CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1117             *srcreg &= ~mask;
1118         }
1119     }
1120     DECODE_CLEAR_SEGOVR();
1121     END_OF_INSTR();
1122 }
1123 
1124 /****************************************************************************
1125 REMARKS:
1126 Handles opcode 0x0f,0xb4
1127 ****************************************************************************/
x86emuOp2_lfs_R_IMM(u8 X86EMU_UNUSED (op2))1128 static void x86emuOp2_lfs_R_IMM(u8 X86EMU_UNUSED(op2))
1129 {
1130     int mod, rh, rl;
1131     u16 *dstreg;
1132     uint srcoffset;
1133 
1134     START_OF_INSTR();
1135     DECODE_PRINTF("LFS\t");
1136     FETCH_DECODE_MODRM(mod, rh, rl);
1137     if (mod < 3) {
1138         dstreg = DECODE_RM_WORD_REGISTER(rh);
1139         DECODE_PRINTF(",");
1140         srcoffset = decode_rmXX_address(mod, rl);
1141         DECODE_PRINTF("\n");
1142         TRACE_AND_STEP();
1143         *dstreg = fetch_data_word(srcoffset);
1144         M.x86.R_FS = fetch_data_word(srcoffset + 2);
1145     } else {                     /* register to register */
1146         /* UNDEFINED! */
1147         TRACE_AND_STEP();
1148     }
1149     DECODE_CLEAR_SEGOVR();
1150     END_OF_INSTR();
1151 }
1152 
1153 /****************************************************************************
1154 REMARKS:
1155 Handles opcode 0x0f,0xb5
1156 ****************************************************************************/
x86emuOp2_lgs_R_IMM(u8 X86EMU_UNUSED (op2))1157 static void x86emuOp2_lgs_R_IMM(u8 X86EMU_UNUSED(op2))
1158 {
1159     int mod, rh, rl;
1160     u16 *dstreg;
1161     uint srcoffset;
1162 
1163     START_OF_INSTR();
1164     DECODE_PRINTF("LGS\t");
1165     FETCH_DECODE_MODRM(mod, rh, rl);
1166     if (mod < 3) {
1167         dstreg = DECODE_RM_WORD_REGISTER(rh);
1168         DECODE_PRINTF(",");
1169         srcoffset = decode_rmXX_address(mod, rl);
1170         DECODE_PRINTF("\n");
1171         TRACE_AND_STEP();
1172         *dstreg = fetch_data_word(srcoffset);
1173         M.x86.R_GS = fetch_data_word(srcoffset + 2);
1174     } else {                     /* register to register */
1175         /* UNDEFINED! */
1176         TRACE_AND_STEP();
1177     }
1178     DECODE_CLEAR_SEGOVR();
1179     END_OF_INSTR();
1180 }
1181 
1182 /****************************************************************************
1183 REMARKS:
1184 Handles opcode 0x0f,0xb6
1185 ****************************************************************************/
x86emuOp2_movzx_byte_R_RM(u8 X86EMU_UNUSED (op2))1186 static void x86emuOp2_movzx_byte_R_RM(u8 X86EMU_UNUSED(op2))
1187 {
1188     int mod, rl, rh;
1189     uint srcoffset;
1190 
1191     START_OF_INSTR();
1192     DECODE_PRINTF("MOVZX\t");
1193     FETCH_DECODE_MODRM(mod, rh, rl);
1194     if (mod < 3) {
1195         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1196             u32 *destreg;
1197             u32 srcval;
1198 
1199             destreg = DECODE_RM_LONG_REGISTER(rh);
1200             DECODE_PRINTF(",");
1201             srcoffset = decode_rmXX_address(mod, rl);
1202             srcval = fetch_data_byte(srcoffset);
1203             DECODE_PRINTF("\n");
1204             TRACE_AND_STEP();
1205             *destreg = srcval;
1206         } else {
1207             u16 *destreg;
1208             u16 srcval;
1209 
1210             destreg = DECODE_RM_WORD_REGISTER(rh);
1211             DECODE_PRINTF(",");
1212             srcoffset = decode_rmXX_address(mod, rl);
1213             srcval = fetch_data_byte(srcoffset);
1214             DECODE_PRINTF("\n");
1215             TRACE_AND_STEP();
1216             *destreg = srcval;
1217         }
1218     } else {                     /* register to register */
1219         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1220             u32 *destreg;
1221             u8  *srcreg;
1222 
1223             destreg = DECODE_RM_LONG_REGISTER(rh);
1224             DECODE_PRINTF(",");
1225             srcreg = DECODE_RM_BYTE_REGISTER(rl);
1226             DECODE_PRINTF("\n");
1227             TRACE_AND_STEP();
1228             *destreg = *srcreg;
1229         } else {
1230             u16 *destreg;
1231             u8  *srcreg;
1232 
1233             destreg = DECODE_RM_WORD_REGISTER(rh);
1234             DECODE_PRINTF(",");
1235             srcreg = DECODE_RM_BYTE_REGISTER(rl);
1236             DECODE_PRINTF("\n");
1237             TRACE_AND_STEP();
1238             *destreg = *srcreg;
1239         }
1240     }
1241     DECODE_CLEAR_SEGOVR();
1242     END_OF_INSTR();
1243 }
1244 
1245 /****************************************************************************
1246 REMARKS:
1247 Handles opcode 0x0f,0xb7
1248 ****************************************************************************/
x86emuOp2_movzx_word_R_RM(u8 X86EMU_UNUSED (op2))1249 static void x86emuOp2_movzx_word_R_RM(u8 X86EMU_UNUSED(op2))
1250 {
1251     int mod, rl, rh;
1252     uint srcoffset;
1253     u32 *destreg;
1254     u32 srcval;
1255     u16 *srcreg;
1256 
1257     START_OF_INSTR();
1258     DECODE_PRINTF("MOVZX\t");
1259     FETCH_DECODE_MODRM(mod, rh, rl);
1260     if (mod < 3) {
1261         destreg = DECODE_RM_LONG_REGISTER(rh);
1262         DECODE_PRINTF(",");
1263         srcoffset = decode_rmXX_address(mod, rl);
1264         srcval = fetch_data_word(srcoffset);
1265         DECODE_PRINTF("\n");
1266         TRACE_AND_STEP();
1267         *destreg = srcval;
1268     } else {                     /* register to register */
1269         destreg = DECODE_RM_LONG_REGISTER(rh);
1270         DECODE_PRINTF(",");
1271         srcreg = DECODE_RM_WORD_REGISTER(rl);
1272         DECODE_PRINTF("\n");
1273         TRACE_AND_STEP();
1274         *destreg = *srcreg;
1275     }
1276     DECODE_CLEAR_SEGOVR();
1277     END_OF_INSTR();
1278 }
1279 
1280 /****************************************************************************
1281 REMARKS:
1282 Handles opcode 0x0f,0xba
1283 ****************************************************************************/
x86emuOp2_btX_I(u8 X86EMU_UNUSED (op2))1284 static void x86emuOp2_btX_I(u8 X86EMU_UNUSED(op2))
1285 {
1286     int mod, rl, rh;
1287     uint srcoffset;
1288     u8 shift;
1289     int bit;
1290 
1291     START_OF_INSTR();
1292     FETCH_DECODE_MODRM(mod, rh, rl);
1293     switch (rh) {
1294     case 4:
1295         DECODE_PRINTF("BT\t");
1296         break;
1297     case 5:
1298         DECODE_PRINTF("BTS\t");
1299         break;
1300     case 6:
1301         DECODE_PRINTF("BTR\t");
1302         break;
1303     case 7:
1304         DECODE_PRINTF("BTC\t");
1305         break;
1306     default:
1307         DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n");
1308         TRACE_REGS();
1309         printf("%04x:%04x: %02X%02X ILLEGAL EXTENDED X86 OPCODE EXTENSION!\n",
1310                 M.x86.R_CS, M.x86.R_IP-3,op2, (mod<<6)|(rh<<3)|rl);
1311         HALT_SYS();
1312     }
1313     if (mod < 3) {
1314 
1315         srcoffset = decode_rmXX_address(mod, rl);
1316         shift = fetch_byte_imm();
1317         DECODE_PRINTF2(",%d\n", shift);
1318         TRACE_AND_STEP();
1319 
1320         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1321             u32 srcval, mask;
1322 
1323             bit = shift & 0x1F;
1324             srcval = fetch_data_long(srcoffset);
1325             mask = (0x1 << bit);
1326             CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1327             switch (rh) {
1328             case 5:
1329                 store_data_long(srcoffset, srcval | mask);
1330                 break;
1331             case 6:
1332                 store_data_long(srcoffset, srcval & ~mask);
1333                 break;
1334             case 7:
1335                 store_data_long(srcoffset, srcval ^ mask);
1336                 break;
1337             default:
1338                 break;
1339             }
1340         } else {
1341             u16 srcval, mask;
1342 
1343             bit = shift & 0xF;
1344             srcval = fetch_data_word(srcoffset);
1345             mask = (0x1 << bit);
1346             CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1347             switch (rh) {
1348             case 5:
1349                 store_data_word(srcoffset, srcval | mask);
1350                 break;
1351             case 6:
1352                 store_data_word(srcoffset, srcval & ~mask);
1353                 break;
1354             case 7:
1355                 store_data_word(srcoffset, srcval ^ mask);
1356                 break;
1357             default:
1358                 break;
1359             }
1360         }
1361     } else {                     /* register to register */
1362         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1363             u32 *srcreg;
1364             u32 mask;
1365 
1366             srcreg = DECODE_RM_LONG_REGISTER(rl);
1367             shift = fetch_byte_imm();
1368             DECODE_PRINTF2(",%d\n", shift);
1369             TRACE_AND_STEP();
1370             bit = shift & 0x1F;
1371             mask = (0x1 << bit);
1372             CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1373             switch (rh) {
1374             case 5:
1375                 *srcreg |= mask;
1376                 break;
1377             case 6:
1378                 *srcreg &= ~mask;
1379                 break;
1380             case 7:
1381                 *srcreg ^= mask;
1382                 break;
1383             default:
1384                 break;
1385             }
1386         } else {
1387             u16 *srcreg;
1388             u16 mask;
1389 
1390             srcreg = DECODE_RM_WORD_REGISTER(rl);
1391             shift = fetch_byte_imm();
1392             DECODE_PRINTF2(",%d\n", shift);
1393             TRACE_AND_STEP();
1394             bit = shift & 0xF;
1395             mask = (0x1 << bit);
1396             CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1397             switch (rh) {
1398             case 5:
1399                 *srcreg |= mask;
1400                 break;
1401             case 6:
1402                 *srcreg &= ~mask;
1403                 break;
1404             case 7:
1405                 *srcreg ^= mask;
1406                 break;
1407             default:
1408                 break;
1409             }
1410         }
1411     }
1412     DECODE_CLEAR_SEGOVR();
1413     END_OF_INSTR();
1414 }
1415 
1416 /****************************************************************************
1417 REMARKS:
1418 Handles opcode 0x0f,0xbb
1419 ****************************************************************************/
x86emuOp2_btc_R(u8 X86EMU_UNUSED (op2))1420 static void x86emuOp2_btc_R(u8 X86EMU_UNUSED(op2))
1421 {
1422     int mod, rl, rh;
1423     uint srcoffset;
1424     int bit,disp;
1425 
1426     START_OF_INSTR();
1427     DECODE_PRINTF("BTC\t");
1428     FETCH_DECODE_MODRM(mod, rh, rl);
1429     if (mod < 3) {
1430         srcoffset = decode_rmXX_address(mod, rl);
1431         DECODE_PRINTF(",");
1432         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1433             u32 srcval,mask;
1434             u32 *shiftreg;
1435 
1436             shiftreg = DECODE_RM_LONG_REGISTER(rh);
1437             TRACE_AND_STEP();
1438             bit = *shiftreg & 0x1F;
1439             disp = (s16)*shiftreg >> 5;
1440             srcval = fetch_data_long(srcoffset+disp);
1441             mask = (0x1 << bit);
1442             CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1443             store_data_long(srcoffset+disp, srcval ^ mask);
1444         } else {
1445             u16 srcval,mask;
1446             u16 *shiftreg;
1447 
1448             shiftreg = DECODE_RM_WORD_REGISTER(rh);
1449             TRACE_AND_STEP();
1450             bit = *shiftreg & 0xF;
1451             disp = (s16)*shiftreg >> 4;
1452             srcval = fetch_data_word(srcoffset+disp);
1453             mask = (u16)(0x1 << bit);
1454             CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1455             store_data_word(srcoffset+disp, (u16)(srcval ^ mask));
1456         }
1457     } else {                     /* register to register */
1458         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1459             u32 *srcreg,*shiftreg;
1460             u32 mask;
1461 
1462             srcreg = DECODE_RM_LONG_REGISTER(rl);
1463             DECODE_PRINTF(",");
1464             shiftreg = DECODE_RM_LONG_REGISTER(rh);
1465             TRACE_AND_STEP();
1466             bit = *shiftreg & 0x1F;
1467             mask = (0x1 << bit);
1468             CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1469             *srcreg ^= mask;
1470         } else {
1471             u16 *srcreg,*shiftreg;
1472             u16 mask;
1473 
1474             srcreg = DECODE_RM_WORD_REGISTER(rl);
1475             DECODE_PRINTF(",");
1476             shiftreg = DECODE_RM_WORD_REGISTER(rh);
1477             TRACE_AND_STEP();
1478             bit = *shiftreg & 0xF;
1479             mask = (u16)(0x1 << bit);
1480             CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1481             *srcreg ^= mask;
1482         }
1483     }
1484     DECODE_CLEAR_SEGOVR();
1485     END_OF_INSTR();
1486 }
1487 
1488 /****************************************************************************
1489 REMARKS:
1490 Handles opcode 0x0f,0xbc
1491 ****************************************************************************/
x86emuOp2_bsf(u8 X86EMU_UNUSED (op2))1492 static void x86emuOp2_bsf(u8 X86EMU_UNUSED(op2))
1493 {
1494     int mod, rl, rh;
1495     uint srcoffset;
1496 
1497     START_OF_INSTR();
1498     DECODE_PRINTF("BSF\t");
1499     FETCH_DECODE_MODRM(mod, rh, rl);
1500     if (mod < 3) {
1501         srcoffset = decode_rmXX_address(mod, rl);
1502         DECODE_PRINTF(",");
1503         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1504             u32 srcval, *dstreg;
1505 
1506             dstreg = DECODE_RM_LONG_REGISTER(rh);
1507             TRACE_AND_STEP();
1508             srcval = fetch_data_long(srcoffset);
1509             CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
1510             for (*dstreg = 0; *dstreg < 32; (*dstreg)++)
1511                 if ((srcval >> *dstreg) & 1) break;
1512         } else {
1513             u16 srcval, *dstreg;
1514 
1515             dstreg = DECODE_RM_WORD_REGISTER(rh);
1516             TRACE_AND_STEP();
1517             srcval = fetch_data_word(srcoffset);
1518             CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
1519             for (*dstreg = 0; *dstreg < 16; (*dstreg)++)
1520                 if ((srcval >> *dstreg) & 1) break;
1521         }
1522     } else {             /* register to register */
1523         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1524             u32 srcval, *dstreg;
1525 
1526             srcval = *DECODE_RM_LONG_REGISTER(rl);
1527             DECODE_PRINTF(",");
1528             dstreg = DECODE_RM_LONG_REGISTER(rh);
1529             TRACE_AND_STEP();
1530             CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
1531             for (*dstreg = 0; *dstreg < 32; (*dstreg)++)
1532                 if ((srcval >> *dstreg) & 1) break;
1533         } else {
1534             u16 srcval, *dstreg;
1535 
1536             srcval = *DECODE_RM_WORD_REGISTER(rl);
1537             DECODE_PRINTF(",");
1538             dstreg = DECODE_RM_WORD_REGISTER(rh);
1539             TRACE_AND_STEP();
1540             CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
1541             for (*dstreg = 0; *dstreg < 16; (*dstreg)++)
1542                 if ((srcval >> *dstreg) & 1) break;
1543         }
1544     }
1545     DECODE_CLEAR_SEGOVR();
1546     END_OF_INSTR();
1547 }
1548 
1549 /****************************************************************************
1550 REMARKS:
1551 Handles opcode 0x0f,0xbd
1552 ****************************************************************************/
x86emuOp2_bsr(u8 X86EMU_UNUSED (op2))1553 static void x86emuOp2_bsr(u8 X86EMU_UNUSED(op2))
1554 {
1555     int mod, rl, rh;
1556     uint srcoffset;
1557 
1558     START_OF_INSTR();
1559     DECODE_PRINTF("BSR\t");
1560     FETCH_DECODE_MODRM(mod, rh, rl);
1561     if (mod < 3) {
1562         srcoffset = decode_rmXX_address(mod, rl);
1563         DECODE_PRINTF(",");
1564         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1565             u32 srcval, *dstreg;
1566 
1567             dstreg = DECODE_RM_LONG_REGISTER(rh);
1568             TRACE_AND_STEP();
1569             srcval = fetch_data_long(srcoffset);
1570             CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
1571             for (*dstreg = 31; *dstreg > 0; (*dstreg)--)
1572                 if ((srcval >> *dstreg) & 1) break;
1573         } else {
1574             u16 srcval, *dstreg;
1575 
1576             dstreg = DECODE_RM_WORD_REGISTER(rh);
1577             TRACE_AND_STEP();
1578             srcval = fetch_data_word(srcoffset);
1579             CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
1580             for (*dstreg = 15; *dstreg > 0; (*dstreg)--)
1581                 if ((srcval >> *dstreg) & 1) break;
1582         }
1583     } else {             /* register to register */
1584         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1585             u32 srcval, *dstreg;
1586 
1587             srcval = *DECODE_RM_LONG_REGISTER(rl);
1588             DECODE_PRINTF(",");
1589             dstreg = DECODE_RM_LONG_REGISTER(rh);
1590             TRACE_AND_STEP();
1591             CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
1592             for (*dstreg = 31; *dstreg > 0; (*dstreg)--)
1593                 if ((srcval >> *dstreg) & 1) break;
1594         } else {
1595             u16 srcval, *dstreg;
1596 
1597             srcval = *DECODE_RM_WORD_REGISTER(rl);
1598             DECODE_PRINTF(",");
1599             dstreg = DECODE_RM_WORD_REGISTER(rh);
1600             TRACE_AND_STEP();
1601             CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
1602             for (*dstreg = 15; *dstreg > 0; (*dstreg)--)
1603                 if ((srcval >> *dstreg) & 1) break;
1604         }
1605     }
1606     DECODE_CLEAR_SEGOVR();
1607     END_OF_INSTR();
1608 }
1609 
1610 /****************************************************************************
1611 REMARKS:
1612 Handles opcode 0x0f,0xbe
1613 ****************************************************************************/
x86emuOp2_movsx_byte_R_RM(u8 X86EMU_UNUSED (op2))1614 static void x86emuOp2_movsx_byte_R_RM(u8 X86EMU_UNUSED(op2))
1615 {
1616     int mod, rl, rh;
1617     uint srcoffset;
1618 
1619     START_OF_INSTR();
1620     DECODE_PRINTF("MOVSX\t");
1621     FETCH_DECODE_MODRM(mod, rh, rl);
1622     if (mod < 3) {
1623         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1624             u32 *destreg;
1625             u32 srcval;
1626 
1627             destreg = DECODE_RM_LONG_REGISTER(rh);
1628             DECODE_PRINTF(",");
1629             srcoffset = decode_rmXX_address(mod, rl);
1630             srcval = (s32)((s8)fetch_data_byte(srcoffset));
1631             DECODE_PRINTF("\n");
1632             TRACE_AND_STEP();
1633             *destreg = srcval;
1634         } else {
1635             u16 *destreg;
1636             u16 srcval;
1637 
1638             destreg = DECODE_RM_WORD_REGISTER(rh);
1639             DECODE_PRINTF(",");
1640             srcoffset = decode_rmXX_address(mod, rl);
1641             srcval = (s16)((s8)fetch_data_byte(srcoffset));
1642             DECODE_PRINTF("\n");
1643             TRACE_AND_STEP();
1644             *destreg = srcval;
1645         }
1646     } else {                     /* register to register */
1647         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1648             u32 *destreg;
1649             u8  *srcreg;
1650 
1651             destreg = DECODE_RM_LONG_REGISTER(rh);
1652             DECODE_PRINTF(",");
1653             srcreg = DECODE_RM_BYTE_REGISTER(rl);
1654             DECODE_PRINTF("\n");
1655             TRACE_AND_STEP();
1656             *destreg = (s32)((s8)*srcreg);
1657         } else {
1658             u16 *destreg;
1659             u8  *srcreg;
1660 
1661             destreg = DECODE_RM_WORD_REGISTER(rh);
1662             DECODE_PRINTF(",");
1663             srcreg = DECODE_RM_BYTE_REGISTER(rl);
1664             DECODE_PRINTF("\n");
1665             TRACE_AND_STEP();
1666             *destreg = (s16)((s8)*srcreg);
1667         }
1668     }
1669     DECODE_CLEAR_SEGOVR();
1670     END_OF_INSTR();
1671 }
1672 
1673 /****************************************************************************
1674 REMARKS:
1675 Handles opcode 0x0f,0xbf
1676 ****************************************************************************/
x86emuOp2_movsx_word_R_RM(u8 X86EMU_UNUSED (op2))1677 static void x86emuOp2_movsx_word_R_RM(u8 X86EMU_UNUSED(op2))
1678 {
1679     int mod, rl, rh;
1680     uint srcoffset;
1681     u32 *destreg;
1682     u32 srcval;
1683     u16 *srcreg;
1684 
1685     START_OF_INSTR();
1686     DECODE_PRINTF("MOVSX\t");
1687     FETCH_DECODE_MODRM(mod, rh, rl);
1688     if (mod < 3) {
1689         destreg = DECODE_RM_LONG_REGISTER(rh);
1690         DECODE_PRINTF(",");
1691         srcoffset = decode_rmXX_address(mod, rl);
1692         srcval = (s32)((s16)fetch_data_word(srcoffset));
1693         DECODE_PRINTF("\n");
1694         TRACE_AND_STEP();
1695         *destreg = srcval;
1696     } else {                     /* register to register */
1697         destreg = DECODE_RM_LONG_REGISTER(rh);
1698         DECODE_PRINTF(",");
1699         srcreg = DECODE_RM_WORD_REGISTER(rl);
1700         DECODE_PRINTF("\n");
1701         TRACE_AND_STEP();
1702         *destreg = (s32)((s16)*srcreg);
1703     }
1704     DECODE_CLEAR_SEGOVR();
1705     END_OF_INSTR();
1706 }
1707 
1708 /***************************************************************************
1709  * Double byte operation code table:
1710  **************************************************************************/
1711 void (*x86emu_optab2[256])(u8) =
1712 {
1713 /*  0x00 */ x86emuOp2_illegal_op,  /* Group F (ring 0 PM)      */
1714 /*  0x01 */ x86emuOp2_opc_01,      /* Group G (ring 0 PM)      */
1715 /*  0x02 */ x86emuOp2_illegal_op,  /* lar (ring 0 PM)          */
1716 /*  0x03 */ x86emuOp2_illegal_op,  /* lsl (ring 0 PM)          */
1717 /*  0x04 */ x86emuOp2_illegal_op,
1718 /*  0x05 */ x86emuOp2_illegal_op,  /* loadall (undocumented)   */
1719 /*  0x06 */ x86emuOp2_illegal_op,  /* clts (ring 0 PM)         */
1720 /*  0x07 */ x86emuOp2_illegal_op,  /* loadall (undocumented)   */
1721 /*  0x08 */ x86emuOp2_invd,        /* invd (ring 0 PM)         */
1722 /*  0x09 */ x86emuOp2_wbinvd,      /* wbinvd (ring 0 PM)       */
1723 /*  0x0a */ x86emuOp2_illegal_op,
1724 /*  0x0b */ x86emuOp2_illegal_op,
1725 /*  0x0c */ x86emuOp2_illegal_op,
1726 /*  0x0d */ x86emuOp2_illegal_op,
1727 /*  0x0e */ x86emuOp2_illegal_op,
1728 /*  0x0f */ x86emuOp2_illegal_op,
1729 
1730 /*  0x10 */ x86emuOp2_illegal_op,
1731 /*  0x11 */ x86emuOp2_illegal_op,
1732 /*  0x12 */ x86emuOp2_illegal_op,
1733 /*  0x13 */ x86emuOp2_illegal_op,
1734 /*  0x14 */ x86emuOp2_illegal_op,
1735 /*  0x15 */ x86emuOp2_illegal_op,
1736 /*  0x16 */ x86emuOp2_illegal_op,
1737 /*  0x17 */ x86emuOp2_illegal_op,
1738 /*  0x18 */ x86emuOp2_illegal_op,
1739 /*  0x19 */ x86emuOp2_illegal_op,
1740 /*  0x1a */ x86emuOp2_illegal_op,
1741 /*  0x1b */ x86emuOp2_illegal_op,
1742 /*  0x1c */ x86emuOp2_illegal_op,
1743 /*  0x1d */ x86emuOp2_illegal_op,
1744 /*  0x1e */ x86emuOp2_illegal_op,
1745 /*  0x1f */ x86emuOp2_illegal_op,
1746 
1747 /*  0x20 */ x86emuOp2_illegal_op,  /* mov reg32,creg (ring 0 PM) */
1748 /*  0x21 */ x86emuOp2_illegal_op,  /* mov reg32,dreg (ring 0 PM) */
1749 /*  0x22 */ x86emuOp2_illegal_op,  /* mov creg,reg32 (ring 0 PM) */
1750 /*  0x23 */ x86emuOp2_illegal_op,  /* mov dreg,reg32 (ring 0 PM) */
1751 /*  0x24 */ x86emuOp2_illegal_op,  /* mov reg32,treg (ring 0 PM) */
1752 /*  0x25 */ x86emuOp2_illegal_op,
1753 /*  0x26 */ x86emuOp2_illegal_op,  /* mov treg,reg32 (ring 0 PM) */
1754 /*  0x27 */ x86emuOp2_illegal_op,
1755 /*  0x28 */ x86emuOp2_illegal_op,
1756 /*  0x29 */ x86emuOp2_illegal_op,
1757 /*  0x2a */ x86emuOp2_illegal_op,
1758 /*  0x2b */ x86emuOp2_illegal_op,
1759 /*  0x2c */ x86emuOp2_illegal_op,
1760 /*  0x2d */ x86emuOp2_illegal_op,
1761 /*  0x2e */ x86emuOp2_illegal_op,
1762 /*  0x2f */ x86emuOp2_illegal_op,
1763 
1764 /*  0x30 */ x86emuOp2_wrmsr,
1765 /*  0x31 */ x86emuOp2_rdtsc,
1766 /*  0x32 */ x86emuOp2_rdmsr,
1767 /*  0x33 */ x86emuOp2_illegal_op,
1768 /*  0x34 */ x86emuOp2_illegal_op,
1769 /*  0x35 */ x86emuOp2_illegal_op,
1770 /*  0x36 */ x86emuOp2_illegal_op,
1771 /*  0x37 */ x86emuOp2_illegal_op,
1772 /*  0x38 */ x86emuOp2_illegal_op,
1773 /*  0x39 */ x86emuOp2_illegal_op,
1774 /*  0x3a */ x86emuOp2_illegal_op,
1775 /*  0x3b */ x86emuOp2_illegal_op,
1776 /*  0x3c */ x86emuOp2_illegal_op,
1777 /*  0x3d */ x86emuOp2_illegal_op,
1778 /*  0x3e */ x86emuOp2_illegal_op,
1779 /*  0x3f */ x86emuOp2_illegal_op,
1780 
1781 /*  0x40 */ x86emuOp2_illegal_op,
1782 /*  0x41 */ x86emuOp2_illegal_op,
1783 /*  0x42 */ x86emuOp2_illegal_op,
1784 /*  0x43 */ x86emuOp2_illegal_op,
1785 /*  0x44 */ x86emuOp2_illegal_op,
1786 /*  0x45 */ x86emuOp2_illegal_op,
1787 /*  0x46 */ x86emuOp2_illegal_op,
1788 /*  0x47 */ x86emuOp2_illegal_op,
1789 /*  0x48 */ x86emuOp2_illegal_op,
1790 /*  0x49 */ x86emuOp2_illegal_op,
1791 /*  0x4a */ x86emuOp2_illegal_op,
1792 /*  0x4b */ x86emuOp2_illegal_op,
1793 /*  0x4c */ x86emuOp2_illegal_op,
1794 /*  0x4d */ x86emuOp2_illegal_op,
1795 /*  0x4e */ x86emuOp2_illegal_op,
1796 /*  0x4f */ x86emuOp2_illegal_op,
1797 
1798 /*  0x50 */ x86emuOp2_illegal_op,
1799 /*  0x51 */ x86emuOp2_illegal_op,
1800 /*  0x52 */ x86emuOp2_illegal_op,
1801 /*  0x53 */ x86emuOp2_illegal_op,
1802 /*  0x54 */ x86emuOp2_illegal_op,
1803 /*  0x55 */ x86emuOp2_illegal_op,
1804 /*  0x56 */ x86emuOp2_illegal_op,
1805 /*  0x57 */ x86emuOp2_illegal_op,
1806 /*  0x58 */ x86emuOp2_illegal_op,
1807 /*  0x59 */ x86emuOp2_illegal_op,
1808 /*  0x5a */ x86emuOp2_illegal_op,
1809 /*  0x5b */ x86emuOp2_illegal_op,
1810 /*  0x5c */ x86emuOp2_illegal_op,
1811 /*  0x5d */ x86emuOp2_illegal_op,
1812 /*  0x5e */ x86emuOp2_illegal_op,
1813 /*  0x5f */ x86emuOp2_illegal_op,
1814 
1815 /*  0x60 */ x86emuOp2_illegal_op,
1816 /*  0x61 */ x86emuOp2_illegal_op,
1817 /*  0x62 */ x86emuOp2_illegal_op,
1818 /*  0x63 */ x86emuOp2_illegal_op,
1819 /*  0x64 */ x86emuOp2_illegal_op,
1820 /*  0x65 */ x86emuOp2_illegal_op,
1821 /*  0x66 */ x86emuOp2_illegal_op,
1822 /*  0x67 */ x86emuOp2_illegal_op,
1823 /*  0x68 */ x86emuOp2_illegal_op,
1824 /*  0x69 */ x86emuOp2_illegal_op,
1825 /*  0x6a */ x86emuOp2_illegal_op,
1826 /*  0x6b */ x86emuOp2_illegal_op,
1827 /*  0x6c */ x86emuOp2_illegal_op,
1828 /*  0x6d */ x86emuOp2_illegal_op,
1829 /*  0x6e */ x86emuOp2_illegal_op,
1830 /*  0x6f */ x86emuOp2_illegal_op,
1831 
1832 /*  0x70 */ x86emuOp2_illegal_op,
1833 /*  0x71 */ x86emuOp2_illegal_op,
1834 /*  0x72 */ x86emuOp2_illegal_op,
1835 /*  0x73 */ x86emuOp2_illegal_op,
1836 /*  0x74 */ x86emuOp2_illegal_op,
1837 /*  0x75 */ x86emuOp2_illegal_op,
1838 /*  0x76 */ x86emuOp2_illegal_op,
1839 /*  0x77 */ x86emuOp2_illegal_op,
1840 /*  0x78 */ x86emuOp2_illegal_op,
1841 /*  0x79 */ x86emuOp2_illegal_op,
1842 /*  0x7a */ x86emuOp2_illegal_op,
1843 /*  0x7b */ x86emuOp2_illegal_op,
1844 /*  0x7c */ x86emuOp2_illegal_op,
1845 /*  0x7d */ x86emuOp2_illegal_op,
1846 /*  0x7e */ x86emuOp2_illegal_op,
1847 /*  0x7f */ x86emuOp2_illegal_op,
1848 
1849 /*  0x80 */ x86emuOp2_long_jump,
1850 /*  0x81 */ x86emuOp2_long_jump,
1851 /*  0x82 */ x86emuOp2_long_jump,
1852 /*  0x83 */ x86emuOp2_long_jump,
1853 /*  0x84 */ x86emuOp2_long_jump,
1854 /*  0x85 */ x86emuOp2_long_jump,
1855 /*  0x86 */ x86emuOp2_long_jump,
1856 /*  0x87 */ x86emuOp2_long_jump,
1857 /*  0x88 */ x86emuOp2_long_jump,
1858 /*  0x89 */ x86emuOp2_long_jump,
1859 /*  0x8a */ x86emuOp2_long_jump,
1860 /*  0x8b */ x86emuOp2_long_jump,
1861 /*  0x8c */ x86emuOp2_long_jump,
1862 /*  0x8d */ x86emuOp2_long_jump,
1863 /*  0x8e */ x86emuOp2_long_jump,
1864 /*  0x8f */ x86emuOp2_long_jump,
1865 
1866 /*  0x90 */ x86emuOp2_set_byte,
1867 /*  0x91 */ x86emuOp2_set_byte,
1868 /*  0x92 */ x86emuOp2_set_byte,
1869 /*  0x93 */ x86emuOp2_set_byte,
1870 /*  0x94 */ x86emuOp2_set_byte,
1871 /*  0x95 */ x86emuOp2_set_byte,
1872 /*  0x96 */ x86emuOp2_set_byte,
1873 /*  0x97 */ x86emuOp2_set_byte,
1874 /*  0x98 */ x86emuOp2_set_byte,
1875 /*  0x99 */ x86emuOp2_set_byte,
1876 /*  0x9a */ x86emuOp2_set_byte,
1877 /*  0x9b */ x86emuOp2_set_byte,
1878 /*  0x9c */ x86emuOp2_set_byte,
1879 /*  0x9d */ x86emuOp2_set_byte,
1880 /*  0x9e */ x86emuOp2_set_byte,
1881 /*  0x9f */ x86emuOp2_set_byte,
1882 
1883 /*  0xa0 */ x86emuOp2_push_FS,
1884 /*  0xa1 */ x86emuOp2_pop_FS,
1885 /*  0xa2 */ x86emuOp2_cpuid,
1886 /*  0xa3 */ x86emuOp2_bt_R,
1887 /*  0xa4 */ x86emuOp2_shld_IMM,
1888 /*  0xa5 */ x86emuOp2_shld_CL,
1889 /*  0xa6 */ x86emuOp2_illegal_op,
1890 /*  0xa7 */ x86emuOp2_illegal_op,
1891 /*  0xa8 */ x86emuOp2_push_GS,
1892 /*  0xa9 */ x86emuOp2_pop_GS,
1893 /*  0xaa */ x86emuOp2_illegal_op,
1894 /*  0xab */ x86emuOp2_bts_R,
1895 /*  0xac */ x86emuOp2_shrd_IMM,
1896 /*  0xad */ x86emuOp2_shrd_CL,
1897 /*  0xae */ x86emuOp2_illegal_op,
1898 /*  0xaf */ x86emuOp2_imul_R_RM,
1899 
1900 /*  0xb0 */ x86emuOp2_illegal_op,  /* TODO: cmpxchg */
1901 /*  0xb1 */ x86emuOp2_illegal_op,  /* TODO: cmpxchg */
1902 /*  0xb2 */ x86emuOp2_lss_R_IMM,
1903 /*  0xb3 */ x86emuOp2_btr_R,
1904 /*  0xb4 */ x86emuOp2_lfs_R_IMM,
1905 /*  0xb5 */ x86emuOp2_lgs_R_IMM,
1906 /*  0xb6 */ x86emuOp2_movzx_byte_R_RM,
1907 /*  0xb7 */ x86emuOp2_movzx_word_R_RM,
1908 /*  0xb8 */ x86emuOp2_illegal_op,
1909 /*  0xb9 */ x86emuOp2_illegal_op,
1910 /*  0xba */ x86emuOp2_btX_I,
1911 /*  0xbb */ x86emuOp2_btc_R,
1912 /*  0xbc */ x86emuOp2_bsf,
1913 /*  0xbd */ x86emuOp2_bsr,
1914 /*  0xbe */ x86emuOp2_movsx_byte_R_RM,
1915 /*  0xbf */ x86emuOp2_movsx_word_R_RM,
1916 
1917 /*  0xc0 */ x86emuOp2_illegal_op,  /* TODO: xadd */
1918 /*  0xc1 */ x86emuOp2_illegal_op,  /* TODO: xadd */
1919 /*  0xc2 */ x86emuOp2_illegal_op,
1920 /*  0xc3 */ x86emuOp2_illegal_op,
1921 /*  0xc4 */ x86emuOp2_illegal_op,
1922 /*  0xc5 */ x86emuOp2_illegal_op,
1923 /*  0xc6 */ x86emuOp2_illegal_op,
1924 /*  0xc7 */ x86emuOp2_illegal_op,
1925 /*  0xc8 */ x86emuOp2_bswap,
1926 /*  0xc9 */ x86emuOp2_bswap,
1927 /*  0xca */ x86emuOp2_bswap,
1928 /*  0xcb */ x86emuOp2_bswap,
1929 /*  0xcc */ x86emuOp2_bswap,
1930 /*  0xcd */ x86emuOp2_bswap,
1931 /*  0xce */ x86emuOp2_bswap,
1932 /*  0xcf */ x86emuOp2_bswap,
1933 
1934 /*  0xd0 */ x86emuOp2_illegal_op,
1935 /*  0xd1 */ x86emuOp2_illegal_op,
1936 /*  0xd2 */ x86emuOp2_illegal_op,
1937 /*  0xd3 */ x86emuOp2_illegal_op,
1938 /*  0xd4 */ x86emuOp2_illegal_op,
1939 /*  0xd5 */ x86emuOp2_illegal_op,
1940 /*  0xd6 */ x86emuOp2_illegal_op,
1941 /*  0xd7 */ x86emuOp2_illegal_op,
1942 /*  0xd8 */ x86emuOp2_illegal_op,
1943 /*  0xd9 */ x86emuOp2_illegal_op,
1944 /*  0xda */ x86emuOp2_illegal_op,
1945 /*  0xdb */ x86emuOp2_illegal_op,
1946 /*  0xdc */ x86emuOp2_illegal_op,
1947 /*  0xdd */ x86emuOp2_illegal_op,
1948 /*  0xde */ x86emuOp2_illegal_op,
1949 /*  0xdf */ x86emuOp2_illegal_op,
1950 
1951 /*  0xe0 */ x86emuOp2_illegal_op,
1952 /*  0xe1 */ x86emuOp2_illegal_op,
1953 /*  0xe2 */ x86emuOp2_illegal_op,
1954 /*  0xe3 */ x86emuOp2_illegal_op,
1955 /*  0xe4 */ x86emuOp2_illegal_op,
1956 /*  0xe5 */ x86emuOp2_illegal_op,
1957 /*  0xe6 */ x86emuOp2_illegal_op,
1958 /*  0xe7 */ x86emuOp2_illegal_op,
1959 /*  0xe8 */ x86emuOp2_illegal_op,
1960 /*  0xe9 */ x86emuOp2_illegal_op,
1961 /*  0xea */ x86emuOp2_illegal_op,
1962 /*  0xeb */ x86emuOp2_illegal_op,
1963 /*  0xec */ x86emuOp2_illegal_op,
1964 /*  0xed */ x86emuOp2_illegal_op,
1965 /*  0xee */ x86emuOp2_illegal_op,
1966 /*  0xef */ x86emuOp2_illegal_op,
1967 
1968 /*  0xf0 */ x86emuOp2_illegal_op,
1969 /*  0xf1 */ x86emuOp2_illegal_op,
1970 /*  0xf2 */ x86emuOp2_illegal_op,
1971 /*  0xf3 */ x86emuOp2_illegal_op,
1972 /*  0xf4 */ x86emuOp2_illegal_op,
1973 /*  0xf5 */ x86emuOp2_illegal_op,
1974 /*  0xf6 */ x86emuOp2_illegal_op,
1975 /*  0xf7 */ x86emuOp2_illegal_op,
1976 /*  0xf8 */ x86emuOp2_illegal_op,
1977 /*  0xf9 */ x86emuOp2_illegal_op,
1978 /*  0xfa */ x86emuOp2_illegal_op,
1979 /*  0xfb */ x86emuOp2_illegal_op,
1980 /*  0xfc */ x86emuOp2_illegal_op,
1981 /*  0xfd */ x86emuOp2_illegal_op,
1982 /*  0xfe */ x86emuOp2_illegal_op,
1983 /*  0xff */ x86emuOp2_illegal_op,
1984 };
1985