]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/bios_emulator/x86emu/ops.c
Merge with /home/wd/git/u-boot/work
[karo-tx-uboot.git] / drivers / bios_emulator / x86emu / ops.c
1 /****************************************************************************
2 *                       Realmode X86 Emulator Library
3 *
4 *  Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
5 *  Jason Jin <Jason.jin@freescale.com>
6 *
7 *               Copyright (C) 1991-2004 SciTech Software, Inc.
8 *                                    Copyright (C) David Mosberger-Tang
9 *                                          Copyright (C) 1999 Egbert Eich
10 *
11 *  ========================================================================
12 *
13 *  Permission to use, copy, modify, distribute, and sell this software and
14 *  its documentation for any purpose is hereby granted without fee,
15 *  provided that the above copyright notice appear in all copies and that
16 *  both that copyright notice and this permission notice appear in
17 *  supporting documentation, and that the name of the authors not be used
18 *  in advertising or publicity pertaining to distribution of the software
19 *  without specific, written prior permission.  The authors makes no
20 *  representations about the suitability of this software for any purpose.
21 *  It is provided "as is" without express or implied warranty.
22 *
23 *  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
24 *  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
25 *  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
26 *  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
27 *  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
28 *  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
29 *  PERFORMANCE OF THIS SOFTWARE.
30 *
31 *  ========================================================================
32 *
33 * Language:             ANSI C
34 * Environment:  Any
35 * Developer:    Kendall Bennett
36 *
37 * Description:  This file includes subroutines to implement the decoding
38 *               and emulation of all the x86 processor instructions.
39 *
40 * There are approximately 250 subroutines in here, which correspond
41 * to the 256 byte-"opcodes" found on the 8086.  The table which
42 * dispatches this is found in the files optab.[ch].
43 *
44 * Each opcode proc has a comment preceeding it which gives it's table
45 * address.  Several opcodes are missing (undefined) in the table.
46 *
47 * Each proc includes information for decoding (DECODE_PRINTF and
48 * DECODE_PRINTF2), debugging (TRACE_REGS, SINGLE_STEP), and misc
49 * functions (START_OF_INSTR, END_OF_INSTR).
50 *
51 * Many of the procedures are *VERY* similar in coding.  This has
52 * allowed for a very large amount of code to be generated in a fairly
53 * short amount of time (i.e. cut, paste, and modify).  The result is
54 * that much of the code below could have been folded into subroutines
55 * for a large reduction in size of this file.  The downside would be
56 * that there would be a penalty in execution speed.  The file could
57 * also have been *MUCH* larger by inlining certain functions which
58 * were called.  This could have resulted even faster execution.  The
59 * prime directive I used to decide whether to inline the code or to
60 * modularize it, was basically: 1) no unnecessary subroutine calls,
61 * 2) no routines more than about 200 lines in size, and 3) modularize
62 * any code that I might not get right the first time.  The fetch_*
63 * subroutines fall into the latter category.  The The decode_* fall
64 * into the second category.  The coding of the "switch(mod){ .... }"
65 * in many of the subroutines below falls into the first category.
66 * Especially, the coding of {add,and,or,sub,...}_{byte,word}
67 * subroutines are an especially glaring case of the third guideline.
68 * Since so much of the code is cloned from other modules (compare
69 * opcode #00 to opcode #01), making the basic operations subroutine
70 * calls is especially important; otherwise mistakes in coding an
71 * "add" would represent a nightmare in maintenance.
72 *
73 * Jason ported this file to u-boot. place all the function pointer in
74 * the got2 sector. Removed some opcode.
75 *
76 ****************************************************************************/
77
78 #include "x86emu/x86emui.h"
79
80 #if defined(CONFIG_BIOSEMU)
81
82 /*----------------------------- Implementation ----------------------------*/
83
84 /* constant arrays to do several instructions in just one function */
85
86 #ifdef DEBUG
87 static char *x86emu_GenOpName[8] = {
88     "ADD", "OR", "ADC", "SBB", "AND", "SUB", "XOR", "CMP"};
89 #endif
90
91 /* used by several opcodes  */
92 static u8 (*genop_byte_operation[])(u8 d, u8 s) __attribute__ ((section(".got2"))) =
93 {
94     add_byte,           /* 00 */
95     or_byte,            /* 01 */
96     adc_byte,           /* 02 */
97     sbb_byte,           /* 03 */
98     and_byte,           /* 04 */
99     sub_byte,           /* 05 */
100     xor_byte,           /* 06 */
101     cmp_byte,           /* 07 */
102 };
103
104 static u16 (*genop_word_operation[])(u16 d, u16 s) __attribute__ ((section(".got2"))) =
105 {
106     add_word,           /*00 */
107     or_word,            /*01 */
108     adc_word,           /*02 */
109     sbb_word,           /*03 */
110     and_word,           /*04 */
111     sub_word,           /*05 */
112     xor_word,           /*06 */
113     cmp_word,           /*07 */
114 };
115
116 static u32 (*genop_long_operation[])(u32 d, u32 s) __attribute__ ((section(".got2"))) =
117 {
118     add_long,           /*00 */
119     or_long,            /*01 */
120     adc_long,           /*02 */
121     sbb_long,           /*03 */
122     and_long,           /*04 */
123     sub_long,           /*05 */
124     xor_long,           /*06 */
125     cmp_long,           /*07 */
126 };
127
128 /* used by opcodes 80, c0, d0, and d2. */
129 static u8(*opcD0_byte_operation[])(u8 d, u8 s) __attribute__ ((section(".got2"))) =
130 {
131     rol_byte,
132     ror_byte,
133     rcl_byte,
134     rcr_byte,
135     shl_byte,
136     shr_byte,
137     shl_byte,           /* sal_byte === shl_byte  by definition */
138     sar_byte,
139 };
140
141 /* used by opcodes c1, d1, and d3. */
142 static u16(*opcD1_word_operation[])(u16 s, u8 d) __attribute__ ((section(".got2"))) =
143 {
144     rol_word,
145     ror_word,
146     rcl_word,
147     rcr_word,
148     shl_word,
149     shr_word,
150     shl_word,           /* sal_byte === shl_byte  by definition */
151     sar_word,
152 };
153
154 /* used by opcodes c1, d1, and d3. */
155 static u32 (*opcD1_long_operation[])(u32 s, u8 d) __attribute__ ((section(".got2"))) =
156 {
157     rol_long,
158     ror_long,
159     rcl_long,
160     rcr_long,
161     shl_long,
162     shr_long,
163     shl_long,           /* sal_byte === shl_byte  by definition */
164     sar_long,
165 };
166
167 #ifdef DEBUG
168
169 static char *opF6_names[8] =
170   { "TEST\t", "", "NOT\t", "NEG\t", "MUL\t", "IMUL\t", "DIV\t", "IDIV\t" };
171
172 #endif
173
174 /****************************************************************************
175 PARAMETERS:
176 op1 - Instruction op code
177
178 REMARKS:
179 Handles illegal opcodes.
180 ****************************************************************************/
181 void x86emuOp_illegal_op(
182     u8 op1)
183 {
184     START_OF_INSTR();
185     if (M.x86.R_SP != 0) {
186         DECODE_PRINTF("ILLEGAL X86 OPCODE\n");
187         TRACE_REGS();
188         DB( printk("%04x:%04x: %02X ILLEGAL X86 OPCODE!\n",
189             M.x86.R_CS, M.x86.R_IP-1,op1));
190         HALT_SYS();
191         }
192     else {
193         /* If we get here, it means the stack pointer is back to zero
194          * so we are just returning from an emulator service call
195          * so therte is no need to display an error message. We trap
196          * the emulator with an 0xF1 opcode to finish the service
197          * call.
198          */
199         X86EMU_halt_sys();
200         }
201     END_OF_INSTR();
202 }
203
204 /****************************************************************************
205 REMARKS:
206 Handles opcodes 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38
207 ****************************************************************************/
208 void x86emuOp_genop_byte_RM_R(u8 op1)
209 {
210     int mod, rl, rh;
211     uint destoffset;
212     u8 *destreg, *srcreg;
213     u8 destval;
214
215     op1 = (op1 >> 3) & 0x7;
216
217     START_OF_INSTR();
218     DECODE_PRINTF(x86emu_GenOpName[op1]);
219     DECODE_PRINTF("\t");
220     FETCH_DECODE_MODRM(mod, rh, rl);
221     if(mod<3)
222         { destoffset = decode_rmXX_address(mod,rl);
223         DECODE_PRINTF(",");
224         destval = fetch_data_byte(destoffset);
225         srcreg = DECODE_RM_BYTE_REGISTER(rh);
226         DECODE_PRINTF("\n");
227         TRACE_AND_STEP();
228         destval = genop_byte_operation[op1](destval, *srcreg);
229         store_data_byte(destoffset, destval);
230         }
231     else
232         {                       /* register to register */
233         destreg = DECODE_RM_BYTE_REGISTER(rl);
234         DECODE_PRINTF(",");
235         srcreg = DECODE_RM_BYTE_REGISTER(rh);
236         DECODE_PRINTF("\n");
237         TRACE_AND_STEP();
238         *destreg = genop_byte_operation[op1](*destreg, *srcreg);
239         }
240     DECODE_CLEAR_SEGOVR();
241     END_OF_INSTR();
242 }
243
244 /****************************************************************************
245 REMARKS:
246 Handles opcodes 0x01, 0x09, 0x11, 0x19, 0x21, 0x29, 0x31, 0x39
247 ****************************************************************************/
248 void x86emuOp_genop_word_RM_R(u8 op1)
249 {
250     int mod, rl, rh;
251     uint destoffset;
252
253     op1 = (op1 >> 3) & 0x7;
254
255     START_OF_INSTR();
256     DECODE_PRINTF(x86emu_GenOpName[op1]);
257     DECODE_PRINTF("\t");
258     FETCH_DECODE_MODRM(mod, rh, rl);
259
260     if(mod<3) {
261         destoffset = decode_rmXX_address(mod,rl);
262         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
263             u32 destval;
264             u32 *srcreg;
265
266             DECODE_PRINTF(",");
267             destval = fetch_data_long(destoffset);
268             srcreg = DECODE_RM_LONG_REGISTER(rh);
269             DECODE_PRINTF("\n");
270             TRACE_AND_STEP();
271             destval = genop_long_operation[op1](destval, *srcreg);
272             store_data_long(destoffset, destval);
273         } else {
274             u16 destval;
275             u16 *srcreg;
276
277             DECODE_PRINTF(",");
278             destval = fetch_data_word(destoffset);
279             srcreg = DECODE_RM_WORD_REGISTER(rh);
280             DECODE_PRINTF("\n");
281             TRACE_AND_STEP();
282             destval = genop_word_operation[op1](destval, *srcreg);
283             store_data_word(destoffset, destval);
284         }
285     } else {                    /* register to register */
286         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
287             u32 *destreg,*srcreg;
288
289             destreg = DECODE_RM_LONG_REGISTER(rl);
290             DECODE_PRINTF(",");
291             srcreg = DECODE_RM_LONG_REGISTER(rh);
292             DECODE_PRINTF("\n");
293             TRACE_AND_STEP();
294             *destreg = genop_long_operation[op1](*destreg, *srcreg);
295         } else {
296             u16 *destreg,*srcreg;
297
298             destreg = DECODE_RM_WORD_REGISTER(rl);
299             DECODE_PRINTF(",");
300             srcreg = DECODE_RM_WORD_REGISTER(rh);
301             DECODE_PRINTF("\n");
302             TRACE_AND_STEP();
303             *destreg = genop_word_operation[op1](*destreg, *srcreg);
304         }
305     }
306     DECODE_CLEAR_SEGOVR();
307     END_OF_INSTR();
308 }
309
310 /****************************************************************************
311 REMARKS:
312 Handles opcodes 0x02, 0x0a, 0x12, 0x1a, 0x22, 0x2a, 0x32, 0x3a
313 ****************************************************************************/
314 void x86emuOp_genop_byte_R_RM(u8 op1)
315 {
316     int mod, rl, rh;
317     u8 *destreg, *srcreg;
318     uint srcoffset;
319     u8 srcval;
320
321     op1 = (op1 >> 3) & 0x7;
322
323     START_OF_INSTR();
324     DECODE_PRINTF(x86emu_GenOpName[op1]);
325     DECODE_PRINTF("\t");
326     FETCH_DECODE_MODRM(mod, rh, rl);
327     if (mod < 3) {
328         destreg = DECODE_RM_BYTE_REGISTER(rh);
329         DECODE_PRINTF(",");
330         srcoffset = decode_rmXX_address(mod,rl);
331         srcval = fetch_data_byte(srcoffset);
332     } else {     /* register to register */
333         destreg = DECODE_RM_BYTE_REGISTER(rh);
334         DECODE_PRINTF(",");
335         srcreg = DECODE_RM_BYTE_REGISTER(rl);
336         srcval = *srcreg;
337     }
338     DECODE_PRINTF("\n");
339     TRACE_AND_STEP();
340     *destreg = genop_byte_operation[op1](*destreg, srcval);
341
342     DECODE_CLEAR_SEGOVR();
343     END_OF_INSTR();
344 }
345
346 /****************************************************************************
347 REMARKS:
348 Handles opcodes 0x03, 0x0b, 0x13, 0x1b, 0x23, 0x2b, 0x33, 0x3b
349 ****************************************************************************/
350 void x86emuOp_genop_word_R_RM(u8 op1)
351 {
352     int mod, rl, rh;
353     uint srcoffset;
354     u32 *destreg32, srcval;
355     u16 *destreg;
356
357     op1 = (op1 >> 3) & 0x7;
358
359     START_OF_INSTR();
360     DECODE_PRINTF(x86emu_GenOpName[op1]);
361     DECODE_PRINTF("\t");
362     FETCH_DECODE_MODRM(mod, rh, rl);
363     if (mod < 3) {
364         srcoffset = decode_rmXX_address(mod,rl);
365         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
366             destreg32 = DECODE_RM_LONG_REGISTER(rh);
367             DECODE_PRINTF(",");
368             srcval = fetch_data_long(srcoffset);
369             DECODE_PRINTF("\n");
370             TRACE_AND_STEP();
371             *destreg32 = genop_long_operation[op1](*destreg32, srcval);
372         } else {
373             destreg = DECODE_RM_WORD_REGISTER(rh);
374             DECODE_PRINTF(",");
375             srcval = fetch_data_word(srcoffset);
376             DECODE_PRINTF("\n");
377             TRACE_AND_STEP();
378             *destreg = genop_word_operation[op1](*destreg, srcval);
379         }
380     } else {                     /* register to register */
381         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
382             u32 *srcreg;
383             destreg32 = DECODE_RM_LONG_REGISTER(rh);
384             DECODE_PRINTF(",");
385             srcreg = DECODE_RM_LONG_REGISTER(rl);
386             DECODE_PRINTF("\n");
387             TRACE_AND_STEP();
388             *destreg32 = genop_long_operation[op1](*destreg32, *srcreg);
389         } else {
390             u16 *srcreg;
391             destreg = DECODE_RM_WORD_REGISTER(rh);
392             DECODE_PRINTF(",");
393             srcreg = DECODE_RM_WORD_REGISTER(rl);
394             DECODE_PRINTF("\n");
395             TRACE_AND_STEP();
396             *destreg = genop_word_operation[op1](*destreg, *srcreg);
397         }
398     }
399     DECODE_CLEAR_SEGOVR();
400     END_OF_INSTR();
401 }
402
403 /****************************************************************************
404 REMARKS:
405 Handles opcodes 0x04, 0x0c, 0x14, 0x1c, 0x24, 0x2c, 0x34, 0x3c
406 ****************************************************************************/
407 void x86emuOp_genop_byte_AL_IMM(u8 op1)
408 {
409     u8 srcval;
410
411     op1 = (op1 >> 3) & 0x7;
412
413     START_OF_INSTR();
414     DECODE_PRINTF(x86emu_GenOpName[op1]);
415     DECODE_PRINTF("\tAL,");
416     srcval = fetch_byte_imm();
417     DECODE_PRINTF2("%x\n", srcval);
418     TRACE_AND_STEP();
419     M.x86.R_AL = genop_byte_operation[op1](M.x86.R_AL, srcval);
420     DECODE_CLEAR_SEGOVR();
421     END_OF_INSTR();
422 }
423
424 /****************************************************************************
425 REMARKS:
426 Handles opcodes 0x05, 0x0d, 0x15, 0x1d, 0x25, 0x2d, 0x35, 0x3d
427 ****************************************************************************/
428 void x86emuOp_genop_word_AX_IMM(u8 op1)
429 {
430     u32 srcval;
431
432     op1 = (op1 >> 3) & 0x7;
433
434     START_OF_INSTR();
435     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
436         DECODE_PRINTF(x86emu_GenOpName[op1]);
437         DECODE_PRINTF("\tEAX,");
438         srcval = fetch_long_imm();
439     } else {
440         DECODE_PRINTF(x86emu_GenOpName[op1]);
441         DECODE_PRINTF("\tAX,");
442         srcval = fetch_word_imm();
443     }
444     DECODE_PRINTF2("%x\n", srcval);
445     TRACE_AND_STEP();
446     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
447         M.x86.R_EAX = genop_long_operation[op1](M.x86.R_EAX, srcval);
448     } else {
449         M.x86.R_AX = genop_word_operation[op1](M.x86.R_AX, (u16)srcval);
450     }
451     DECODE_CLEAR_SEGOVR();
452     END_OF_INSTR();
453 }
454
455 /****************************************************************************
456 REMARKS:
457 Handles opcode 0x06
458 ****************************************************************************/
459 void x86emuOp_push_ES(u8 X86EMU_UNUSED(op1))
460 {
461     START_OF_INSTR();
462     DECODE_PRINTF("PUSH\tES\n");
463     TRACE_AND_STEP();
464     push_word(M.x86.R_ES);
465     DECODE_CLEAR_SEGOVR();
466     END_OF_INSTR();
467 }
468
469 /****************************************************************************
470 REMARKS:
471 Handles opcode 0x07
472 ****************************************************************************/
473 void x86emuOp_pop_ES(u8 X86EMU_UNUSED(op1))
474 {
475     START_OF_INSTR();
476     DECODE_PRINTF("POP\tES\n");
477     TRACE_AND_STEP();
478     M.x86.R_ES = pop_word();
479     DECODE_CLEAR_SEGOVR();
480     END_OF_INSTR();
481 }
482
483 /****************************************************************************
484 REMARKS:
485 Handles opcode 0x0e
486 ****************************************************************************/
487 void x86emuOp_push_CS(u8 X86EMU_UNUSED(op1))
488 {
489     START_OF_INSTR();
490     DECODE_PRINTF("PUSH\tCS\n");
491     TRACE_AND_STEP();
492     push_word(M.x86.R_CS);
493     DECODE_CLEAR_SEGOVR();
494     END_OF_INSTR();
495 }
496
497 /****************************************************************************
498 REMARKS:
499 Handles opcode 0x0f. Escape for two-byte opcode (286 or better)
500 ****************************************************************************/
501 void x86emuOp_two_byte(u8 X86EMU_UNUSED(op1))
502 {
503     u8 op2 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
504     INC_DECODED_INST_LEN(1);
505     (*x86emu_optab2[op2])(op2);
506 }
507
508 /****************************************************************************
509 REMARKS:
510 Handles opcode 0x16
511 ****************************************************************************/
512 void x86emuOp_push_SS(u8 X86EMU_UNUSED(op1))
513 {
514     START_OF_INSTR();
515     DECODE_PRINTF("PUSH\tSS\n");
516     TRACE_AND_STEP();
517     push_word(M.x86.R_SS);
518     DECODE_CLEAR_SEGOVR();
519     END_OF_INSTR();
520 }
521
522 /****************************************************************************
523 REMARKS:
524 Handles opcode 0x17
525 ****************************************************************************/
526 void x86emuOp_pop_SS(u8 X86EMU_UNUSED(op1))
527 {
528     START_OF_INSTR();
529     DECODE_PRINTF("POP\tSS\n");
530     TRACE_AND_STEP();
531     M.x86.R_SS = pop_word();
532     DECODE_CLEAR_SEGOVR();
533     END_OF_INSTR();
534 }
535
536 /****************************************************************************
537 REMARKS:
538 Handles opcode 0x1e
539 ****************************************************************************/
540 void x86emuOp_push_DS(u8 X86EMU_UNUSED(op1))
541 {
542     START_OF_INSTR();
543     DECODE_PRINTF("PUSH\tDS\n");
544     TRACE_AND_STEP();
545     push_word(M.x86.R_DS);
546     DECODE_CLEAR_SEGOVR();
547     END_OF_INSTR();
548 }
549
550 /****************************************************************************
551 REMARKS:
552 Handles opcode 0x1f
553 ****************************************************************************/
554 void x86emuOp_pop_DS(u8 X86EMU_UNUSED(op1))
555 {
556     START_OF_INSTR();
557     DECODE_PRINTF("POP\tDS\n");
558     TRACE_AND_STEP();
559     M.x86.R_DS = pop_word();
560     DECODE_CLEAR_SEGOVR();
561     END_OF_INSTR();
562 }
563
564 /****************************************************************************
565 REMARKS:
566 Handles opcode 0x26
567 ****************************************************************************/
568 void x86emuOp_segovr_ES(u8 X86EMU_UNUSED(op1))
569 {
570     START_OF_INSTR();
571     DECODE_PRINTF("ES:\n");
572     TRACE_AND_STEP();
573     M.x86.mode |= SYSMODE_SEGOVR_ES;
574     /*
575      * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
576      * opcode subroutines we do not want to do this.
577      */
578     END_OF_INSTR();
579 }
580
581 /****************************************************************************
582 REMARKS:
583 Handles opcode 0x27
584 ****************************************************************************/
585 void x86emuOp_daa(u8 X86EMU_UNUSED(op1))
586 {
587     START_OF_INSTR();
588     DECODE_PRINTF("DAA\n");
589     TRACE_AND_STEP();
590     M.x86.R_AL = daa_byte(M.x86.R_AL);
591     DECODE_CLEAR_SEGOVR();
592     END_OF_INSTR();
593 }
594
595 /****************************************************************************
596 REMARKS:
597 Handles opcode 0x2e
598 ****************************************************************************/
599 void x86emuOp_segovr_CS(u8 X86EMU_UNUSED(op1))
600 {
601     START_OF_INSTR();
602     DECODE_PRINTF("CS:\n");
603     TRACE_AND_STEP();
604     M.x86.mode |= SYSMODE_SEGOVR_CS;
605     /* note no DECODE_CLEAR_SEGOVR here. */
606     END_OF_INSTR();
607 }
608
609 /****************************************************************************
610 REMARKS:
611 Handles opcode 0x2f
612 ****************************************************************************/
613 void x86emuOp_das(u8 X86EMU_UNUSED(op1))
614 {
615     START_OF_INSTR();
616     DECODE_PRINTF("DAS\n");
617     TRACE_AND_STEP();
618     M.x86.R_AL = das_byte(M.x86.R_AL);
619     DECODE_CLEAR_SEGOVR();
620     END_OF_INSTR();
621 }
622
623 /****************************************************************************
624 REMARKS:
625 Handles opcode 0x36
626 ****************************************************************************/
627 void x86emuOp_segovr_SS(u8 X86EMU_UNUSED(op1))
628 {
629     START_OF_INSTR();
630     DECODE_PRINTF("SS:\n");
631     TRACE_AND_STEP();
632     M.x86.mode |= SYSMODE_SEGOVR_SS;
633     /* no DECODE_CLEAR_SEGOVR ! */
634     END_OF_INSTR();
635 }
636
637 /****************************************************************************
638 REMARKS:
639 Handles opcode 0x37
640 ****************************************************************************/
641 void x86emuOp_aaa(u8 X86EMU_UNUSED(op1))
642 {
643     START_OF_INSTR();
644     DECODE_PRINTF("AAA\n");
645     TRACE_AND_STEP();
646     M.x86.R_AX = aaa_word(M.x86.R_AX);
647     DECODE_CLEAR_SEGOVR();
648     END_OF_INSTR();
649 }
650
651 /****************************************************************************
652 REMARKS:
653 Handles opcode 0x3e
654 ****************************************************************************/
655 void x86emuOp_segovr_DS(u8 X86EMU_UNUSED(op1))
656 {
657     START_OF_INSTR();
658     DECODE_PRINTF("DS:\n");
659     TRACE_AND_STEP();
660     M.x86.mode |= SYSMODE_SEGOVR_DS;
661     /* NO DECODE_CLEAR_SEGOVR! */
662     END_OF_INSTR();
663 }
664
665 /****************************************************************************
666 REMARKS:
667 Handles opcode 0x3f
668 ****************************************************************************/
669 void x86emuOp_aas(u8 X86EMU_UNUSED(op1))
670 {
671     START_OF_INSTR();
672     DECODE_PRINTF("AAS\n");
673     TRACE_AND_STEP();
674     M.x86.R_AX = aas_word(M.x86.R_AX);
675     DECODE_CLEAR_SEGOVR();
676     END_OF_INSTR();
677 }
678
679 /****************************************************************************
680 REMARKS:
681 Handles opcode 0x40 - 0x47
682 ****************************************************************************/
683 void x86emuOp_inc_register(u8 op1)
684 {
685     START_OF_INSTR();
686     op1 &= 0x7;
687     DECODE_PRINTF("INC\t");
688     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
689         u32 *reg;
690         reg = DECODE_RM_LONG_REGISTER(op1);
691         DECODE_PRINTF("\n");
692         TRACE_AND_STEP();
693         *reg = inc_long(*reg);
694     } else {
695         u16 *reg;
696         reg = DECODE_RM_WORD_REGISTER(op1);
697         DECODE_PRINTF("\n");
698         TRACE_AND_STEP();
699         *reg = inc_word(*reg);
700     }
701     DECODE_CLEAR_SEGOVR();
702     END_OF_INSTR();
703 }
704
705 /****************************************************************************
706 REMARKS:
707 Handles opcode 0x48 - 0x4F
708 ****************************************************************************/
709 void x86emuOp_dec_register(u8 op1)
710 {
711     START_OF_INSTR();
712     op1 &= 0x7;
713     DECODE_PRINTF("DEC\t");
714     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
715         u32 *reg;
716         reg = DECODE_RM_LONG_REGISTER(op1);
717         DECODE_PRINTF("\n");
718         TRACE_AND_STEP();
719         *reg = dec_long(*reg);
720     } else {
721         u16 *reg;
722         reg = DECODE_RM_WORD_REGISTER(op1);
723         DECODE_PRINTF("\n");
724         TRACE_AND_STEP();
725         *reg = dec_word(*reg);
726     }
727     DECODE_CLEAR_SEGOVR();
728     END_OF_INSTR();
729 }
730
731 /****************************************************************************
732 REMARKS:
733 Handles opcode 0x50 - 0x57
734 ****************************************************************************/
735 void x86emuOp_push_register(u8 op1)
736 {
737     START_OF_INSTR();
738     op1 &= 0x7;
739     DECODE_PRINTF("PUSH\t");
740     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
741         u32 *reg;
742         reg = DECODE_RM_LONG_REGISTER(op1);
743         DECODE_PRINTF("\n");
744         TRACE_AND_STEP();
745         push_long(*reg);
746     } else {
747         u16 *reg;
748         reg = DECODE_RM_WORD_REGISTER(op1);
749         DECODE_PRINTF("\n");
750         TRACE_AND_STEP();
751         push_word(*reg);
752     }
753     DECODE_CLEAR_SEGOVR();
754     END_OF_INSTR();
755 }
756
757 /****************************************************************************
758 REMARKS:
759 Handles opcode 0x58 - 0x5F
760 ****************************************************************************/
761 void x86emuOp_pop_register(u8 op1)
762 {
763     START_OF_INSTR();
764     op1 &= 0x7;
765     DECODE_PRINTF("POP\t");
766     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
767         u32 *reg;
768         reg = DECODE_RM_LONG_REGISTER(op1);
769         DECODE_PRINTF("\n");
770         TRACE_AND_STEP();
771         *reg = pop_long();
772     } else {
773         u16 *reg;
774         reg = DECODE_RM_WORD_REGISTER(op1);
775         DECODE_PRINTF("\n");
776         TRACE_AND_STEP();
777         *reg = pop_word();
778     }
779     DECODE_CLEAR_SEGOVR();
780     END_OF_INSTR();
781 }
782
783 /****************************************************************************
784 REMARKS:
785 Handles opcode 0x60
786 ****************************************************************************/
787 void x86emuOp_push_all(u8 X86EMU_UNUSED(op1))
788 {
789     START_OF_INSTR();
790     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
791         DECODE_PRINTF("PUSHAD\n");
792     } else {
793         DECODE_PRINTF("PUSHA\n");
794     }
795     TRACE_AND_STEP();
796     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
797         u32 old_sp = M.x86.R_ESP;
798
799         push_long(M.x86.R_EAX);
800         push_long(M.x86.R_ECX);
801         push_long(M.x86.R_EDX);
802         push_long(M.x86.R_EBX);
803         push_long(old_sp);
804         push_long(M.x86.R_EBP);
805         push_long(M.x86.R_ESI);
806         push_long(M.x86.R_EDI);
807     } else {
808         u16 old_sp = M.x86.R_SP;
809
810         push_word(M.x86.R_AX);
811         push_word(M.x86.R_CX);
812         push_word(M.x86.R_DX);
813         push_word(M.x86.R_BX);
814         push_word(old_sp);
815         push_word(M.x86.R_BP);
816         push_word(M.x86.R_SI);
817         push_word(M.x86.R_DI);
818     }
819     DECODE_CLEAR_SEGOVR();
820     END_OF_INSTR();
821 }
822
823 /****************************************************************************
824 REMARKS:
825 Handles opcode 0x61
826 ****************************************************************************/
827 void x86emuOp_pop_all(u8 X86EMU_UNUSED(op1))
828 {
829     START_OF_INSTR();
830     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
831         DECODE_PRINTF("POPAD\n");
832     } else {
833         DECODE_PRINTF("POPA\n");
834     }
835     TRACE_AND_STEP();
836     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
837         M.x86.R_EDI = pop_long();
838         M.x86.R_ESI = pop_long();
839         M.x86.R_EBP = pop_long();
840         M.x86.R_ESP += 4;              /* skip ESP */
841         M.x86.R_EBX = pop_long();
842         M.x86.R_EDX = pop_long();
843         M.x86.R_ECX = pop_long();
844         M.x86.R_EAX = pop_long();
845     } else {
846         M.x86.R_DI = pop_word();
847         M.x86.R_SI = pop_word();
848         M.x86.R_BP = pop_word();
849         M.x86.R_SP += 2;               /* skip SP */
850         M.x86.R_BX = pop_word();
851         M.x86.R_DX = pop_word();
852         M.x86.R_CX = pop_word();
853         M.x86.R_AX = pop_word();
854     }
855     DECODE_CLEAR_SEGOVR();
856     END_OF_INSTR();
857 }
858
859 /*opcode 0x62   ILLEGAL OP, calls x86emuOp_illegal_op() */
860 /*opcode 0x63   ILLEGAL OP, calls x86emuOp_illegal_op() */
861
862 /****************************************************************************
863 REMARKS:
864 Handles opcode 0x64
865 ****************************************************************************/
866 void x86emuOp_segovr_FS(u8 X86EMU_UNUSED(op1))
867 {
868     START_OF_INSTR();
869     DECODE_PRINTF("FS:\n");
870     TRACE_AND_STEP();
871     M.x86.mode |= SYSMODE_SEGOVR_FS;
872     /*
873      * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
874      * opcode subroutines we do not want to do this.
875      */
876     END_OF_INSTR();
877 }
878
879 /****************************************************************************
880 REMARKS:
881 Handles opcode 0x65
882 ****************************************************************************/
883 void x86emuOp_segovr_GS(u8 X86EMU_UNUSED(op1))
884 {
885     START_OF_INSTR();
886     DECODE_PRINTF("GS:\n");
887     TRACE_AND_STEP();
888     M.x86.mode |= SYSMODE_SEGOVR_GS;
889     /*
890      * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
891      * opcode subroutines we do not want to do this.
892      */
893     END_OF_INSTR();
894 }
895
896 /****************************************************************************
897 REMARKS:
898 Handles opcode 0x66 - prefix for 32-bit register
899 ****************************************************************************/
900 void x86emuOp_prefix_data(u8 X86EMU_UNUSED(op1))
901 {
902     START_OF_INSTR();
903     DECODE_PRINTF("DATA:\n");
904     TRACE_AND_STEP();
905     M.x86.mode |= SYSMODE_PREFIX_DATA;
906     /* note no DECODE_CLEAR_SEGOVR here. */
907     END_OF_INSTR();
908 }
909
910 /****************************************************************************
911 REMARKS:
912 Handles opcode 0x67 - prefix for 32-bit address
913 ****************************************************************************/
914 void x86emuOp_prefix_addr(u8 X86EMU_UNUSED(op1))
915 {
916     START_OF_INSTR();
917     DECODE_PRINTF("ADDR:\n");
918     TRACE_AND_STEP();
919     M.x86.mode |= SYSMODE_PREFIX_ADDR;
920     /* note no DECODE_CLEAR_SEGOVR here. */
921     END_OF_INSTR();
922 }
923
924 /****************************************************************************
925 REMARKS:
926 Handles opcode 0x68
927 ****************************************************************************/
928 void x86emuOp_push_word_IMM(u8 X86EMU_UNUSED(op1))
929 {
930     u32 imm;
931
932     START_OF_INSTR();
933     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
934         imm = fetch_long_imm();
935     } else {
936         imm = fetch_word_imm();
937     }
938     DECODE_PRINTF2("PUSH\t%x\n", imm);
939     TRACE_AND_STEP();
940     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
941         push_long(imm);
942     } else {
943         push_word((u16)imm);
944     }
945     DECODE_CLEAR_SEGOVR();
946     END_OF_INSTR();
947 }
948
949 /****************************************************************************
950 REMARKS:
951 Handles opcode 0x69
952 ****************************************************************************/
953 void x86emuOp_imul_word_IMM(u8 X86EMU_UNUSED(op1))
954 {
955     int mod, rl, rh;
956     uint srcoffset;
957
958     START_OF_INSTR();
959     DECODE_PRINTF("IMUL\t");
960     FETCH_DECODE_MODRM(mod, rh, rl);
961     if (mod < 3) {
962         srcoffset = decode_rmXX_address(mod, rl);
963         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
964             u32 *destreg;
965             u32 srcval;
966             u32 res_lo,res_hi;
967             s32 imm;
968
969             destreg = DECODE_RM_LONG_REGISTER(rh);
970             DECODE_PRINTF(",");
971             srcval = fetch_data_long(srcoffset);
972             imm = fetch_long_imm();
973             DECODE_PRINTF2(",%d\n", (s32)imm);
974             TRACE_AND_STEP();
975             imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
976             if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
977                 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
978                 CLEAR_FLAG(F_CF);
979                 CLEAR_FLAG(F_OF);
980             } else {
981                 SET_FLAG(F_CF);
982                 SET_FLAG(F_OF);
983             }
984             *destreg = (u32)res_lo;
985         } else {
986             u16 *destreg;
987             u16 srcval;
988             u32 res;
989             s16 imm;
990
991             destreg = DECODE_RM_WORD_REGISTER(rh);
992             DECODE_PRINTF(",");
993             srcval = fetch_data_word(srcoffset);
994             imm = fetch_word_imm();
995             DECODE_PRINTF2(",%d\n", (s32)imm);
996             TRACE_AND_STEP();
997             res = (s16)srcval * (s16)imm;
998             if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
999                 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1000                 CLEAR_FLAG(F_CF);
1001                 CLEAR_FLAG(F_OF);
1002             } else {
1003                 SET_FLAG(F_CF);
1004                 SET_FLAG(F_OF);
1005             }
1006             *destreg = (u16)res;
1007         }
1008     } else {                     /* register to register */
1009         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1010             u32 *destreg,*srcreg;
1011             u32 res_lo,res_hi;
1012             s32 imm;
1013
1014             destreg = DECODE_RM_LONG_REGISTER(rh);
1015             DECODE_PRINTF(",");
1016             srcreg = DECODE_RM_LONG_REGISTER(rl);
1017             imm = fetch_long_imm();
1018             DECODE_PRINTF2(",%d\n", (s32)imm);
1019             TRACE_AND_STEP();
1020             imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
1021             if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1022                 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1023                 CLEAR_FLAG(F_CF);
1024                 CLEAR_FLAG(F_OF);
1025             } else {
1026                 SET_FLAG(F_CF);
1027                 SET_FLAG(F_OF);
1028             }
1029             *destreg = (u32)res_lo;
1030         } else {
1031             u16 *destreg,*srcreg;
1032             u32 res;
1033             s16 imm;
1034
1035             destreg = DECODE_RM_WORD_REGISTER(rh);
1036             DECODE_PRINTF(",");
1037             srcreg = DECODE_RM_WORD_REGISTER(rl);
1038             imm = fetch_word_imm();
1039             DECODE_PRINTF2(",%d\n", (s32)imm);
1040             res = (s16)*srcreg * (s16)imm;
1041             if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1042                 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1043                 CLEAR_FLAG(F_CF);
1044                 CLEAR_FLAG(F_OF);
1045             } else {
1046                 SET_FLAG(F_CF);
1047                 SET_FLAG(F_OF);
1048             }
1049             *destreg = (u16)res;
1050         }
1051     }
1052     DECODE_CLEAR_SEGOVR();
1053     END_OF_INSTR();
1054 }
1055
1056 /****************************************************************************
1057 REMARKS:
1058 Handles opcode 0x6a
1059 ****************************************************************************/
1060 void x86emuOp_push_byte_IMM(u8 X86EMU_UNUSED(op1))
1061 {
1062     s16 imm;
1063
1064     START_OF_INSTR();
1065     imm = (s8)fetch_byte_imm();
1066     DECODE_PRINTF2("PUSH\t%d\n", imm);
1067     TRACE_AND_STEP();
1068     push_word(imm);
1069     DECODE_CLEAR_SEGOVR();
1070     END_OF_INSTR();
1071 }
1072
1073 /****************************************************************************
1074 REMARKS:
1075 Handles opcode 0x6b
1076 ****************************************************************************/
1077 void x86emuOp_imul_byte_IMM(u8 X86EMU_UNUSED(op1))
1078 {
1079     int mod, rl, rh;
1080     uint srcoffset;
1081     s8  imm;
1082
1083     START_OF_INSTR();
1084     DECODE_PRINTF("IMUL\t");
1085     FETCH_DECODE_MODRM(mod, rh, rl);
1086     if (mod < 3) {
1087         srcoffset = decode_rmXX_address(mod, rl);
1088         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1089             u32 *destreg;
1090             u32 srcval;
1091             u32 res_lo,res_hi;
1092
1093             destreg = DECODE_RM_LONG_REGISTER(rh);
1094             DECODE_PRINTF(",");
1095             srcval = fetch_data_long(srcoffset);
1096             imm = fetch_byte_imm();
1097             DECODE_PRINTF2(",%d\n", (s32)imm);
1098             TRACE_AND_STEP();
1099             imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
1100             if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1101                 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1102                 CLEAR_FLAG(F_CF);
1103                 CLEAR_FLAG(F_OF);
1104             } else {
1105                 SET_FLAG(F_CF);
1106                 SET_FLAG(F_OF);
1107             }
1108             *destreg = (u32)res_lo;
1109         } else {
1110             u16 *destreg;
1111             u16 srcval;
1112             u32 res;
1113
1114             destreg = DECODE_RM_WORD_REGISTER(rh);
1115             DECODE_PRINTF(",");
1116             srcval = fetch_data_word(srcoffset);
1117             imm = fetch_byte_imm();
1118             DECODE_PRINTF2(",%d\n", (s32)imm);
1119             TRACE_AND_STEP();
1120             res = (s16)srcval * (s16)imm;
1121             if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1122                 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1123                 CLEAR_FLAG(F_CF);
1124                 CLEAR_FLAG(F_OF);
1125             } else {
1126                 SET_FLAG(F_CF);
1127                 SET_FLAG(F_OF);
1128             }
1129             *destreg = (u16)res;
1130         }
1131     } else {                     /* register to register */
1132         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1133             u32 *destreg,*srcreg;
1134             u32 res_lo,res_hi;
1135
1136             destreg = DECODE_RM_LONG_REGISTER(rh);
1137             DECODE_PRINTF(",");
1138             srcreg = DECODE_RM_LONG_REGISTER(rl);
1139             imm = fetch_byte_imm();
1140             DECODE_PRINTF2(",%d\n", (s32)imm);
1141             TRACE_AND_STEP();
1142             imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
1143             if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1144                 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1145                 CLEAR_FLAG(F_CF);
1146                 CLEAR_FLAG(F_OF);
1147             } else {
1148                 SET_FLAG(F_CF);
1149                 SET_FLAG(F_OF);
1150             }
1151             *destreg = (u32)res_lo;
1152         } else {
1153             u16 *destreg,*srcreg;
1154             u32 res;
1155
1156             destreg = DECODE_RM_WORD_REGISTER(rh);
1157             DECODE_PRINTF(",");
1158             srcreg = DECODE_RM_WORD_REGISTER(rl);
1159             imm = fetch_byte_imm();
1160             DECODE_PRINTF2(",%d\n", (s32)imm);
1161             TRACE_AND_STEP();
1162             res = (s16)*srcreg * (s16)imm;
1163             if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1164                 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1165                 CLEAR_FLAG(F_CF);
1166                 CLEAR_FLAG(F_OF);
1167             } else {
1168                 SET_FLAG(F_CF);
1169                 SET_FLAG(F_OF);
1170             }
1171             *destreg = (u16)res;
1172         }
1173     }
1174     DECODE_CLEAR_SEGOVR();
1175     END_OF_INSTR();
1176 }
1177
1178 /****************************************************************************
1179 REMARKS:
1180 Handles opcode 0x6c
1181 ****************************************************************************/
1182 void x86emuOp_ins_byte(u8 X86EMU_UNUSED(op1))
1183 {
1184     START_OF_INSTR();
1185     DECODE_PRINTF("INSB\n");
1186     ins(1);
1187     TRACE_AND_STEP();
1188     DECODE_CLEAR_SEGOVR();
1189     END_OF_INSTR();
1190 }
1191
1192 /****************************************************************************
1193 REMARKS:
1194 Handles opcode 0x6d
1195 ****************************************************************************/
1196 void x86emuOp_ins_word(u8 X86EMU_UNUSED(op1))
1197 {
1198     START_OF_INSTR();
1199     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1200         DECODE_PRINTF("INSD\n");
1201         ins(4);
1202     } else {
1203         DECODE_PRINTF("INSW\n");
1204         ins(2);
1205     }
1206     TRACE_AND_STEP();
1207     DECODE_CLEAR_SEGOVR();
1208     END_OF_INSTR();
1209 }
1210
1211 /****************************************************************************
1212 REMARKS:
1213 Handles opcode 0x6e
1214 ****************************************************************************/
1215 void x86emuOp_outs_byte(u8 X86EMU_UNUSED(op1))
1216 {
1217     START_OF_INSTR();
1218     DECODE_PRINTF("OUTSB\n");
1219     outs(1);
1220     TRACE_AND_STEP();
1221     DECODE_CLEAR_SEGOVR();
1222     END_OF_INSTR();
1223 }
1224
1225 /****************************************************************************
1226 REMARKS:
1227 Handles opcode 0x6f
1228 ****************************************************************************/
1229 void x86emuOp_outs_word(u8 X86EMU_UNUSED(op1))
1230 {
1231     START_OF_INSTR();
1232     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1233         DECODE_PRINTF("OUTSD\n");
1234         outs(4);
1235     } else {
1236         DECODE_PRINTF("OUTSW\n");
1237         outs(2);
1238     }
1239     TRACE_AND_STEP();
1240     DECODE_CLEAR_SEGOVR();
1241     END_OF_INSTR();
1242 }
1243
1244 /****************************************************************************
1245 REMARKS:
1246 Handles opcode 0x70 - 0x7F
1247 ****************************************************************************/
1248 int x86emu_check_jump_condition(u8 op);
1249
1250 void x86emuOp_jump_near_cond(u8 op1)
1251 {
1252     s8 offset;
1253     u16 target;
1254     int cond;
1255
1256     /* jump to byte offset if overflow flag is set */
1257     START_OF_INSTR();
1258     cond = x86emu_check_jump_condition(op1 & 0xF);
1259     offset = (s8)fetch_byte_imm();
1260     target = (u16)(M.x86.R_IP + (s16)offset);
1261     DECODE_PRINTF2("%x\n", target);
1262     TRACE_AND_STEP();
1263     if (cond)
1264         M.x86.R_IP = target;
1265     DECODE_CLEAR_SEGOVR();
1266     END_OF_INSTR();
1267 }
1268
1269 /****************************************************************************
1270 REMARKS:
1271 Handles opcode 0x80
1272 ****************************************************************************/
1273 void x86emuOp_opc80_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
1274 {
1275     int mod, rl, rh;
1276     u8 *destreg;
1277     uint destoffset;
1278     u8 imm;
1279     u8 destval;
1280
1281     /*
1282      * Weirdo special case instruction format.  Part of the opcode
1283      * held below in "RH".  Doubly nested case would result, except
1284      * that the decoded instruction
1285      */
1286     START_OF_INSTR();
1287     FETCH_DECODE_MODRM(mod, rh, rl);
1288 #ifdef DEBUG
1289     if (DEBUG_DECODE()) {
1290         /* XXX DECODE_PRINTF may be changed to something more
1291            general, so that it is important to leave the strings
1292            in the same format, even though the result is that the
1293            above test is done twice. */
1294
1295         switch (rh) {
1296         case 0:
1297             DECODE_PRINTF("ADD\t");
1298             break;
1299         case 1:
1300             DECODE_PRINTF("OR\t");
1301             break;
1302         case 2:
1303             DECODE_PRINTF("ADC\t");
1304             break;
1305         case 3:
1306             DECODE_PRINTF("SBB\t");
1307             break;
1308         case 4:
1309             DECODE_PRINTF("AND\t");
1310             break;
1311         case 5:
1312             DECODE_PRINTF("SUB\t");
1313             break;
1314         case 6:
1315             DECODE_PRINTF("XOR\t");
1316             break;
1317         case 7:
1318             DECODE_PRINTF("CMP\t");
1319             break;
1320         }
1321     }
1322 #endif
1323     /* know operation, decode the mod byte to find the addressing
1324        mode. */
1325     if (mod < 3) {
1326         DECODE_PRINTF("BYTE PTR ");
1327         destoffset = decode_rmXX_address(mod, rl);
1328         DECODE_PRINTF(",");
1329         destval = fetch_data_byte(destoffset);
1330         imm = fetch_byte_imm();
1331         DECODE_PRINTF2("%x\n", imm);
1332         TRACE_AND_STEP();
1333         destval = (*genop_byte_operation[rh]) (destval, imm);
1334         if (rh != 7)
1335             store_data_byte(destoffset, destval);
1336     } else {                     /* register to register */
1337         destreg = DECODE_RM_BYTE_REGISTER(rl);
1338         DECODE_PRINTF(",");
1339         imm = fetch_byte_imm();
1340         DECODE_PRINTF2("%x\n", imm);
1341         TRACE_AND_STEP();
1342         destval = (*genop_byte_operation[rh]) (*destreg, imm);
1343         if (rh != 7)
1344             *destreg = destval;
1345     }
1346     DECODE_CLEAR_SEGOVR();
1347     END_OF_INSTR();
1348 }
1349
1350 /****************************************************************************
1351 REMARKS:
1352 Handles opcode 0x81
1353 ****************************************************************************/
1354 void x86emuOp_opc81_word_RM_IMM(u8 X86EMU_UNUSED(op1))
1355 {
1356     int mod, rl, rh;
1357     uint destoffset;
1358
1359     /*
1360      * Weirdo special case instruction format.  Part of the opcode
1361      * held below in "RH".  Doubly nested case would result, except
1362      * that the decoded instruction
1363      */
1364     START_OF_INSTR();
1365     FETCH_DECODE_MODRM(mod, rh, rl);
1366 #ifdef DEBUG
1367     if (DEBUG_DECODE()) {
1368         /* XXX DECODE_PRINTF may be changed to something more
1369            general, so that it is important to leave the strings
1370            in the same format, even though the result is that the
1371            above test is done twice. */
1372
1373         switch (rh) {
1374         case 0:
1375             DECODE_PRINTF("ADD\t");
1376             break;
1377         case 1:
1378             DECODE_PRINTF("OR\t");
1379             break;
1380         case 2:
1381             DECODE_PRINTF("ADC\t");
1382             break;
1383         case 3:
1384             DECODE_PRINTF("SBB\t");
1385             break;
1386         case 4:
1387             DECODE_PRINTF("AND\t");
1388             break;
1389         case 5:
1390             DECODE_PRINTF("SUB\t");
1391             break;
1392         case 6:
1393             DECODE_PRINTF("XOR\t");
1394             break;
1395         case 7:
1396             DECODE_PRINTF("CMP\t");
1397             break;
1398         }
1399     }
1400 #endif
1401     /*
1402      * Know operation, decode the mod byte to find the addressing
1403      * mode.
1404      */
1405     if (mod < 3) {
1406         DECODE_PRINTF("DWORD PTR ");
1407         destoffset = decode_rmXX_address(mod, rl);
1408         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1409             u32 destval,imm;
1410
1411             DECODE_PRINTF(",");
1412             destval = fetch_data_long(destoffset);
1413             imm = fetch_long_imm();
1414             DECODE_PRINTF2("%x\n", imm);
1415             TRACE_AND_STEP();
1416             destval = (*genop_long_operation[rh]) (destval, imm);
1417             if (rh != 7)
1418                 store_data_long(destoffset, destval);
1419         } else {
1420             u16 destval,imm;
1421
1422             DECODE_PRINTF(",");
1423             destval = fetch_data_word(destoffset);
1424             imm = fetch_word_imm();
1425             DECODE_PRINTF2("%x\n", imm);
1426             TRACE_AND_STEP();
1427             destval = (*genop_word_operation[rh]) (destval, imm);
1428             if (rh != 7)
1429                 store_data_word(destoffset, destval);
1430         }
1431     } else {                     /* register to register */
1432         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1433             u32 *destreg;
1434             u32 destval,imm;
1435
1436             destreg = DECODE_RM_LONG_REGISTER(rl);
1437             DECODE_PRINTF(",");
1438             imm = fetch_long_imm();
1439             DECODE_PRINTF2("%x\n", imm);
1440             TRACE_AND_STEP();
1441             destval = (*genop_long_operation[rh]) (*destreg, imm);
1442             if (rh != 7)
1443                 *destreg = destval;
1444         } else {
1445             u16 *destreg;
1446             u16 destval,imm;
1447
1448             destreg = DECODE_RM_WORD_REGISTER(rl);
1449             DECODE_PRINTF(",");
1450             imm = fetch_word_imm();
1451             DECODE_PRINTF2("%x\n", imm);
1452             TRACE_AND_STEP();
1453             destval = (*genop_word_operation[rh]) (*destreg, imm);
1454             if (rh != 7)
1455                 *destreg = destval;
1456         }
1457     }
1458     DECODE_CLEAR_SEGOVR();
1459     END_OF_INSTR();
1460 }
1461
1462 /****************************************************************************
1463 REMARKS:
1464 Handles opcode 0x82
1465 ****************************************************************************/
1466 void x86emuOp_opc82_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
1467 {
1468     int mod, rl, rh;
1469     u8 *destreg;
1470     uint destoffset;
1471     u8 imm;
1472     u8 destval;
1473
1474     /*
1475      * Weirdo special case instruction format.  Part of the opcode
1476      * held below in "RH".  Doubly nested case would result, except
1477      * that the decoded instruction Similar to opcode 81, except that
1478      * the immediate byte is sign extended to a word length.
1479      */
1480     START_OF_INSTR();
1481     FETCH_DECODE_MODRM(mod, rh, rl);
1482 #ifdef DEBUG
1483     if (DEBUG_DECODE()) {
1484         /* XXX DECODE_PRINTF may be changed to something more
1485            general, so that it is important to leave the strings
1486            in the same format, even though the result is that the
1487            above test is done twice. */
1488         switch (rh) {
1489         case 0:
1490             DECODE_PRINTF("ADD\t");
1491             break;
1492         case 1:
1493             DECODE_PRINTF("OR\t");
1494             break;
1495         case 2:
1496             DECODE_PRINTF("ADC\t");
1497             break;
1498         case 3:
1499             DECODE_PRINTF("SBB\t");
1500             break;
1501         case 4:
1502             DECODE_PRINTF("AND\t");
1503             break;
1504         case 5:
1505             DECODE_PRINTF("SUB\t");
1506             break;
1507         case 6:
1508             DECODE_PRINTF("XOR\t");
1509             break;
1510         case 7:
1511             DECODE_PRINTF("CMP\t");
1512             break;
1513         }
1514     }
1515 #endif
1516     /* know operation, decode the mod byte to find the addressing
1517        mode. */
1518     if (mod < 3) {
1519         DECODE_PRINTF("BYTE PTR ");
1520         destoffset = decode_rmXX_address(mod, rl);
1521         destval = fetch_data_byte(destoffset);
1522         imm = fetch_byte_imm();
1523         DECODE_PRINTF2(",%x\n", imm);
1524         TRACE_AND_STEP();
1525         destval = (*genop_byte_operation[rh]) (destval, imm);
1526         if (rh != 7)
1527             store_data_byte(destoffset, destval);
1528     } else {                     /* register to register */
1529         destreg = DECODE_RM_BYTE_REGISTER(rl);
1530         imm = fetch_byte_imm();
1531         DECODE_PRINTF2(",%x\n", imm);
1532         TRACE_AND_STEP();
1533         destval = (*genop_byte_operation[rh]) (*destreg, imm);
1534         if (rh != 7)
1535             *destreg = destval;
1536     }
1537     DECODE_CLEAR_SEGOVR();
1538     END_OF_INSTR();
1539 }
1540
1541 /****************************************************************************
1542 REMARKS:
1543 Handles opcode 0x83
1544 ****************************************************************************/
1545 void x86emuOp_opc83_word_RM_IMM(u8 X86EMU_UNUSED(op1))
1546 {
1547     int mod, rl, rh;
1548     uint destoffset;
1549
1550     /*
1551      * Weirdo special case instruction format.  Part of the opcode
1552      * held below in "RH".  Doubly nested case would result, except
1553      * that the decoded instruction Similar to opcode 81, except that
1554      * the immediate byte is sign extended to a word length.
1555      */
1556     START_OF_INSTR();
1557     FETCH_DECODE_MODRM(mod, rh, rl);
1558 #ifdef DEBUG
1559     if (DEBUG_DECODE()) {
1560         /* XXX DECODE_PRINTF may be changed to something more
1561            general, so that it is important to leave the strings
1562            in the same format, even though the result is that the
1563            above test is done twice. */
1564        switch (rh) {
1565         case 0:
1566             DECODE_PRINTF("ADD\t");
1567             break;
1568         case 1:
1569             DECODE_PRINTF("OR\t");
1570             break;
1571         case 2:
1572             DECODE_PRINTF("ADC\t");
1573             break;
1574         case 3:
1575             DECODE_PRINTF("SBB\t");
1576             break;
1577         case 4:
1578             DECODE_PRINTF("AND\t");
1579             break;
1580         case 5:
1581             DECODE_PRINTF("SUB\t");
1582             break;
1583         case 6:
1584             DECODE_PRINTF("XOR\t");
1585             break;
1586         case 7:
1587             DECODE_PRINTF("CMP\t");
1588             break;
1589         }
1590     }
1591 #endif
1592     /* know operation, decode the mod byte to find the addressing
1593        mode. */
1594     if (mod < 3) {
1595         DECODE_PRINTF("DWORD PTR ");
1596         destoffset = decode_rmXX_address(mod,rl);
1597
1598         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1599             u32 destval,imm;
1600
1601             destval = fetch_data_long(destoffset);
1602             imm = (s8) fetch_byte_imm();
1603             DECODE_PRINTF2(",%x\n", imm);
1604             TRACE_AND_STEP();
1605             destval = (*genop_long_operation[rh]) (destval, imm);
1606             if (rh != 7)
1607                 store_data_long(destoffset, destval);
1608         } else {
1609             u16 destval,imm;
1610
1611             destval = fetch_data_word(destoffset);
1612             imm = (s8) fetch_byte_imm();
1613             DECODE_PRINTF2(",%x\n", imm);
1614             TRACE_AND_STEP();
1615             destval = (*genop_word_operation[rh]) (destval, imm);
1616             if (rh != 7)
1617                 store_data_word(destoffset, destval);
1618         }
1619     } else {                     /* register to register */
1620         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1621             u32 *destreg;
1622             u32 destval,imm;
1623
1624             destreg = DECODE_RM_LONG_REGISTER(rl);
1625             imm = (s8) fetch_byte_imm();
1626             DECODE_PRINTF2(",%x\n", imm);
1627             TRACE_AND_STEP();
1628             destval = (*genop_long_operation[rh]) (*destreg, imm);
1629             if (rh != 7)
1630                 *destreg = destval;
1631         } else {
1632             u16 *destreg;
1633             u16 destval,imm;
1634
1635             destreg = DECODE_RM_WORD_REGISTER(rl);
1636             imm = (s8) fetch_byte_imm();
1637             DECODE_PRINTF2(",%x\n", imm);
1638             TRACE_AND_STEP();
1639             destval = (*genop_word_operation[rh]) (*destreg, imm);
1640             if (rh != 7)
1641                 *destreg = destval;
1642         }
1643     }
1644     DECODE_CLEAR_SEGOVR();
1645     END_OF_INSTR();
1646 }
1647
1648 /****************************************************************************
1649 REMARKS:
1650 Handles opcode 0x84
1651 ****************************************************************************/
1652 void x86emuOp_test_byte_RM_R(u8 X86EMU_UNUSED(op1))
1653 {
1654     int mod, rl, rh;
1655     u8 *destreg, *srcreg;
1656     uint destoffset;
1657     u8 destval;
1658
1659     START_OF_INSTR();
1660     DECODE_PRINTF("TEST\t");
1661     FETCH_DECODE_MODRM(mod, rh, rl);
1662     if (mod < 3) {
1663         destoffset = decode_rmXX_address(mod, rl);
1664         DECODE_PRINTF(",");
1665         destval = fetch_data_byte(destoffset);
1666         srcreg = DECODE_RM_BYTE_REGISTER(rh);
1667         DECODE_PRINTF("\n");
1668         TRACE_AND_STEP();
1669         test_byte(destval, *srcreg);
1670     } else {                     /* register to register */
1671         destreg = DECODE_RM_BYTE_REGISTER(rl);
1672         DECODE_PRINTF(",");
1673         srcreg = DECODE_RM_BYTE_REGISTER(rh);
1674         DECODE_PRINTF("\n");
1675         TRACE_AND_STEP();
1676         test_byte(*destreg, *srcreg);
1677     }
1678     DECODE_CLEAR_SEGOVR();
1679     END_OF_INSTR();
1680 }
1681
1682 /****************************************************************************
1683 REMARKS:
1684 Handles opcode 0x85
1685 ****************************************************************************/
1686 void x86emuOp_test_word_RM_R(u8 X86EMU_UNUSED(op1))
1687 {
1688     int mod, rl, rh;
1689     uint destoffset;
1690
1691     START_OF_INSTR();
1692     DECODE_PRINTF("TEST\t");
1693     FETCH_DECODE_MODRM(mod, rh, rl);
1694     if (mod < 3) {
1695         destoffset = decode_rmXX_address(mod, rl);
1696         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1697             u32 destval;
1698             u32 *srcreg;
1699
1700             DECODE_PRINTF(",");
1701             destval = fetch_data_long(destoffset);
1702             srcreg = DECODE_RM_LONG_REGISTER(rh);
1703             DECODE_PRINTF("\n");
1704             TRACE_AND_STEP();
1705             test_long(destval, *srcreg);
1706         } else {
1707             u16 destval;
1708             u16 *srcreg;
1709
1710             DECODE_PRINTF(",");
1711             destval = fetch_data_word(destoffset);
1712             srcreg = DECODE_RM_WORD_REGISTER(rh);
1713             DECODE_PRINTF("\n");
1714             TRACE_AND_STEP();
1715             test_word(destval, *srcreg);
1716         }
1717     } else {                     /* register to register */
1718         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1719             u32 *destreg,*srcreg;
1720
1721             destreg = DECODE_RM_LONG_REGISTER(rl);
1722             DECODE_PRINTF(",");
1723             srcreg = DECODE_RM_LONG_REGISTER(rh);
1724             DECODE_PRINTF("\n");
1725             TRACE_AND_STEP();
1726             test_long(*destreg, *srcreg);
1727         } else {
1728             u16 *destreg,*srcreg;
1729
1730             destreg = DECODE_RM_WORD_REGISTER(rl);
1731             DECODE_PRINTF(",");
1732             srcreg = DECODE_RM_WORD_REGISTER(rh);
1733             DECODE_PRINTF("\n");
1734             TRACE_AND_STEP();
1735             test_word(*destreg, *srcreg);
1736         }
1737     }
1738     DECODE_CLEAR_SEGOVR();
1739     END_OF_INSTR();
1740 }
1741
1742 /****************************************************************************
1743 REMARKS:
1744 Handles opcode 0x86
1745 ****************************************************************************/
1746 void x86emuOp_xchg_byte_RM_R(u8 X86EMU_UNUSED(op1))
1747 {
1748     int mod, rl, rh;
1749     u8 *destreg, *srcreg;
1750     uint destoffset;
1751     u8 destval;
1752     u8 tmp;
1753
1754     START_OF_INSTR();
1755     DECODE_PRINTF("XCHG\t");
1756     FETCH_DECODE_MODRM(mod, rh, rl);
1757     if (mod < 3) {
1758         destoffset = decode_rmXX_address(mod, rl);
1759         DECODE_PRINTF(",");
1760         destval = fetch_data_byte(destoffset);
1761         srcreg = DECODE_RM_BYTE_REGISTER(rh);
1762         DECODE_PRINTF("\n");
1763         TRACE_AND_STEP();
1764         tmp = *srcreg;
1765         *srcreg = destval;
1766         destval = tmp;
1767         store_data_byte(destoffset, destval);
1768     } else {                     /* register to register */
1769         destreg = DECODE_RM_BYTE_REGISTER(rl);
1770         DECODE_PRINTF(",");
1771         srcreg = DECODE_RM_BYTE_REGISTER(rh);
1772         DECODE_PRINTF("\n");
1773         TRACE_AND_STEP();
1774         tmp = *srcreg;
1775         *srcreg = *destreg;
1776         *destreg = tmp;
1777     }
1778     DECODE_CLEAR_SEGOVR();
1779     END_OF_INSTR();
1780 }
1781
1782 /****************************************************************************
1783 REMARKS:
1784 Handles opcode 0x87
1785 ****************************************************************************/
1786 void x86emuOp_xchg_word_RM_R(u8 X86EMU_UNUSED(op1))
1787 {
1788     int mod, rl, rh;
1789     uint destoffset;
1790
1791     START_OF_INSTR();
1792     DECODE_PRINTF("XCHG\t");
1793     FETCH_DECODE_MODRM(mod, rh, rl);
1794     if (mod < 3) {
1795         destoffset = decode_rmXX_address(mod, rl);
1796         DECODE_PRINTF(",");
1797         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1798             u32 *srcreg;
1799             u32 destval,tmp;
1800
1801             destval = fetch_data_long(destoffset);
1802             srcreg = DECODE_RM_LONG_REGISTER(rh);
1803             DECODE_PRINTF("\n");
1804             TRACE_AND_STEP();
1805             tmp = *srcreg;
1806             *srcreg = destval;
1807             destval = tmp;
1808             store_data_long(destoffset, destval);
1809         } else {
1810             u16 *srcreg;
1811             u16 destval,tmp;
1812
1813             destval = fetch_data_word(destoffset);
1814             srcreg = DECODE_RM_WORD_REGISTER(rh);
1815             DECODE_PRINTF("\n");
1816             TRACE_AND_STEP();
1817             tmp = *srcreg;
1818             *srcreg = destval;
1819             destval = tmp;
1820             store_data_word(destoffset, destval);
1821         }
1822     } else {                     /* register to register */
1823         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1824             u32 *destreg,*srcreg;
1825             u32 tmp;
1826
1827             destreg = DECODE_RM_LONG_REGISTER(rl);
1828             DECODE_PRINTF(",");
1829             srcreg = DECODE_RM_LONG_REGISTER(rh);
1830             DECODE_PRINTF("\n");
1831             TRACE_AND_STEP();
1832             tmp = *srcreg;
1833             *srcreg = *destreg;
1834             *destreg = tmp;
1835         } else {
1836             u16 *destreg,*srcreg;
1837             u16 tmp;
1838
1839             destreg = DECODE_RM_WORD_REGISTER(rl);
1840             DECODE_PRINTF(",");
1841             srcreg = DECODE_RM_WORD_REGISTER(rh);
1842             DECODE_PRINTF("\n");
1843             TRACE_AND_STEP();
1844             tmp = *srcreg;
1845             *srcreg = *destreg;
1846             *destreg = tmp;
1847         }
1848     }
1849     DECODE_CLEAR_SEGOVR();
1850     END_OF_INSTR();
1851 }
1852
1853 /****************************************************************************
1854 REMARKS:
1855 Handles opcode 0x88
1856 ****************************************************************************/
1857 void x86emuOp_mov_byte_RM_R(u8 X86EMU_UNUSED(op1))
1858 {
1859     int mod, rl, rh;
1860     u8 *destreg, *srcreg;
1861     uint destoffset;
1862
1863     START_OF_INSTR();
1864     DECODE_PRINTF("MOV\t");
1865     FETCH_DECODE_MODRM(mod, rh, rl);
1866     if (mod < 3) {
1867         destoffset = decode_rmXX_address(mod, rl);
1868         DECODE_PRINTF(",");
1869         srcreg = DECODE_RM_BYTE_REGISTER(rh);
1870         DECODE_PRINTF("\n");
1871         TRACE_AND_STEP();
1872         store_data_byte(destoffset, *srcreg);
1873     } else {                     /* register to register */
1874         destreg = DECODE_RM_BYTE_REGISTER(rl);
1875         DECODE_PRINTF(",");
1876         srcreg = DECODE_RM_BYTE_REGISTER(rh);
1877         DECODE_PRINTF("\n");
1878         TRACE_AND_STEP();
1879         *destreg = *srcreg;
1880     }
1881     DECODE_CLEAR_SEGOVR();
1882     END_OF_INSTR();
1883 }
1884
1885 /****************************************************************************
1886 REMARKS:
1887 Handles opcode 0x89
1888 ****************************************************************************/
1889 void x86emuOp_mov_word_RM_R(u8 X86EMU_UNUSED(op1))
1890 {
1891     int mod, rl, rh;
1892     uint destoffset;
1893
1894     START_OF_INSTR();
1895     DECODE_PRINTF("MOV\t");
1896     FETCH_DECODE_MODRM(mod, rh, rl);
1897     if (mod < 3) {
1898         destoffset = decode_rmXX_address(mod, rl);
1899         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1900             u32 *srcreg;
1901
1902             DECODE_PRINTF(",");
1903             srcreg = DECODE_RM_LONG_REGISTER(rh);
1904             DECODE_PRINTF("\n");
1905             TRACE_AND_STEP();
1906             store_data_long(destoffset, *srcreg);
1907         } else {
1908             u16 *srcreg;
1909
1910             DECODE_PRINTF(",");
1911             srcreg = DECODE_RM_WORD_REGISTER(rh);
1912             DECODE_PRINTF("\n");
1913             TRACE_AND_STEP();
1914             store_data_word(destoffset, *srcreg);
1915         }
1916     } else {                     /* register to register */
1917         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1918             u32 *destreg,*srcreg;
1919
1920             destreg = DECODE_RM_LONG_REGISTER(rl);
1921             DECODE_PRINTF(",");
1922             srcreg = DECODE_RM_LONG_REGISTER(rh);
1923             DECODE_PRINTF("\n");
1924             TRACE_AND_STEP();
1925             *destreg = *srcreg;
1926         } else {
1927             u16 *destreg,*srcreg;
1928
1929             destreg = DECODE_RM_WORD_REGISTER(rl);
1930             DECODE_PRINTF(",");
1931             srcreg = DECODE_RM_WORD_REGISTER(rh);
1932             DECODE_PRINTF("\n");
1933             TRACE_AND_STEP();
1934             *destreg = *srcreg;
1935         }
1936     }
1937     DECODE_CLEAR_SEGOVR();
1938     END_OF_INSTR();
1939 }
1940
1941 /****************************************************************************
1942 REMARKS:
1943 Handles opcode 0x8a
1944 ****************************************************************************/
1945 void x86emuOp_mov_byte_R_RM(u8 X86EMU_UNUSED(op1))
1946 {
1947     int mod, rl, rh;
1948     u8 *destreg, *srcreg;
1949     uint srcoffset;
1950     u8 srcval;
1951
1952     START_OF_INSTR();
1953     DECODE_PRINTF("MOV\t");
1954     FETCH_DECODE_MODRM(mod, rh, rl);
1955     if (mod < 3) {
1956         destreg = DECODE_RM_BYTE_REGISTER(rh);
1957         DECODE_PRINTF(",");
1958         srcoffset = decode_rmXX_address(mod, rl);
1959         srcval = fetch_data_byte(srcoffset);
1960         DECODE_PRINTF("\n");
1961         TRACE_AND_STEP();
1962         *destreg = srcval;
1963     } else {                     /* register to register */
1964         destreg = DECODE_RM_BYTE_REGISTER(rh);
1965         DECODE_PRINTF(",");
1966         srcreg = DECODE_RM_BYTE_REGISTER(rl);
1967         DECODE_PRINTF("\n");
1968         TRACE_AND_STEP();
1969         *destreg = *srcreg;
1970     }
1971     DECODE_CLEAR_SEGOVR();
1972     END_OF_INSTR();
1973 }
1974
1975 /****************************************************************************
1976 REMARKS:
1977 Handles opcode 0x8b
1978 ****************************************************************************/
1979 void x86emuOp_mov_word_R_RM(u8 X86EMU_UNUSED(op1))
1980 {
1981     int mod, rl, rh;
1982     uint srcoffset;
1983
1984     START_OF_INSTR();
1985     DECODE_PRINTF("MOV\t");
1986     FETCH_DECODE_MODRM(mod, rh, rl);
1987     if (mod < 3) {
1988         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1989             u32 *destreg;
1990             u32 srcval;
1991
1992             destreg = DECODE_RM_LONG_REGISTER(rh);
1993             DECODE_PRINTF(",");
1994             srcoffset = decode_rmXX_address(mod, rl);
1995             srcval = fetch_data_long(srcoffset);
1996             DECODE_PRINTF("\n");
1997             TRACE_AND_STEP();
1998             *destreg = srcval;
1999         } else {
2000             u16 *destreg;
2001             u16 srcval;
2002
2003             destreg = DECODE_RM_WORD_REGISTER(rh);
2004             DECODE_PRINTF(",");
2005             srcoffset = decode_rmXX_address(mod, rl);
2006             srcval = fetch_data_word(srcoffset);
2007             DECODE_PRINTF("\n");
2008             TRACE_AND_STEP();
2009             *destreg = srcval;
2010         }
2011     } else {                     /* register to register */
2012         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2013             u32 *destreg, *srcreg;
2014
2015             destreg = DECODE_RM_LONG_REGISTER(rh);
2016             DECODE_PRINTF(",");
2017             srcreg = DECODE_RM_LONG_REGISTER(rl);
2018             DECODE_PRINTF("\n");
2019             TRACE_AND_STEP();
2020             *destreg = *srcreg;
2021         } else {
2022             u16 *destreg, *srcreg;
2023
2024             destreg = DECODE_RM_WORD_REGISTER(rh);
2025             DECODE_PRINTF(",");
2026             srcreg = DECODE_RM_WORD_REGISTER(rl);
2027             DECODE_PRINTF("\n");
2028             TRACE_AND_STEP();
2029             *destreg = *srcreg;
2030         }
2031     }
2032     DECODE_CLEAR_SEGOVR();
2033     END_OF_INSTR();
2034 }
2035
2036 /****************************************************************************
2037 REMARKS:
2038 Handles opcode 0x8c
2039 ****************************************************************************/
2040 void x86emuOp_mov_word_RM_SR(u8 X86EMU_UNUSED(op1))
2041 {
2042     int mod, rl, rh;
2043     u16 *destreg, *srcreg;
2044     uint destoffset;
2045     u16 destval;
2046
2047     START_OF_INSTR();
2048     DECODE_PRINTF("MOV\t");
2049     FETCH_DECODE_MODRM(mod, rh, rl);
2050     if (mod < 3) {
2051         destoffset = decode_rmXX_address(mod, rl);
2052         DECODE_PRINTF(",");
2053         srcreg = decode_rm_seg_register(rh);
2054         DECODE_PRINTF("\n");
2055         TRACE_AND_STEP();
2056         destval = *srcreg;
2057         store_data_word(destoffset, destval);
2058     } else {                     /* register to register */
2059         destreg = DECODE_RM_WORD_REGISTER(rl);
2060         DECODE_PRINTF(",");
2061         srcreg = decode_rm_seg_register(rh);
2062         DECODE_PRINTF("\n");
2063         TRACE_AND_STEP();
2064         *destreg = *srcreg;
2065     }
2066     DECODE_CLEAR_SEGOVR();
2067     END_OF_INSTR();
2068 }
2069
2070 /****************************************************************************
2071 REMARKS:
2072 Handles opcode 0x8d
2073 ****************************************************************************/
2074 void x86emuOp_lea_word_R_M(u8 X86EMU_UNUSED(op1))
2075 {
2076     int mod, rl, rh;
2077     u16 *srcreg;
2078     uint destoffset;
2079
2080 /*
2081  * TODO: Need to handle address size prefix!
2082  *
2083  * lea  eax,[eax+ebx*2] ??
2084  */
2085
2086     START_OF_INSTR();
2087     DECODE_PRINTF("LEA\t");
2088     FETCH_DECODE_MODRM(mod, rh, rl);
2089     if (mod < 3) {
2090         srcreg = DECODE_RM_WORD_REGISTER(rh);
2091         DECODE_PRINTF(",");
2092         destoffset = decode_rmXX_address(mod, rl);
2093         DECODE_PRINTF("\n");
2094         TRACE_AND_STEP();
2095         *srcreg = (u16)destoffset;
2096         }
2097     /* } else { undefined.  Do nothing. } */
2098     DECODE_CLEAR_SEGOVR();
2099     END_OF_INSTR();
2100 }
2101
2102 /****************************************************************************
2103 REMARKS:
2104 Handles opcode 0x8e
2105 ****************************************************************************/
2106 void x86emuOp_mov_word_SR_RM(u8 X86EMU_UNUSED(op1))
2107 {
2108     int mod, rl, rh;
2109     u16 *destreg, *srcreg;
2110     uint srcoffset;
2111     u16 srcval;
2112
2113     START_OF_INSTR();
2114     DECODE_PRINTF("MOV\t");
2115     FETCH_DECODE_MODRM(mod, rh, rl);
2116     if (mod < 3) {
2117         destreg = decode_rm_seg_register(rh);
2118         DECODE_PRINTF(",");
2119         srcoffset = decode_rmXX_address(mod, rl);
2120         srcval = fetch_data_word(srcoffset);
2121         DECODE_PRINTF("\n");
2122         TRACE_AND_STEP();
2123         *destreg = srcval;
2124     } else {                     /* register to register */
2125         destreg = decode_rm_seg_register(rh);
2126         DECODE_PRINTF(",");
2127         srcreg = DECODE_RM_WORD_REGISTER(rl);
2128         DECODE_PRINTF("\n");
2129         TRACE_AND_STEP();
2130         *destreg = *srcreg;
2131     }
2132     /*
2133      * Clean up, and reset all the R_xSP pointers to the correct
2134      * locations.  This is about 3x too much overhead (doing all the
2135      * segreg ptrs when only one is needed, but this instruction
2136      * *cannot* be that common, and this isn't too much work anyway.
2137      */
2138     DECODE_CLEAR_SEGOVR();
2139     END_OF_INSTR();
2140 }
2141
2142 /****************************************************************************
2143 REMARKS:
2144 Handles opcode 0x8f
2145 ****************************************************************************/
2146 void x86emuOp_pop_RM(u8 X86EMU_UNUSED(op1))
2147 {
2148     int mod, rl, rh;
2149     uint destoffset;
2150
2151     START_OF_INSTR();
2152     DECODE_PRINTF("POP\t");
2153     FETCH_DECODE_MODRM(mod, rh, rl);
2154     if (rh != 0) {
2155         DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
2156         HALT_SYS();
2157     }
2158     if (mod < 3) {
2159         destoffset = decode_rmXX_address(mod, rl);
2160         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2161             u32 destval;
2162
2163             DECODE_PRINTF("\n");
2164             TRACE_AND_STEP();
2165             destval = pop_long();
2166             store_data_long(destoffset, destval);
2167         } else {
2168             u16 destval;
2169
2170             DECODE_PRINTF("\n");
2171             TRACE_AND_STEP();
2172             destval = pop_word();
2173             store_data_word(destoffset, destval);
2174         }
2175     } else {                    /* register to register */
2176         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2177             u32 *destreg;
2178
2179             destreg = DECODE_RM_LONG_REGISTER(rl);
2180             DECODE_PRINTF("\n");
2181             TRACE_AND_STEP();
2182             *destreg = pop_long();
2183         } else {
2184             u16 *destreg;
2185
2186             destreg = DECODE_RM_WORD_REGISTER(rl);
2187             DECODE_PRINTF("\n");
2188             TRACE_AND_STEP();
2189             *destreg = pop_word();
2190         }
2191     }
2192     DECODE_CLEAR_SEGOVR();
2193     END_OF_INSTR();
2194 }
2195
2196 /****************************************************************************
2197 REMARKS:
2198 Handles opcode 0x90
2199 ****************************************************************************/
2200 void x86emuOp_nop(u8 X86EMU_UNUSED(op1))
2201 {
2202     START_OF_INSTR();
2203     DECODE_PRINTF("NOP\n");
2204     TRACE_AND_STEP();
2205     DECODE_CLEAR_SEGOVR();
2206     END_OF_INSTR();
2207 }
2208
2209 /****************************************************************************
2210 REMARKS:
2211 Handles opcode 0x91-0x97
2212 ****************************************************************************/
2213 void x86emuOp_xchg_word_AX_register(u8 X86EMU_UNUSED(op1))
2214 {
2215     u32 tmp;
2216
2217     op1 &= 0x7;
2218
2219     START_OF_INSTR();
2220
2221     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2222         u32 *reg32;
2223         DECODE_PRINTF("XCHG\tEAX,");
2224         reg32 = DECODE_RM_LONG_REGISTER(op1);
2225         DECODE_PRINTF("\n");
2226         TRACE_AND_STEP();
2227         tmp = M.x86.R_EAX;
2228         M.x86.R_EAX = *reg32;
2229         *reg32 = tmp;
2230     } else {
2231         u16 *reg16;
2232         DECODE_PRINTF("XCHG\tAX,");
2233         reg16 = DECODE_RM_WORD_REGISTER(op1);
2234         DECODE_PRINTF("\n");
2235         TRACE_AND_STEP();
2236         tmp = M.x86.R_AX;
2237         M.x86.R_EAX = *reg16;
2238         *reg16 = (u16)tmp;
2239     }
2240     DECODE_CLEAR_SEGOVR();
2241     END_OF_INSTR();
2242 }
2243
2244 /****************************************************************************
2245 REMARKS:
2246 Handles opcode 0x98
2247 ****************************************************************************/
2248 void x86emuOp_cbw(u8 X86EMU_UNUSED(op1))
2249 {
2250     START_OF_INSTR();
2251     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2252         DECODE_PRINTF("CWDE\n");
2253     } else {
2254         DECODE_PRINTF("CBW\n");
2255     }
2256     TRACE_AND_STEP();
2257     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2258         if (M.x86.R_AX & 0x8000) {
2259             M.x86.R_EAX |= 0xffff0000;
2260         } else {
2261             M.x86.R_EAX &= 0x0000ffff;
2262         }
2263     } else {
2264         if (M.x86.R_AL & 0x80) {
2265             M.x86.R_AH = 0xff;
2266         } else {
2267             M.x86.R_AH = 0x0;
2268         }
2269     }
2270     DECODE_CLEAR_SEGOVR();
2271     END_OF_INSTR();
2272 }
2273
2274 /****************************************************************************
2275 REMARKS:
2276 Handles opcode 0x99
2277 ****************************************************************************/
2278 void x86emuOp_cwd(u8 X86EMU_UNUSED(op1))
2279 {
2280     START_OF_INSTR();
2281     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2282         DECODE_PRINTF("CDQ\n");
2283     } else {
2284         DECODE_PRINTF("CWD\n");
2285     }
2286     DECODE_PRINTF("CWD\n");
2287     TRACE_AND_STEP();
2288     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2289         if (M.x86.R_EAX & 0x80000000) {
2290             M.x86.R_EDX = 0xffffffff;
2291         } else {
2292             M.x86.R_EDX = 0x0;
2293         }
2294     } else {
2295         if (M.x86.R_AX & 0x8000) {
2296             M.x86.R_DX = 0xffff;
2297         } else {
2298             M.x86.R_DX = 0x0;
2299         }
2300     }
2301     DECODE_CLEAR_SEGOVR();
2302     END_OF_INSTR();
2303 }
2304
2305 /****************************************************************************
2306 REMARKS:
2307 Handles opcode 0x9a
2308 ****************************************************************************/
2309 void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1))
2310 {
2311     u16 farseg, faroff;
2312
2313     START_OF_INSTR();
2314         DECODE_PRINTF("CALL\t");
2315         faroff = fetch_word_imm();
2316         farseg = fetch_word_imm();
2317         DECODE_PRINTF2("%04x:", farseg);
2318         DECODE_PRINTF2("%04x\n", faroff);
2319         CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, farseg, faroff, "FAR ");
2320
2321     /* XXX
2322      *
2323      * Hooked interrupt vectors calling into our "BIOS" will cause
2324      * problems unless all intersegment stuff is checked for BIOS
2325      * access.  Check needed here.  For moment, let it alone.
2326      */
2327     TRACE_AND_STEP();
2328     push_word(M.x86.R_CS);
2329     M.x86.R_CS = farseg;
2330     push_word(M.x86.R_IP);
2331     M.x86.R_IP = faroff;
2332     DECODE_CLEAR_SEGOVR();
2333     END_OF_INSTR();
2334 }
2335
2336 /****************************************************************************
2337 REMARKS:
2338 Handles opcode 0x9b
2339 ****************************************************************************/
2340 void x86emuOp_wait(u8 X86EMU_UNUSED(op1))
2341 {
2342     START_OF_INSTR();
2343     DECODE_PRINTF("WAIT");
2344     TRACE_AND_STEP();
2345     /* NADA.  */
2346     DECODE_CLEAR_SEGOVR();
2347     END_OF_INSTR();
2348 }
2349
2350 /****************************************************************************
2351 REMARKS:
2352 Handles opcode 0x9c
2353 ****************************************************************************/
2354 void x86emuOp_pushf_word(u8 X86EMU_UNUSED(op1))
2355 {
2356     u32 flags;
2357
2358     START_OF_INSTR();
2359     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2360         DECODE_PRINTF("PUSHFD\n");
2361     } else {
2362         DECODE_PRINTF("PUSHF\n");
2363     }
2364     TRACE_AND_STEP();
2365
2366     /* clear out *all* bits not representing flags, and turn on real bits */
2367     flags = (M.x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
2368     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2369         push_long(flags);
2370     } else {
2371         push_word((u16)flags);
2372     }
2373     DECODE_CLEAR_SEGOVR();
2374     END_OF_INSTR();
2375 }
2376
2377 /****************************************************************************
2378 REMARKS:
2379 Handles opcode 0x9d
2380 ****************************************************************************/
2381 void x86emuOp_popf_word(u8 X86EMU_UNUSED(op1))
2382 {
2383     START_OF_INSTR();
2384     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2385         DECODE_PRINTF("POPFD\n");
2386     } else {
2387         DECODE_PRINTF("POPF\n");
2388     }
2389     TRACE_AND_STEP();
2390     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2391         M.x86.R_EFLG = pop_long();
2392     } else {
2393         M.x86.R_FLG = pop_word();
2394     }
2395     DECODE_CLEAR_SEGOVR();
2396     END_OF_INSTR();
2397 }
2398
2399 /****************************************************************************
2400 REMARKS:
2401 Handles opcode 0x9e
2402 ****************************************************************************/
2403 void x86emuOp_sahf(u8 X86EMU_UNUSED(op1))
2404 {
2405     START_OF_INSTR();
2406     DECODE_PRINTF("SAHF\n");
2407     TRACE_AND_STEP();
2408     /* clear the lower bits of the flag register */
2409     M.x86.R_FLG &= 0xffffff00;
2410     /* or in the AH register into the flags register */
2411     M.x86.R_FLG |= M.x86.R_AH;
2412     DECODE_CLEAR_SEGOVR();
2413     END_OF_INSTR();
2414 }
2415
2416 /****************************************************************************
2417 REMARKS:
2418 Handles opcode 0x9f
2419 ****************************************************************************/
2420 void x86emuOp_lahf(u8 X86EMU_UNUSED(op1))
2421 {
2422     START_OF_INSTR();
2423     DECODE_PRINTF("LAHF\n");
2424     TRACE_AND_STEP();
2425         M.x86.R_AH = (u8)(M.x86.R_FLG & 0xff);
2426     /*undocumented TC++ behavior??? Nope.  It's documented, but
2427        you have too look real hard to notice it. */
2428     M.x86.R_AH |= 0x2;
2429     DECODE_CLEAR_SEGOVR();
2430     END_OF_INSTR();
2431 }
2432
2433 /****************************************************************************
2434 REMARKS:
2435 Handles opcode 0xa0
2436 ****************************************************************************/
2437 void x86emuOp_mov_AL_M_IMM(u8 X86EMU_UNUSED(op1))
2438 {
2439     u16 offset;
2440
2441     START_OF_INSTR();
2442     DECODE_PRINTF("MOV\tAL,");
2443     offset = fetch_word_imm();
2444     DECODE_PRINTF2("[%04x]\n", offset);
2445     TRACE_AND_STEP();
2446     M.x86.R_AL = fetch_data_byte(offset);
2447     DECODE_CLEAR_SEGOVR();
2448     END_OF_INSTR();
2449 }
2450
2451 /****************************************************************************
2452 REMARKS:
2453 Handles opcode 0xa1
2454 ****************************************************************************/
2455 void x86emuOp_mov_AX_M_IMM(u8 X86EMU_UNUSED(op1))
2456 {
2457     u16 offset;
2458
2459     START_OF_INSTR();
2460     offset = fetch_word_imm();
2461     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2462         DECODE_PRINTF2("MOV\tEAX,[%04x]\n", offset);
2463     } else {
2464         DECODE_PRINTF2("MOV\tAX,[%04x]\n", offset);
2465     }
2466     TRACE_AND_STEP();
2467     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2468         M.x86.R_EAX = fetch_data_long(offset);
2469     } else {
2470         M.x86.R_AX = fetch_data_word(offset);
2471     }
2472     DECODE_CLEAR_SEGOVR();
2473     END_OF_INSTR();
2474 }
2475
2476 /****************************************************************************
2477 REMARKS:
2478 Handles opcode 0xa2
2479 ****************************************************************************/
2480 void x86emuOp_mov_M_AL_IMM(u8 X86EMU_UNUSED(op1))
2481 {
2482     u16 offset;
2483
2484     START_OF_INSTR();
2485     DECODE_PRINTF("MOV\t");
2486     offset = fetch_word_imm();
2487     DECODE_PRINTF2("[%04x],AL\n", offset);
2488     TRACE_AND_STEP();
2489     store_data_byte(offset, M.x86.R_AL);
2490     DECODE_CLEAR_SEGOVR();
2491     END_OF_INSTR();
2492 }
2493
2494 /****************************************************************************
2495 REMARKS:
2496 Handles opcode 0xa3
2497 ****************************************************************************/
2498 void x86emuOp_mov_M_AX_IMM(u8 X86EMU_UNUSED(op1))
2499 {
2500     u16 offset;
2501
2502     START_OF_INSTR();
2503     offset = fetch_word_imm();
2504     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2505         DECODE_PRINTF2("MOV\t[%04x],EAX\n", offset);
2506     } else {
2507         DECODE_PRINTF2("MOV\t[%04x],AX\n", offset);
2508     }
2509     TRACE_AND_STEP();
2510     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2511         store_data_long(offset, M.x86.R_EAX);
2512     } else {
2513         store_data_word(offset, M.x86.R_AX);
2514     }
2515     DECODE_CLEAR_SEGOVR();
2516     END_OF_INSTR();
2517 }
2518
2519 /****************************************************************************
2520 REMARKS:
2521 Handles opcode 0xa4
2522 ****************************************************************************/
2523 void x86emuOp_movs_byte(u8 X86EMU_UNUSED(op1))
2524 {
2525     u8  val;
2526     u32 count;
2527     int inc;
2528
2529     START_OF_INSTR();
2530     DECODE_PRINTF("MOVS\tBYTE\n");
2531     if (ACCESS_FLAG(F_DF))   /* down */
2532         inc = -1;
2533     else
2534         inc = 1;
2535     TRACE_AND_STEP();
2536     count = 1;
2537     if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2538         /* dont care whether REPE or REPNE */
2539         /* move them until CX is ZERO. */
2540         count = M.x86.R_CX;
2541         M.x86.R_CX = 0;
2542         M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2543     }
2544     while (count--) {
2545         val = fetch_data_byte(M.x86.R_SI);
2546         store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, val);
2547         M.x86.R_SI += inc;
2548         M.x86.R_DI += inc;
2549     }
2550     DECODE_CLEAR_SEGOVR();
2551     END_OF_INSTR();
2552 }
2553
2554 /****************************************************************************
2555 REMARKS:
2556 Handles opcode 0xa5
2557 ****************************************************************************/
2558 void x86emuOp_movs_word(u8 X86EMU_UNUSED(op1))
2559 {
2560     u32 val;
2561     int inc;
2562     u32 count;
2563
2564     START_OF_INSTR();
2565     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2566         DECODE_PRINTF("MOVS\tDWORD\n");
2567         if (ACCESS_FLAG(F_DF))      /* down */
2568             inc = -4;
2569         else
2570             inc = 4;
2571     } else {
2572         DECODE_PRINTF("MOVS\tWORD\n");
2573         if (ACCESS_FLAG(F_DF))      /* down */
2574             inc = -2;
2575         else
2576             inc = 2;
2577     }
2578     TRACE_AND_STEP();
2579     count = 1;
2580     if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2581         /* dont care whether REPE or REPNE */
2582         /* move them until CX is ZERO. */
2583         count = M.x86.R_CX;
2584         M.x86.R_CX = 0;
2585         M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2586     }
2587     while (count--) {
2588         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2589             val = fetch_data_long(M.x86.R_SI);
2590             store_data_long_abs(M.x86.R_ES, M.x86.R_DI, val);
2591         } else {
2592             val = fetch_data_word(M.x86.R_SI);
2593             store_data_word_abs(M.x86.R_ES, M.x86.R_DI, (u16)val);
2594         }
2595         M.x86.R_SI += inc;
2596         M.x86.R_DI += inc;
2597     }
2598     DECODE_CLEAR_SEGOVR();
2599     END_OF_INSTR();
2600 }
2601
2602 /****************************************************************************
2603 REMARKS:
2604 Handles opcode 0xa6
2605 ****************************************************************************/
2606 void x86emuOp_cmps_byte(u8 X86EMU_UNUSED(op1))
2607 {
2608     s8 val1, val2;
2609     int inc;
2610
2611     START_OF_INSTR();
2612     DECODE_PRINTF("CMPS\tBYTE\n");
2613     TRACE_AND_STEP();
2614     if (ACCESS_FLAG(F_DF))   /* down */
2615         inc = -1;
2616     else
2617         inc = 1;
2618
2619     if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2620         /* REPE  */
2621         /* move them until CX is ZERO. */
2622         while (M.x86.R_CX != 0) {
2623             val1 = fetch_data_byte(M.x86.R_SI);
2624             val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2625                      cmp_byte(val1, val2);
2626             M.x86.R_CX -= 1;
2627             M.x86.R_SI += inc;
2628             M.x86.R_DI += inc;
2629             if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && (ACCESS_FLAG(F_ZF) == 0) ) break;
2630             if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2631         }
2632         M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2633     } else {
2634         val1 = fetch_data_byte(M.x86.R_SI);
2635         val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2636         cmp_byte(val1, val2);
2637         M.x86.R_SI += inc;
2638         M.x86.R_DI += inc;
2639     }
2640     DECODE_CLEAR_SEGOVR();
2641     END_OF_INSTR();
2642 }
2643
2644 /****************************************************************************
2645 REMARKS:
2646 Handles opcode 0xa7
2647 ****************************************************************************/
2648 void x86emuOp_cmps_word(u8 X86EMU_UNUSED(op1))
2649 {
2650     u32 val1,val2;
2651     int inc;
2652
2653     START_OF_INSTR();
2654     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2655         DECODE_PRINTF("CMPS\tDWORD\n");
2656         inc = 4;
2657     } else {
2658         DECODE_PRINTF("CMPS\tWORD\n");
2659         inc = 2;
2660     }
2661     if (ACCESS_FLAG(F_DF))   /* down */
2662         inc = -inc;
2663
2664     TRACE_AND_STEP();
2665     if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2666         /* REPE  */
2667         /* move them until CX is ZERO. */
2668         while (M.x86.R_CX != 0) {
2669             if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2670                 val1 = fetch_data_long(M.x86.R_SI);
2671                 val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2672                 cmp_long(val1, val2);
2673             } else {
2674                 val1 = fetch_data_word(M.x86.R_SI);
2675                 val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2676                 cmp_word((u16)val1, (u16)val2);
2677             }
2678             M.x86.R_CX -= 1;
2679             M.x86.R_SI += inc;
2680             M.x86.R_DI += inc;
2681             if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && ACCESS_FLAG(F_ZF) == 0 ) break;
2682             if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2683         }
2684         M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2685     } else {
2686         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2687             val1 = fetch_data_long(M.x86.R_SI);
2688             val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2689             cmp_long(val1, val2);
2690         } else {
2691             val1 = fetch_data_word(M.x86.R_SI);
2692             val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2693             cmp_word((u16)val1, (u16)val2);
2694         }
2695         M.x86.R_SI += inc;
2696         M.x86.R_DI += inc;
2697     }
2698     DECODE_CLEAR_SEGOVR();
2699     END_OF_INSTR();
2700 }
2701
2702 /****************************************************************************
2703 REMARKS:
2704 Handles opcode 0xa8
2705 ****************************************************************************/
2706 void x86emuOp_test_AL_IMM(u8 X86EMU_UNUSED(op1))
2707 {
2708     int imm;
2709
2710     START_OF_INSTR();
2711     DECODE_PRINTF("TEST\tAL,");
2712     imm = fetch_byte_imm();
2713     DECODE_PRINTF2("%04x\n", imm);
2714     TRACE_AND_STEP();
2715         test_byte(M.x86.R_AL, (u8)imm);
2716     DECODE_CLEAR_SEGOVR();
2717     END_OF_INSTR();
2718 }
2719
2720 /****************************************************************************
2721 REMARKS:
2722 Handles opcode 0xa9
2723 ****************************************************************************/
2724 void x86emuOp_test_AX_IMM(u8 X86EMU_UNUSED(op1))
2725 {
2726     u32 srcval;
2727
2728     START_OF_INSTR();
2729     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2730         DECODE_PRINTF("TEST\tEAX,");
2731         srcval = fetch_long_imm();
2732     } else {
2733         DECODE_PRINTF("TEST\tAX,");
2734         srcval = fetch_word_imm();
2735     }
2736     DECODE_PRINTF2("%x\n", srcval);
2737     TRACE_AND_STEP();
2738     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2739         test_long(M.x86.R_EAX, srcval);
2740     } else {
2741         test_word(M.x86.R_AX, (u16)srcval);
2742     }
2743     DECODE_CLEAR_SEGOVR();
2744     END_OF_INSTR();
2745 }
2746
2747 /****************************************************************************
2748 REMARKS:
2749 Handles opcode 0xaa
2750 ****************************************************************************/
2751 void x86emuOp_stos_byte(u8 X86EMU_UNUSED(op1))
2752 {
2753     int inc;
2754
2755     START_OF_INSTR();
2756     DECODE_PRINTF("STOS\tBYTE\n");
2757     if (ACCESS_FLAG(F_DF))   /* down */
2758         inc = -1;
2759     else
2760         inc = 1;
2761     TRACE_AND_STEP();
2762     if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2763         /* dont care whether REPE or REPNE */
2764         /* move them until CX is ZERO. */
2765         while (M.x86.R_CX != 0) {
2766             store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
2767             M.x86.R_CX -= 1;
2768             M.x86.R_DI += inc;
2769         }
2770         M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2771     } else {
2772         store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
2773         M.x86.R_DI += inc;
2774     }
2775     DECODE_CLEAR_SEGOVR();
2776     END_OF_INSTR();
2777 }
2778
2779 /****************************************************************************
2780 REMARKS:
2781 Handles opcode 0xab
2782 ****************************************************************************/
2783 void x86emuOp_stos_word(u8 X86EMU_UNUSED(op1))
2784 {
2785     int inc;
2786     u32 count;
2787
2788     START_OF_INSTR();
2789     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2790         DECODE_PRINTF("STOS\tDWORD\n");
2791         if (ACCESS_FLAG(F_DF))   /* down */
2792             inc = -4;
2793         else
2794             inc = 4;
2795     } else {
2796         DECODE_PRINTF("STOS\tWORD\n");
2797         if (ACCESS_FLAG(F_DF))   /* down */
2798             inc = -2;
2799         else
2800             inc = 2;
2801     }
2802     TRACE_AND_STEP();
2803     count = 1;
2804     if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2805         /* dont care whether REPE or REPNE */
2806         /* move them until CX is ZERO. */
2807         count = M.x86.R_CX;
2808         M.x86.R_CX = 0;
2809         M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2810     }
2811     while (count--) {
2812         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2813             store_data_long_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_EAX);
2814         } else {
2815             store_data_word_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AX);
2816         }
2817         M.x86.R_DI += inc;
2818     }
2819     DECODE_CLEAR_SEGOVR();
2820     END_OF_INSTR();
2821 }
2822
2823 /****************************************************************************
2824 REMARKS:
2825 Handles opcode 0xac
2826 ****************************************************************************/
2827 void x86emuOp_lods_byte(u8 X86EMU_UNUSED(op1))
2828 {
2829     int inc;
2830
2831     START_OF_INSTR();
2832     DECODE_PRINTF("LODS\tBYTE\n");
2833     TRACE_AND_STEP();
2834     if (ACCESS_FLAG(F_DF))   /* down */
2835         inc = -1;
2836     else
2837         inc = 1;
2838     if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2839         /* dont care whether REPE or REPNE */
2840         /* move them until CX is ZERO. */
2841         while (M.x86.R_CX != 0) {
2842             M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
2843             M.x86.R_CX -= 1;
2844             M.x86.R_SI += inc;
2845         }
2846         M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2847     } else {
2848         M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
2849         M.x86.R_SI += inc;
2850     }
2851     DECODE_CLEAR_SEGOVR();
2852     END_OF_INSTR();
2853 }
2854
2855 /****************************************************************************
2856 REMARKS:
2857 Handles opcode 0xad
2858 ****************************************************************************/
2859 void x86emuOp_lods_word(u8 X86EMU_UNUSED(op1))
2860 {
2861     int inc;
2862     u32 count;
2863
2864     START_OF_INSTR();
2865     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2866         DECODE_PRINTF("LODS\tDWORD\n");
2867         if (ACCESS_FLAG(F_DF))   /* down */
2868             inc = -4;
2869         else
2870             inc = 4;
2871     } else {
2872         DECODE_PRINTF("LODS\tWORD\n");
2873         if (ACCESS_FLAG(F_DF))   /* down */
2874             inc = -2;
2875         else
2876             inc = 2;
2877     }
2878     TRACE_AND_STEP();
2879     count = 1;
2880     if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2881         /* dont care whether REPE or REPNE */
2882         /* move them until CX is ZERO. */
2883         count = M.x86.R_CX;
2884         M.x86.R_CX = 0;
2885         M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2886     }
2887     while (count--) {
2888         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2889             M.x86.R_EAX = fetch_data_long(M.x86.R_SI);
2890         } else {
2891             M.x86.R_AX = fetch_data_word(M.x86.R_SI);
2892         }
2893         M.x86.R_SI += inc;
2894     }
2895     DECODE_CLEAR_SEGOVR();
2896     END_OF_INSTR();
2897 }
2898
2899 /****************************************************************************
2900 REMARKS:
2901 Handles opcode 0xae
2902 ****************************************************************************/
2903 void x86emuOp_scas_byte(u8 X86EMU_UNUSED(op1))
2904 {
2905     s8 val2;
2906     int inc;
2907
2908     START_OF_INSTR();
2909     DECODE_PRINTF("SCAS\tBYTE\n");
2910     TRACE_AND_STEP();
2911     if (ACCESS_FLAG(F_DF))   /* down */
2912         inc = -1;
2913     else
2914         inc = 1;
2915     if (M.x86.mode & SYSMODE_PREFIX_REPE) {
2916         /* REPE  */
2917         /* move them until CX is ZERO. */
2918         while (M.x86.R_CX != 0) {
2919             val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2920             cmp_byte(M.x86.R_AL, val2);
2921             M.x86.R_CX -= 1;
2922             M.x86.R_DI += inc;
2923             if (ACCESS_FLAG(F_ZF) == 0)
2924                 break;
2925         }
2926         M.x86.mode &= ~SYSMODE_PREFIX_REPE;
2927     } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
2928         /* REPNE  */
2929         /* move them until CX is ZERO. */
2930         while (M.x86.R_CX != 0) {
2931             val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2932             cmp_byte(M.x86.R_AL, val2);
2933             M.x86.R_CX -= 1;
2934             M.x86.R_DI += inc;
2935             if (ACCESS_FLAG(F_ZF))
2936                 break;          /* zero flag set means equal */
2937         }
2938         M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
2939     } else {
2940         val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2941         cmp_byte(M.x86.R_AL, val2);
2942         M.x86.R_DI += inc;
2943     }
2944     DECODE_CLEAR_SEGOVR();
2945     END_OF_INSTR();
2946 }
2947
2948 /****************************************************************************
2949 REMARKS:
2950 Handles opcode 0xaf
2951 ****************************************************************************/
2952 void x86emuOp_scas_word(u8 X86EMU_UNUSED(op1))
2953 {
2954     int inc;
2955     u32 val;
2956
2957     START_OF_INSTR();
2958     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2959         DECODE_PRINTF("SCAS\tDWORD\n");
2960         if (ACCESS_FLAG(F_DF))   /* down */
2961             inc = -4;
2962         else
2963             inc = 4;
2964     } else {
2965         DECODE_PRINTF("SCAS\tWORD\n");
2966         if (ACCESS_FLAG(F_DF))   /* down */
2967             inc = -2;
2968         else
2969             inc = 2;
2970     }
2971     TRACE_AND_STEP();
2972     if (M.x86.mode & SYSMODE_PREFIX_REPE) {
2973         /* REPE  */
2974         /* move them until CX is ZERO. */
2975         while (M.x86.R_CX != 0) {
2976             if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2977                 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2978                 cmp_long(M.x86.R_EAX, val);
2979             } else {
2980                 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2981                 cmp_word(M.x86.R_AX, (u16)val);
2982             }
2983             M.x86.R_CX -= 1;
2984             M.x86.R_DI += inc;
2985             if (ACCESS_FLAG(F_ZF) == 0)
2986                 break;
2987         }
2988         M.x86.mode &= ~SYSMODE_PREFIX_REPE;
2989     } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
2990         /* REPNE  */
2991         /* move them until CX is ZERO. */
2992         while (M.x86.R_CX != 0) {
2993             if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2994                 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2995                 cmp_long(M.x86.R_EAX, val);
2996             } else {
2997                 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2998                 cmp_word(M.x86.R_AX, (u16)val);
2999             }
3000             M.x86.R_CX -= 1;
3001             M.x86.R_DI += inc;
3002             if (ACCESS_FLAG(F_ZF))
3003                 break;          /* zero flag set means equal */
3004         }
3005         M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
3006     } else {
3007         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3008             val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
3009             cmp_long(M.x86.R_EAX, val);
3010         } else {
3011             val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
3012             cmp_word(M.x86.R_AX, (u16)val);
3013         }
3014         M.x86.R_DI += inc;
3015     }
3016     DECODE_CLEAR_SEGOVR();
3017     END_OF_INSTR();
3018 }
3019
3020 /****************************************************************************
3021 REMARKS:
3022 Handles opcode 0xb0 - 0xb7
3023 ****************************************************************************/
3024 void x86emuOp_mov_byte_register_IMM(u8 op1)
3025 {
3026     u8 imm, *ptr;
3027
3028     START_OF_INSTR();
3029     DECODE_PRINTF("MOV\t");
3030     ptr = DECODE_RM_BYTE_REGISTER(op1 & 0x7);
3031     DECODE_PRINTF(",");
3032     imm = fetch_byte_imm();
3033     DECODE_PRINTF2("%x\n", imm);
3034     TRACE_AND_STEP();
3035     *ptr = imm;
3036     DECODE_CLEAR_SEGOVR();
3037     END_OF_INSTR();
3038 }
3039
3040 /****************************************************************************
3041 REMARKS:
3042 Handles opcode 0xb8 - 0xbf
3043 ****************************************************************************/
3044 void x86emuOp_mov_word_register_IMM(u8 X86EMU_UNUSED(op1))
3045 {
3046     u32 srcval;
3047
3048     op1 &= 0x7;
3049
3050     START_OF_INSTR();
3051     DECODE_PRINTF("MOV\t");
3052     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3053         u32 *reg32;
3054         reg32 = DECODE_RM_LONG_REGISTER(op1);
3055         srcval = fetch_long_imm();
3056         DECODE_PRINTF2(",%x\n", srcval);
3057         TRACE_AND_STEP();
3058         *reg32 = srcval;
3059     } else {
3060         u16 *reg16;
3061         reg16 = DECODE_RM_WORD_REGISTER(op1);
3062         srcval = fetch_word_imm();
3063         DECODE_PRINTF2(",%x\n", srcval);
3064         TRACE_AND_STEP();
3065         *reg16 = (u16)srcval;
3066     }
3067     DECODE_CLEAR_SEGOVR();
3068     END_OF_INSTR();
3069 }
3070
3071 /****************************************************************************
3072 REMARKS:
3073 Handles opcode 0xc0
3074 ****************************************************************************/
3075 void x86emuOp_opcC0_byte_RM_MEM(u8 X86EMU_UNUSED(op1))
3076 {
3077     int mod, rl, rh;
3078     u8 *destreg;
3079     uint destoffset;
3080     u8 destval;
3081     u8 amt;
3082
3083     /*
3084      * Yet another weirdo special case instruction format.  Part of
3085      * the opcode held below in "RH".  Doubly nested case would
3086      * result, except that the decoded instruction
3087      */
3088     START_OF_INSTR();
3089     FETCH_DECODE_MODRM(mod, rh, rl);
3090 #ifdef DEBUG
3091     if (DEBUG_DECODE()) {
3092         /* XXX DECODE_PRINTF may be changed to something more
3093            general, so that it is important to leave the strings
3094            in the same format, even though the result is that the
3095            above test is done twice. */
3096
3097         switch (rh) {
3098         case 0:
3099             DECODE_PRINTF("ROL\t");
3100             break;
3101         case 1:
3102             DECODE_PRINTF("ROR\t");
3103             break;
3104         case 2:
3105             DECODE_PRINTF("RCL\t");
3106             break;
3107         case 3:
3108             DECODE_PRINTF("RCR\t");
3109             break;
3110         case 4:
3111             DECODE_PRINTF("SHL\t");
3112             break;
3113         case 5:
3114             DECODE_PRINTF("SHR\t");
3115             break;
3116         case 6:
3117             DECODE_PRINTF("SAL\t");
3118             break;
3119         case 7:
3120             DECODE_PRINTF("SAR\t");
3121             break;
3122         }
3123     }
3124 #endif
3125     /* know operation, decode the mod byte to find the addressing
3126        mode. */
3127     if (mod < 3) {
3128         DECODE_PRINTF("BYTE PTR ");
3129         destoffset = decode_rmXX_address(mod, rl);
3130         amt = fetch_byte_imm();
3131         DECODE_PRINTF2(",%x\n", amt);
3132         destval = fetch_data_byte(destoffset);
3133         TRACE_AND_STEP();
3134         destval = (*opcD0_byte_operation[rh]) (destval, amt);
3135         store_data_byte(destoffset, destval);
3136     } else {                     /* register to register */
3137         destreg = DECODE_RM_BYTE_REGISTER(rl);
3138         amt = fetch_byte_imm();
3139         DECODE_PRINTF2(",%x\n", amt);
3140         TRACE_AND_STEP();
3141         destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3142         *destreg = destval;
3143     }
3144     DECODE_CLEAR_SEGOVR();
3145     END_OF_INSTR();
3146 }
3147
3148 /****************************************************************************
3149 REMARKS:
3150 Handles opcode 0xc1
3151 ****************************************************************************/
3152 void x86emuOp_opcC1_word_RM_MEM(u8 X86EMU_UNUSED(op1))
3153 {
3154     int mod, rl, rh;
3155     uint destoffset;
3156     u8 amt;
3157
3158     /*
3159      * Yet another weirdo special case instruction format.  Part of
3160      * the opcode held below in "RH".  Doubly nested case would
3161      * result, except that the decoded instruction
3162      */
3163     START_OF_INSTR();
3164     FETCH_DECODE_MODRM(mod, rh, rl);
3165 #ifdef DEBUG
3166     if (DEBUG_DECODE()) {
3167         /* XXX DECODE_PRINTF may be changed to something more
3168            general, so that it is important to leave the strings
3169            in the same format, even though the result is that the
3170            above test is done twice. */
3171
3172         switch (rh) {
3173         case 0:
3174             DECODE_PRINTF("ROL\t");
3175             break;
3176         case 1:
3177             DECODE_PRINTF("ROR\t");
3178             break;
3179         case 2:
3180             DECODE_PRINTF("RCL\t");
3181             break;
3182         case 3:
3183             DECODE_PRINTF("RCR\t");
3184             break;
3185         case 4:
3186             DECODE_PRINTF("SHL\t");
3187             break;
3188         case 5:
3189             DECODE_PRINTF("SHR\t");
3190             break;
3191         case 6:
3192             DECODE_PRINTF("SAL\t");
3193             break;
3194         case 7:
3195             DECODE_PRINTF("SAR\t");
3196             break;
3197         }
3198     }
3199 #endif
3200     /* know operation, decode the mod byte to find the addressing
3201        mode. */
3202     if (mod < 3) {
3203         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3204             u32 destval;
3205
3206             DECODE_PRINTF("DWORD PTR ");
3207             destoffset = decode_rmXX_address(mod, rl);
3208             amt = fetch_byte_imm();
3209             DECODE_PRINTF2(",%x\n", amt);
3210             destval = fetch_data_long(destoffset);
3211             TRACE_AND_STEP();
3212             destval = (*opcD1_long_operation[rh]) (destval, amt);
3213             store_data_long(destoffset, destval);
3214         } else {
3215             u16 destval;
3216
3217             DECODE_PRINTF("WORD PTR ");
3218             destoffset = decode_rmXX_address(mod, rl);
3219             amt = fetch_byte_imm();
3220             DECODE_PRINTF2(",%x\n", amt);
3221             destval = fetch_data_word(destoffset);
3222             TRACE_AND_STEP();
3223             destval = (*opcD1_word_operation[rh]) (destval, amt);
3224             store_data_word(destoffset, destval);
3225         }
3226     } else {                     /* register to register */
3227         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3228             u32 *destreg;
3229
3230             destreg = DECODE_RM_LONG_REGISTER(rl);
3231             amt = fetch_byte_imm();
3232             DECODE_PRINTF2(",%x\n", amt);
3233             TRACE_AND_STEP();
3234             *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3235         } else {
3236             u16 *destreg;
3237
3238             destreg = DECODE_RM_WORD_REGISTER(rl);
3239             amt = fetch_byte_imm();
3240             DECODE_PRINTF2(",%x\n", amt);
3241             TRACE_AND_STEP();
3242             *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
3243         }
3244     }
3245     DECODE_CLEAR_SEGOVR();
3246     END_OF_INSTR();
3247 }
3248
3249 /****************************************************************************
3250 REMARKS:
3251 Handles opcode 0xc2
3252 ****************************************************************************/
3253 void x86emuOp_ret_near_IMM(u8 X86EMU_UNUSED(op1))
3254 {
3255     u16 imm;
3256
3257     START_OF_INSTR();
3258     DECODE_PRINTF("RET\t");
3259     imm = fetch_word_imm();
3260     DECODE_PRINTF2("%x\n", imm);
3261         RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
3262         TRACE_AND_STEP();
3263     M.x86.R_IP = pop_word();
3264     M.x86.R_SP += imm;
3265     DECODE_CLEAR_SEGOVR();
3266     END_OF_INSTR();
3267 }
3268
3269 /****************************************************************************
3270 REMARKS:
3271 Handles opcode 0xc3
3272 ****************************************************************************/
3273 void x86emuOp_ret_near(u8 X86EMU_UNUSED(op1))
3274 {
3275     START_OF_INSTR();
3276     DECODE_PRINTF("RET\n");
3277         RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
3278         TRACE_AND_STEP();
3279     M.x86.R_IP = pop_word();
3280     DECODE_CLEAR_SEGOVR();
3281     END_OF_INSTR();
3282 }
3283
3284 /****************************************************************************
3285 REMARKS:
3286 Handles opcode 0xc4
3287 ****************************************************************************/
3288 void x86emuOp_les_R_IMM(u8 X86EMU_UNUSED(op1))
3289 {
3290     int mod, rh, rl;
3291     u16 *dstreg;
3292     uint srcoffset;
3293
3294     START_OF_INSTR();
3295     DECODE_PRINTF("LES\t");
3296     FETCH_DECODE_MODRM(mod, rh, rl);
3297     if (mod < 3) {
3298         dstreg = DECODE_RM_WORD_REGISTER(rh);
3299         DECODE_PRINTF(",");
3300         srcoffset = decode_rmXX_address(mod, rl);
3301         DECODE_PRINTF("\n");
3302         TRACE_AND_STEP();
3303         *dstreg = fetch_data_word(srcoffset);
3304         M.x86.R_ES = fetch_data_word(srcoffset + 2);
3305     }
3306     /* else UNDEFINED!                   register to register */
3307
3308     DECODE_CLEAR_SEGOVR();
3309     END_OF_INSTR();
3310 }
3311
3312 /****************************************************************************
3313 REMARKS:
3314 Handles opcode 0xc5
3315 ****************************************************************************/
3316 void x86emuOp_lds_R_IMM(u8 X86EMU_UNUSED(op1))
3317 {
3318     int mod, rh, rl;
3319     u16 *dstreg;
3320     uint srcoffset;
3321
3322     START_OF_INSTR();
3323     DECODE_PRINTF("LDS\t");
3324     FETCH_DECODE_MODRM(mod, rh, rl);
3325     if (mod < 3) {
3326         dstreg = DECODE_RM_WORD_REGISTER(rh);
3327         DECODE_PRINTF(",");
3328         srcoffset = decode_rmXX_address(mod, rl);
3329         DECODE_PRINTF("\n");
3330         TRACE_AND_STEP();
3331         *dstreg = fetch_data_word(srcoffset);
3332         M.x86.R_DS = fetch_data_word(srcoffset + 2);
3333     }
3334     /* else UNDEFINED! */
3335     DECODE_CLEAR_SEGOVR();
3336     END_OF_INSTR();
3337 }
3338
3339 /****************************************************************************
3340 REMARKS:
3341 Handles opcode 0xc6
3342 ****************************************************************************/
3343 void x86emuOp_mov_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
3344 {
3345     int mod, rl, rh;
3346     u8 *destreg;
3347     uint destoffset;
3348     u8 imm;
3349
3350     START_OF_INSTR();
3351     DECODE_PRINTF("MOV\t");
3352     FETCH_DECODE_MODRM(mod, rh, rl);
3353     if (rh != 0) {
3354         DECODE_PRINTF("ILLEGAL DECODE OF OPCODE c6\n");
3355         HALT_SYS();
3356     }
3357     if (mod < 3) {
3358         DECODE_PRINTF("BYTE PTR ");
3359         destoffset = decode_rmXX_address(mod, rl);
3360         imm = fetch_byte_imm();
3361         DECODE_PRINTF2(",%2x\n", imm);
3362         TRACE_AND_STEP();
3363         store_data_byte(destoffset, imm);
3364     } else {                     /* register to register */
3365         destreg = DECODE_RM_BYTE_REGISTER(rl);
3366         imm = fetch_byte_imm();
3367         DECODE_PRINTF2(",%2x\n", imm);
3368         TRACE_AND_STEP();
3369         *destreg = imm;
3370     }
3371     DECODE_CLEAR_SEGOVR();
3372     END_OF_INSTR();
3373 }
3374
3375 /****************************************************************************
3376 REMARKS:
3377 Handles opcode 0xc7
3378 ****************************************************************************/
3379 void x86emuOp_mov_word_RM_IMM(u8 X86EMU_UNUSED(op1))
3380 {
3381     int mod, rl, rh;
3382     uint destoffset;
3383
3384     START_OF_INSTR();
3385     DECODE_PRINTF("MOV\t");
3386     FETCH_DECODE_MODRM(mod, rh, rl);
3387     if (rh != 0) {
3388         DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
3389         HALT_SYS();
3390     }
3391     if (mod < 3) {
3392         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3393             u32 imm;
3394
3395             DECODE_PRINTF("DWORD PTR ");
3396             destoffset = decode_rmXX_address(mod, rl);
3397             imm = fetch_long_imm();
3398             DECODE_PRINTF2(",%x\n", imm);
3399             TRACE_AND_STEP();
3400             store_data_long(destoffset, imm);
3401         } else {
3402             u16 imm;
3403
3404             DECODE_PRINTF("WORD PTR ");
3405             destoffset = decode_rmXX_address(mod, rl);
3406             imm = fetch_word_imm();
3407             DECODE_PRINTF2(",%x\n", imm);
3408             TRACE_AND_STEP();
3409             store_data_word(destoffset, imm);
3410         }
3411     } else {                     /* register to register */
3412         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3413                         u32 *destreg;
3414                         u32 imm;
3415
3416             destreg = DECODE_RM_LONG_REGISTER(rl);
3417             imm = fetch_long_imm();
3418             DECODE_PRINTF2(",%x\n", imm);
3419             TRACE_AND_STEP();
3420             *destreg = imm;
3421         } else {
3422                         u16 *destreg;
3423                         u16 imm;
3424
3425             destreg = DECODE_RM_WORD_REGISTER(rl);
3426             imm = fetch_word_imm();
3427             DECODE_PRINTF2(",%x\n", imm);
3428             TRACE_AND_STEP();
3429             *destreg = imm;
3430         }
3431     }
3432     DECODE_CLEAR_SEGOVR();
3433     END_OF_INSTR();
3434 }
3435
3436 /****************************************************************************
3437 REMARKS:
3438 Handles opcode 0xc8
3439 ****************************************************************************/
3440 void x86emuOp_enter(u8 X86EMU_UNUSED(op1))
3441 {
3442     u16 local,frame_pointer;
3443     u8  nesting;
3444     int i;
3445
3446     START_OF_INSTR();
3447     local = fetch_word_imm();
3448     nesting = fetch_byte_imm();
3449     DECODE_PRINTF2("ENTER %x\n", local);
3450     DECODE_PRINTF2(",%x\n", nesting);
3451     TRACE_AND_STEP();
3452     push_word(M.x86.R_BP);
3453     frame_pointer = M.x86.R_SP;
3454     if (nesting > 0) {
3455         for (i = 1; i < nesting; i++) {
3456             M.x86.R_BP -= 2;
3457             push_word(fetch_data_word_abs(M.x86.R_SS, M.x86.R_BP));
3458             }
3459         push_word(frame_pointer);
3460         }
3461     M.x86.R_BP = frame_pointer;
3462     M.x86.R_SP = (u16)(M.x86.R_SP - local);
3463     DECODE_CLEAR_SEGOVR();
3464     END_OF_INSTR();
3465 }
3466
3467 /****************************************************************************
3468 REMARKS:
3469 Handles opcode 0xc9
3470 ****************************************************************************/
3471 void x86emuOp_leave(u8 X86EMU_UNUSED(op1))
3472 {
3473     START_OF_INSTR();
3474     DECODE_PRINTF("LEAVE\n");
3475     TRACE_AND_STEP();
3476     M.x86.R_SP = M.x86.R_BP;
3477     M.x86.R_BP = pop_word();
3478     DECODE_CLEAR_SEGOVR();
3479     END_OF_INSTR();
3480 }
3481
3482 /****************************************************************************
3483 REMARKS:
3484 Handles opcode 0xca
3485 ****************************************************************************/
3486 void x86emuOp_ret_far_IMM(u8 X86EMU_UNUSED(op1))
3487 {
3488     u16 imm;
3489
3490     START_OF_INSTR();
3491     DECODE_PRINTF("RETF\t");
3492     imm = fetch_word_imm();
3493     DECODE_PRINTF2("%x\n", imm);
3494         RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
3495         TRACE_AND_STEP();
3496     M.x86.R_IP = pop_word();
3497     M.x86.R_CS = pop_word();
3498     M.x86.R_SP += imm;
3499     DECODE_CLEAR_SEGOVR();
3500     END_OF_INSTR();
3501 }
3502
3503 /****************************************************************************
3504 REMARKS:
3505 Handles opcode 0xcb
3506 ****************************************************************************/
3507 void x86emuOp_ret_far(u8 X86EMU_UNUSED(op1))
3508 {
3509     START_OF_INSTR();
3510     DECODE_PRINTF("RETF\n");
3511         RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
3512         TRACE_AND_STEP();
3513     M.x86.R_IP = pop_word();
3514     M.x86.R_CS = pop_word();
3515     DECODE_CLEAR_SEGOVR();
3516     END_OF_INSTR();
3517 }
3518
3519 /****************************************************************************
3520 REMARKS:
3521 Handles opcode 0xcc
3522 ****************************************************************************/
3523 void x86emuOp_int3(u8 X86EMU_UNUSED(op1))
3524 {
3525     u16 tmp;
3526
3527     START_OF_INSTR();
3528     DECODE_PRINTF("INT 3\n");
3529     tmp = (u16) mem_access_word(3 * 4 + 2);
3530     /* access the segment register */
3531     TRACE_AND_STEP();
3532         if (_X86EMU_intrTab[3]) {
3533                 (*_X86EMU_intrTab[3])(3);
3534     } else {
3535         push_word((u16)M.x86.R_FLG);
3536         CLEAR_FLAG(F_IF);
3537         CLEAR_FLAG(F_TF);
3538         push_word(M.x86.R_CS);
3539         M.x86.R_CS = mem_access_word(3 * 4 + 2);
3540         push_word(M.x86.R_IP);
3541         M.x86.R_IP = mem_access_word(3 * 4);
3542     }
3543     DECODE_CLEAR_SEGOVR();
3544     END_OF_INSTR();
3545 }
3546
3547 /****************************************************************************
3548 REMARKS:
3549 Handles opcode 0xcd
3550 ****************************************************************************/
3551 void x86emuOp_int_IMM(u8 X86EMU_UNUSED(op1))
3552 {
3553     u16 tmp;
3554     u8 intnum;
3555
3556     START_OF_INSTR();
3557     DECODE_PRINTF("INT\t");
3558     intnum = fetch_byte_imm();
3559     DECODE_PRINTF2("%x\n", intnum);
3560     tmp = mem_access_word(intnum * 4 + 2);
3561     TRACE_AND_STEP();
3562         if (_X86EMU_intrTab[intnum]) {
3563                 (*_X86EMU_intrTab[intnum])(intnum);
3564     } else {
3565         push_word((u16)M.x86.R_FLG);
3566         CLEAR_FLAG(F_IF);
3567         CLEAR_FLAG(F_TF);
3568         push_word(M.x86.R_CS);
3569         M.x86.R_CS = mem_access_word(intnum * 4 + 2);
3570         push_word(M.x86.R_IP);
3571         M.x86.R_IP = mem_access_word(intnum * 4);
3572     }
3573     DECODE_CLEAR_SEGOVR();
3574     END_OF_INSTR();
3575 }
3576
3577 /****************************************************************************
3578 REMARKS:
3579 Handles opcode 0xce
3580 ****************************************************************************/
3581 void x86emuOp_into(u8 X86EMU_UNUSED(op1))
3582 {
3583     u16 tmp;
3584
3585     START_OF_INSTR();
3586     DECODE_PRINTF("INTO\n");
3587     TRACE_AND_STEP();
3588     if (ACCESS_FLAG(F_OF)) {
3589         tmp = mem_access_word(4 * 4 + 2);
3590                 if (_X86EMU_intrTab[4]) {
3591                         (*_X86EMU_intrTab[4])(4);
3592         } else {
3593             push_word((u16)M.x86.R_FLG);
3594             CLEAR_FLAG(F_IF);
3595             CLEAR_FLAG(F_TF);
3596             push_word(M.x86.R_CS);
3597             M.x86.R_CS = mem_access_word(4 * 4 + 2);
3598             push_word(M.x86.R_IP);
3599             M.x86.R_IP = mem_access_word(4 * 4);
3600         }
3601     }
3602     DECODE_CLEAR_SEGOVR();
3603     END_OF_INSTR();
3604 }
3605
3606 /****************************************************************************
3607 REMARKS:
3608 Handles opcode 0xcf
3609 ****************************************************************************/
3610 void x86emuOp_iret(u8 X86EMU_UNUSED(op1))
3611 {
3612     START_OF_INSTR();
3613     DECODE_PRINTF("IRET\n");
3614
3615     TRACE_AND_STEP();
3616
3617     M.x86.R_IP = pop_word();
3618     M.x86.R_CS = pop_word();
3619     M.x86.R_FLG = pop_word();
3620     DECODE_CLEAR_SEGOVR();
3621     END_OF_INSTR();
3622 }
3623
3624 /****************************************************************************
3625 REMARKS:
3626 Handles opcode 0xd0
3627 ****************************************************************************/
3628 void x86emuOp_opcD0_byte_RM_1(u8 X86EMU_UNUSED(op1))
3629 {
3630     int mod, rl, rh;
3631     u8 *destreg;
3632     uint destoffset;
3633     u8 destval;
3634
3635     /*
3636      * Yet another weirdo special case instruction format.  Part of
3637      * the opcode held below in "RH".  Doubly nested case would
3638      * result, except that the decoded instruction
3639      */
3640     START_OF_INSTR();
3641     FETCH_DECODE_MODRM(mod, rh, rl);
3642 #ifdef DEBUG
3643     if (DEBUG_DECODE()) {
3644         /* XXX DECODE_PRINTF may be changed to something more
3645            general, so that it is important to leave the strings
3646            in the same format, even though the result is that the
3647            above test is done twice. */
3648         switch (rh) {
3649         case 0:
3650             DECODE_PRINTF("ROL\t");
3651             break;
3652         case 1:
3653             DECODE_PRINTF("ROR\t");
3654             break;
3655         case 2:
3656             DECODE_PRINTF("RCL\t");
3657             break;
3658         case 3:
3659             DECODE_PRINTF("RCR\t");
3660             break;
3661         case 4:
3662             DECODE_PRINTF("SHL\t");
3663             break;
3664         case 5:
3665             DECODE_PRINTF("SHR\t");
3666             break;
3667         case 6:
3668             DECODE_PRINTF("SAL\t");
3669             break;
3670         case 7:
3671             DECODE_PRINTF("SAR\t");
3672             break;
3673         }
3674     }
3675 #endif
3676     /* know operation, decode the mod byte to find the addressing
3677        mode. */
3678     if (mod < 3) {
3679         DECODE_PRINTF("BYTE PTR ");
3680         destoffset = decode_rmXX_address(mod, rl);
3681         DECODE_PRINTF(",1\n");
3682         destval = fetch_data_byte(destoffset);
3683         TRACE_AND_STEP();
3684         destval = (*opcD0_byte_operation[rh]) (destval, 1);
3685         store_data_byte(destoffset, destval);
3686     } else {                     /* register to register */
3687         destreg = DECODE_RM_BYTE_REGISTER(rl);
3688         DECODE_PRINTF(",1\n");
3689         TRACE_AND_STEP();
3690         destval = (*opcD0_byte_operation[rh]) (*destreg, 1);
3691         *destreg = destval;
3692     }
3693     DECODE_CLEAR_SEGOVR();
3694     END_OF_INSTR();
3695 }
3696
3697 /****************************************************************************
3698 REMARKS:
3699 Handles opcode 0xd1
3700 ****************************************************************************/
3701 void x86emuOp_opcD1_word_RM_1(u8 X86EMU_UNUSED(op1))
3702 {
3703     int mod, rl, rh;
3704     uint destoffset;
3705
3706     /*
3707      * Yet another weirdo special case instruction format.  Part of
3708      * the opcode held below in "RH".  Doubly nested case would
3709      * result, except that the decoded instruction
3710      */
3711     START_OF_INSTR();
3712     FETCH_DECODE_MODRM(mod, rh, rl);
3713 #ifdef DEBUG
3714     if (DEBUG_DECODE()) {
3715         /* XXX DECODE_PRINTF may be changed to something more
3716            general, so that it is important to leave the strings
3717            in the same format, even though the result is that the
3718            above test is done twice. */
3719         switch (rh) {
3720         case 0:
3721             DECODE_PRINTF("ROL\t");
3722             break;
3723         case 1:
3724             DECODE_PRINTF("ROR\t");
3725             break;
3726         case 2:
3727             DECODE_PRINTF("RCL\t");
3728             break;
3729         case 3:
3730             DECODE_PRINTF("RCR\t");
3731             break;
3732         case 4:
3733             DECODE_PRINTF("SHL\t");
3734             break;
3735         case 5:
3736             DECODE_PRINTF("SHR\t");
3737             break;
3738         case 6:
3739             DECODE_PRINTF("SAL\t");
3740             break;
3741         case 7:
3742             DECODE_PRINTF("SAR\t");
3743             break;
3744         }
3745     }
3746 #endif
3747     /* know operation, decode the mod byte to find the addressing
3748        mode. */
3749     if (mod < 3) {
3750         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3751             u32 destval;
3752
3753             DECODE_PRINTF("DWORD PTR ");
3754             destoffset = decode_rmXX_address(mod, rl);
3755             DECODE_PRINTF(",1\n");
3756             destval = fetch_data_long(destoffset);
3757             TRACE_AND_STEP();
3758             destval = (*opcD1_long_operation[rh]) (destval, 1);
3759             store_data_long(destoffset, destval);
3760         } else {
3761             u16 destval;
3762
3763             DECODE_PRINTF("WORD PTR ");
3764             destoffset = decode_rmXX_address(mod, rl);
3765             DECODE_PRINTF(",1\n");
3766             destval = fetch_data_word(destoffset);
3767             TRACE_AND_STEP();
3768             destval = (*opcD1_word_operation[rh]) (destval, 1);
3769             store_data_word(destoffset, destval);
3770         }
3771     } else {                     /* register to register */
3772         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3773                         u32 destval;
3774                         u32 *destreg;
3775
3776             destreg = DECODE_RM_LONG_REGISTER(rl);
3777             DECODE_PRINTF(",1\n");
3778             TRACE_AND_STEP();
3779             destval = (*opcD1_long_operation[rh]) (*destreg, 1);
3780             *destreg = destval;
3781         } else {
3782                         u16 destval;
3783                         u16 *destreg;
3784
3785             destreg = DECODE_RM_WORD_REGISTER(rl);
3786             DECODE_PRINTF(",1\n");
3787             TRACE_AND_STEP();
3788             destval = (*opcD1_word_operation[rh]) (*destreg, 1);
3789             *destreg = destval;
3790         }
3791     }
3792     DECODE_CLEAR_SEGOVR();
3793     END_OF_INSTR();
3794 }
3795
3796 /****************************************************************************
3797 REMARKS:
3798 Handles opcode 0xd2
3799 ****************************************************************************/
3800 void x86emuOp_opcD2_byte_RM_CL(u8 X86EMU_UNUSED(op1))
3801 {
3802     int mod, rl, rh;
3803     u8 *destreg;
3804     uint destoffset;
3805     u8 destval;
3806     u8 amt;
3807
3808     /*
3809      * Yet another weirdo special case instruction format.  Part of
3810      * the opcode held below in "RH".  Doubly nested case would
3811      * result, except that the decoded instruction
3812      */
3813     START_OF_INSTR();
3814     FETCH_DECODE_MODRM(mod, rh, rl);
3815 #ifdef DEBUG
3816     if (DEBUG_DECODE()) {
3817         /* XXX DECODE_PRINTF may be changed to something more
3818            general, so that it is important to leave the strings
3819            in the same format, even though the result is that the
3820            above test is done twice. */
3821         switch (rh) {
3822         case 0:
3823             DECODE_PRINTF("ROL\t");
3824             break;
3825         case 1:
3826             DECODE_PRINTF("ROR\t");
3827             break;
3828         case 2:
3829             DECODE_PRINTF("RCL\t");
3830             break;
3831         case 3:
3832             DECODE_PRINTF("RCR\t");
3833             break;
3834         case 4:
3835             DECODE_PRINTF("SHL\t");
3836             break;
3837         case 5:
3838             DECODE_PRINTF("SHR\t");
3839             break;
3840         case 6:
3841             DECODE_PRINTF("SAL\t");
3842             break;
3843         case 7:
3844             DECODE_PRINTF("SAR\t");
3845             break;
3846         }
3847     }
3848 #endif
3849     /* know operation, decode the mod byte to find the addressing
3850        mode. */
3851     amt = M.x86.R_CL;
3852     if (mod < 3) {
3853         DECODE_PRINTF("BYTE PTR ");
3854         destoffset = decode_rmXX_address(mod, rl);
3855         DECODE_PRINTF(",CL\n");
3856         destval = fetch_data_byte(destoffset);
3857         TRACE_AND_STEP();
3858         destval = (*opcD0_byte_operation[rh]) (destval, amt);
3859         store_data_byte(destoffset, destval);
3860     } else {                     /* register to register */
3861         destreg = DECODE_RM_BYTE_REGISTER(rl);
3862         DECODE_PRINTF(",CL\n");
3863         TRACE_AND_STEP();
3864         destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3865         *destreg = destval;
3866     }
3867     DECODE_CLEAR_SEGOVR();
3868     END_OF_INSTR();
3869 }
3870
3871 /****************************************************************************
3872 REMARKS:
3873 Handles opcode 0xd3
3874 ****************************************************************************/
3875 void x86emuOp_opcD3_word_RM_CL(u8 X86EMU_UNUSED(op1))
3876 {
3877     int mod, rl, rh;
3878     uint destoffset;
3879     u8 amt;
3880
3881     /*
3882      * Yet another weirdo special case instruction format.  Part of
3883      * the opcode held below in "RH".  Doubly nested case would
3884      * result, except that the decoded instruction
3885      */
3886     START_OF_INSTR();
3887     FETCH_DECODE_MODRM(mod, rh, rl);
3888 #ifdef DEBUG
3889     if (DEBUG_DECODE()) {
3890         /* XXX DECODE_PRINTF may be changed to something more
3891            general, so that it is important to leave the strings
3892            in the same format, even though the result is that the
3893            above test is done twice. */
3894         switch (rh) {
3895         case 0:
3896             DECODE_PRINTF("ROL\t");
3897             break;
3898         case 1:
3899             DECODE_PRINTF("ROR\t");
3900             break;
3901         case 2:
3902             DECODE_PRINTF("RCL\t");
3903             break;
3904         case 3:
3905             DECODE_PRINTF("RCR\t");
3906             break;
3907         case 4:
3908             DECODE_PRINTF("SHL\t");
3909             break;
3910         case 5:
3911             DECODE_PRINTF("SHR\t");
3912             break;
3913         case 6:
3914             DECODE_PRINTF("SAL\t");
3915             break;
3916         case 7:
3917             DECODE_PRINTF("SAR\t");
3918             break;
3919         }
3920     }
3921 #endif
3922     /* know operation, decode the mod byte to find the addressing
3923        mode. */
3924     amt = M.x86.R_CL;
3925     if (mod < 3) {
3926         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3927             u32 destval;
3928
3929             DECODE_PRINTF("DWORD PTR ");
3930             destoffset = decode_rmXX_address(mod, rl);
3931             DECODE_PRINTF(",CL\n");
3932             destval = fetch_data_long(destoffset);
3933             TRACE_AND_STEP();
3934             destval = (*opcD1_long_operation[rh]) (destval, amt);
3935             store_data_long(destoffset, destval);
3936         } else {
3937             u16 destval;
3938
3939             DECODE_PRINTF("WORD PTR ");
3940             destoffset = decode_rmXX_address(mod, rl);
3941             DECODE_PRINTF(",CL\n");
3942             destval = fetch_data_word(destoffset);
3943             TRACE_AND_STEP();
3944             destval = (*opcD1_word_operation[rh]) (destval, amt);
3945             store_data_word(destoffset, destval);
3946         }
3947     } else {                     /* register to register */
3948         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3949             u32 *destreg;
3950
3951             destreg = DECODE_RM_LONG_REGISTER(rl);
3952             DECODE_PRINTF(",CL\n");
3953             TRACE_AND_STEP();
3954             *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3955         } else {
3956             u16 *destreg;
3957
3958             destreg = DECODE_RM_WORD_REGISTER(rl);
3959             DECODE_PRINTF(",CL\n");
3960             TRACE_AND_STEP();
3961             *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
3962         }
3963     }
3964     DECODE_CLEAR_SEGOVR();
3965     END_OF_INSTR();
3966 }
3967
3968 /****************************************************************************
3969 REMARKS:
3970 Handles opcode 0xd4
3971 ****************************************************************************/
3972 void x86emuOp_aam(u8 X86EMU_UNUSED(op1))
3973 {
3974     u8 a;
3975
3976     START_OF_INSTR();
3977     DECODE_PRINTF("AAM\n");
3978     a = fetch_byte_imm();      /* this is a stupid encoding. */
3979     if (a != 10) {
3980         DECODE_PRINTF("ERROR DECODING AAM\n");
3981         TRACE_REGS();
3982         HALT_SYS();
3983     }
3984     TRACE_AND_STEP();
3985     /* note the type change here --- returning AL and AH in AX. */
3986     M.x86.R_AX = aam_word(M.x86.R_AL);
3987     DECODE_CLEAR_SEGOVR();
3988     END_OF_INSTR();
3989 }
3990
3991 /****************************************************************************
3992 REMARKS:
3993 Handles opcode 0xd5
3994 ****************************************************************************/
3995 void x86emuOp_aad(u8 X86EMU_UNUSED(op1))
3996 {
3997     u8 a;
3998
3999     START_OF_INSTR();
4000     DECODE_PRINTF("AAD\n");
4001     a = fetch_byte_imm();
4002     TRACE_AND_STEP();
4003     M.x86.R_AX = aad_word(M.x86.R_AX);
4004     DECODE_CLEAR_SEGOVR();
4005     END_OF_INSTR();
4006 }
4007
4008 /* opcode 0xd6 ILLEGAL OPCODE */
4009
4010 /****************************************************************************
4011 REMARKS:
4012 Handles opcode 0xd7
4013 ****************************************************************************/
4014 void x86emuOp_xlat(u8 X86EMU_UNUSED(op1))
4015 {
4016     u16 addr;
4017
4018     START_OF_INSTR();
4019     DECODE_PRINTF("XLAT\n");
4020     TRACE_AND_STEP();
4021         addr = (u16)(M.x86.R_BX + (u8)M.x86.R_AL);
4022     M.x86.R_AL = fetch_data_byte(addr);
4023     DECODE_CLEAR_SEGOVR();
4024     END_OF_INSTR();
4025 }
4026
4027 /* instuctions  D8 .. DF are in i87_ops.c */
4028
4029 /****************************************************************************
4030 REMARKS:
4031 Handles opcode 0xe0
4032 ****************************************************************************/
4033 void x86emuOp_loopne(u8 X86EMU_UNUSED(op1))
4034 {
4035     s16 ip;
4036
4037     START_OF_INSTR();
4038     DECODE_PRINTF("LOOPNE\t");
4039     ip = (s8) fetch_byte_imm();
4040     ip += (s16) M.x86.R_IP;
4041     DECODE_PRINTF2("%04x\n", ip);
4042     TRACE_AND_STEP();
4043     M.x86.R_CX -= 1;
4044     if (M.x86.R_CX != 0 && !ACCESS_FLAG(F_ZF))      /* CX != 0 and !ZF */
4045         M.x86.R_IP = ip;
4046     DECODE_CLEAR_SEGOVR();
4047     END_OF_INSTR();
4048 }
4049
4050 /****************************************************************************
4051 REMARKS:
4052 Handles opcode 0xe1
4053 ****************************************************************************/
4054 void x86emuOp_loope(u8 X86EMU_UNUSED(op1))
4055 {
4056     s16 ip;
4057
4058     START_OF_INSTR();
4059     DECODE_PRINTF("LOOPE\t");
4060     ip = (s8) fetch_byte_imm();
4061     ip += (s16) M.x86.R_IP;
4062     DECODE_PRINTF2("%04x\n", ip);
4063     TRACE_AND_STEP();
4064     M.x86.R_CX -= 1;
4065     if (M.x86.R_CX != 0 && ACCESS_FLAG(F_ZF))       /* CX != 0 and ZF */
4066         M.x86.R_IP = ip;
4067     DECODE_CLEAR_SEGOVR();
4068     END_OF_INSTR();
4069 }
4070
4071 /****************************************************************************
4072 REMARKS:
4073 Handles opcode 0xe2
4074 ****************************************************************************/
4075 void x86emuOp_loop(u8 X86EMU_UNUSED(op1))
4076 {
4077     s16 ip;
4078
4079     START_OF_INSTR();
4080     DECODE_PRINTF("LOOP\t");
4081     ip = (s8) fetch_byte_imm();
4082     ip += (s16) M.x86.R_IP;
4083     DECODE_PRINTF2("%04x\n", ip);
4084     TRACE_AND_STEP();
4085     M.x86.R_CX -= 1;
4086     if (M.x86.R_CX != 0)
4087         M.x86.R_IP = ip;
4088     DECODE_CLEAR_SEGOVR();
4089     END_OF_INSTR();
4090 }
4091
4092 /****************************************************************************
4093 REMARKS:
4094 Handles opcode 0xe3
4095 ****************************************************************************/
4096 void x86emuOp_jcxz(u8 X86EMU_UNUSED(op1))
4097 {
4098     u16 target;
4099     s8  offset;
4100
4101     /* jump to byte offset if overflow flag is set */
4102     START_OF_INSTR();
4103     DECODE_PRINTF("JCXZ\t");
4104     offset = (s8)fetch_byte_imm();
4105     target = (u16)(M.x86.R_IP + offset);
4106     DECODE_PRINTF2("%x\n", target);
4107     TRACE_AND_STEP();
4108     if (M.x86.R_CX == 0)
4109         M.x86.R_IP = target;
4110     DECODE_CLEAR_SEGOVR();
4111     END_OF_INSTR();
4112 }
4113
4114 /****************************************************************************
4115 REMARKS:
4116 Handles opcode 0xe4
4117 ****************************************************************************/
4118 void x86emuOp_in_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
4119 {
4120     u8 port;
4121
4122     START_OF_INSTR();
4123     DECODE_PRINTF("IN\t");
4124         port = (u8) fetch_byte_imm();
4125     DECODE_PRINTF2("%x,AL\n", port);
4126     TRACE_AND_STEP();
4127     M.x86.R_AL = (*sys_inb)(port);
4128     DECODE_CLEAR_SEGOVR();
4129     END_OF_INSTR();
4130 }
4131
4132 /****************************************************************************
4133 REMARKS:
4134 Handles opcode 0xe5
4135 ****************************************************************************/
4136 void x86emuOp_in_word_AX_IMM(u8 X86EMU_UNUSED(op1))
4137 {
4138     u8 port;
4139
4140     START_OF_INSTR();
4141     DECODE_PRINTF("IN\t");
4142         port = (u8) fetch_byte_imm();
4143     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4144         DECODE_PRINTF2("EAX,%x\n", port);
4145     } else {
4146         DECODE_PRINTF2("AX,%x\n", port);
4147     }
4148     TRACE_AND_STEP();
4149     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4150         M.x86.R_EAX = (*sys_inl)(port);
4151     } else {
4152         M.x86.R_AX = (*sys_inw)(port);
4153     }
4154     DECODE_CLEAR_SEGOVR();
4155     END_OF_INSTR();
4156 }
4157
4158 /****************************************************************************
4159 REMARKS:
4160 Handles opcode 0xe6
4161 ****************************************************************************/
4162 void x86emuOp_out_byte_IMM_AL(u8 X86EMU_UNUSED(op1))
4163 {
4164     u8 port;
4165
4166     START_OF_INSTR();
4167     DECODE_PRINTF("OUT\t");
4168         port = (u8) fetch_byte_imm();
4169     DECODE_PRINTF2("%x,AL\n", port);
4170     TRACE_AND_STEP();
4171     (*sys_outb)(port, M.x86.R_AL);
4172     DECODE_CLEAR_SEGOVR();
4173     END_OF_INSTR();
4174 }
4175
4176 /****************************************************************************
4177 REMARKS:
4178 Handles opcode 0xe7
4179 ****************************************************************************/
4180 void x86emuOp_out_word_IMM_AX(u8 X86EMU_UNUSED(op1))
4181 {
4182     u8 port;
4183
4184     START_OF_INSTR();
4185     DECODE_PRINTF("OUT\t");
4186         port = (u8) fetch_byte_imm();
4187     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4188         DECODE_PRINTF2("%x,EAX\n", port);
4189     } else {
4190         DECODE_PRINTF2("%x,AX\n", port);
4191     }
4192     TRACE_AND_STEP();
4193     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4194         (*sys_outl)(port, M.x86.R_EAX);
4195     } else {
4196         (*sys_outw)(port, M.x86.R_AX);
4197     }
4198     DECODE_CLEAR_SEGOVR();
4199     END_OF_INSTR();
4200 }
4201
4202 /****************************************************************************
4203 REMARKS:
4204 Handles opcode 0xe8
4205 ****************************************************************************/
4206 void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1))
4207 {
4208     s16 ip;
4209
4210     START_OF_INSTR();
4211         DECODE_PRINTF("CALL\t");
4212         ip = (s16) fetch_word_imm();
4213         ip += (s16) M.x86.R_IP;    /* CHECK SIGN */
4214         DECODE_PRINTF2("%04x\n", ip);
4215         CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, "");
4216     TRACE_AND_STEP();
4217     push_word(M.x86.R_IP);
4218     M.x86.R_IP = ip;
4219     DECODE_CLEAR_SEGOVR();
4220     END_OF_INSTR();
4221 }
4222
4223 /****************************************************************************
4224 REMARKS:
4225 Handles opcode 0xe9
4226 ****************************************************************************/
4227 void x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1))
4228 {
4229     int ip;
4230
4231     START_OF_INSTR();
4232     DECODE_PRINTF("JMP\t");
4233     ip = (s16)fetch_word_imm();
4234     ip += (s16)M.x86.R_IP;
4235     DECODE_PRINTF2("%04x\n", ip);
4236     TRACE_AND_STEP();
4237     M.x86.R_IP = (u16)ip;
4238     DECODE_CLEAR_SEGOVR();
4239     END_OF_INSTR();
4240 }
4241
4242 /****************************************************************************
4243 REMARKS:
4244 Handles opcode 0xea
4245 ****************************************************************************/
4246 void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1))
4247 {
4248     u16 cs, ip;
4249
4250     START_OF_INSTR();
4251     DECODE_PRINTF("JMP\tFAR ");
4252     ip = fetch_word_imm();
4253     cs = fetch_word_imm();
4254     DECODE_PRINTF2("%04x:", cs);
4255     DECODE_PRINTF2("%04x\n", ip);
4256     TRACE_AND_STEP();
4257     M.x86.R_IP = ip;
4258     M.x86.R_CS = cs;
4259     DECODE_CLEAR_SEGOVR();
4260     END_OF_INSTR();
4261 }
4262
4263 /****************************************************************************
4264 REMARKS:
4265 Handles opcode 0xeb
4266 ****************************************************************************/
4267 void x86emuOp_jump_byte_IMM(u8 X86EMU_UNUSED(op1))
4268 {
4269     u16 target;
4270     s8 offset;
4271
4272     START_OF_INSTR();
4273     DECODE_PRINTF("JMP\t");
4274     offset = (s8)fetch_byte_imm();
4275     target = (u16)(M.x86.R_IP + offset);
4276     DECODE_PRINTF2("%x\n", target);
4277     TRACE_AND_STEP();
4278     M.x86.R_IP = target;
4279     DECODE_CLEAR_SEGOVR();
4280     END_OF_INSTR();
4281 }
4282
4283 /****************************************************************************
4284 REMARKS:
4285 Handles opcode 0xec
4286 ****************************************************************************/
4287 void x86emuOp_in_byte_AL_DX(u8 X86EMU_UNUSED(op1))
4288 {
4289     START_OF_INSTR();
4290     DECODE_PRINTF("IN\tAL,DX\n");
4291     TRACE_AND_STEP();
4292     M.x86.R_AL = (*sys_inb)(M.x86.R_DX);
4293     DECODE_CLEAR_SEGOVR();
4294     END_OF_INSTR();
4295 }
4296
4297 /****************************************************************************
4298 REMARKS:
4299 Handles opcode 0xed
4300 ****************************************************************************/
4301 void x86emuOp_in_word_AX_DX(u8 X86EMU_UNUSED(op1))
4302 {
4303     START_OF_INSTR();
4304     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4305         DECODE_PRINTF("IN\tEAX,DX\n");
4306     } else {
4307         DECODE_PRINTF("IN\tAX,DX\n");
4308     }
4309     TRACE_AND_STEP();
4310     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4311         M.x86.R_EAX = (*sys_inl)(M.x86.R_DX);
4312     } else {
4313         M.x86.R_AX = (*sys_inw)(M.x86.R_DX);
4314     }
4315     DECODE_CLEAR_SEGOVR();
4316     END_OF_INSTR();
4317 }
4318
4319 /****************************************************************************
4320 REMARKS:
4321 Handles opcode 0xee
4322 ****************************************************************************/
4323 void x86emuOp_out_byte_DX_AL(u8 X86EMU_UNUSED(op1))
4324 {
4325     START_OF_INSTR();
4326     DECODE_PRINTF("OUT\tDX,AL\n");
4327     TRACE_AND_STEP();
4328     (*sys_outb)(M.x86.R_DX, M.x86.R_AL);
4329     DECODE_CLEAR_SEGOVR();
4330     END_OF_INSTR();
4331 }
4332
4333 /****************************************************************************
4334 REMARKS:
4335 Handles opcode 0xef
4336 ****************************************************************************/
4337 void x86emuOp_out_word_DX_AX(u8 X86EMU_UNUSED(op1))
4338 {
4339     START_OF_INSTR();
4340     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4341         DECODE_PRINTF("OUT\tDX,EAX\n");
4342     } else {
4343         DECODE_PRINTF("OUT\tDX,AX\n");
4344     }
4345     TRACE_AND_STEP();
4346     if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4347         (*sys_outl)(M.x86.R_DX, M.x86.R_EAX);
4348     } else {
4349         (*sys_outw)(M.x86.R_DX, M.x86.R_AX);
4350     }
4351     DECODE_CLEAR_SEGOVR();
4352     END_OF_INSTR();
4353 }
4354
4355 /****************************************************************************
4356 REMARKS:
4357 Handles opcode 0xf0
4358 ****************************************************************************/
4359 void x86emuOp_lock(u8 X86EMU_UNUSED(op1))
4360 {
4361     START_OF_INSTR();
4362     DECODE_PRINTF("LOCK:\n");
4363     TRACE_AND_STEP();
4364     DECODE_CLEAR_SEGOVR();
4365     END_OF_INSTR();
4366 }
4367
4368 /*opcode 0xf1 ILLEGAL OPERATION */
4369
4370 /****************************************************************************
4371 REMARKS:
4372 Handles opcode 0xf2
4373 ****************************************************************************/
4374 void x86emuOp_repne(u8 X86EMU_UNUSED(op1))
4375 {
4376     START_OF_INSTR();
4377     DECODE_PRINTF("REPNE\n");
4378     TRACE_AND_STEP();
4379     M.x86.mode |= SYSMODE_PREFIX_REPNE;
4380     DECODE_CLEAR_SEGOVR();
4381     END_OF_INSTR();
4382 }
4383
4384 /****************************************************************************
4385 REMARKS:
4386 Handles opcode 0xf3
4387 ****************************************************************************/
4388 void x86emuOp_repe(u8 X86EMU_UNUSED(op1))
4389 {
4390     START_OF_INSTR();
4391     DECODE_PRINTF("REPE\n");
4392     TRACE_AND_STEP();
4393     M.x86.mode |= SYSMODE_PREFIX_REPE;
4394     DECODE_CLEAR_SEGOVR();
4395     END_OF_INSTR();
4396 }
4397
4398 /****************************************************************************
4399 REMARKS:
4400 Handles opcode 0xf4
4401 ****************************************************************************/
4402 void x86emuOp_halt(u8 X86EMU_UNUSED(op1))
4403 {
4404     START_OF_INSTR();
4405     DECODE_PRINTF("HALT\n");
4406     TRACE_AND_STEP();
4407     HALT_SYS();
4408     DECODE_CLEAR_SEGOVR();
4409     END_OF_INSTR();
4410 }
4411
4412 /****************************************************************************
4413 REMARKS:
4414 Handles opcode 0xf5
4415 ****************************************************************************/
4416 void x86emuOp_cmc(u8 X86EMU_UNUSED(op1))
4417 {
4418     /* complement the carry flag. */
4419     START_OF_INSTR();
4420     DECODE_PRINTF("CMC\n");
4421     TRACE_AND_STEP();
4422     TOGGLE_FLAG(F_CF);
4423     DECODE_CLEAR_SEGOVR();
4424     END_OF_INSTR();
4425 }
4426
4427 /****************************************************************************
4428 REMARKS:
4429 Handles opcode 0xf6
4430 ****************************************************************************/
4431 void x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1))
4432 {
4433     int mod, rl, rh;
4434     u8 *destreg;
4435     uint destoffset;
4436     u8 destval, srcval;
4437
4438     /* long, drawn out code follows.  Double switch for a total
4439        of 32 cases.  */
4440     START_OF_INSTR();
4441     FETCH_DECODE_MODRM(mod, rh, rl);
4442     DECODE_PRINTF(opF6_names[rh]);
4443     if (mod < 3) {
4444         DECODE_PRINTF("BYTE PTR ");
4445         destoffset = decode_rmXX_address(mod, rl);
4446         destval = fetch_data_byte(destoffset);
4447
4448         switch (rh) {
4449         case 0:         /* test byte imm */
4450             DECODE_PRINTF(",");
4451             srcval = fetch_byte_imm();
4452             DECODE_PRINTF2("%02x\n", srcval);
4453             TRACE_AND_STEP();
4454             test_byte(destval, srcval);
4455             break;
4456         case 1:
4457             DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4458             HALT_SYS();
4459             break;
4460         case 2:
4461             DECODE_PRINTF("\n");
4462             TRACE_AND_STEP();
4463             destval = not_byte(destval);
4464             store_data_byte(destoffset, destval);
4465             break;
4466         case 3:
4467             DECODE_PRINTF("\n");
4468             TRACE_AND_STEP();
4469             destval = neg_byte(destval);
4470             store_data_byte(destoffset, destval);
4471             break;
4472         case 4:
4473             DECODE_PRINTF("\n");
4474             TRACE_AND_STEP();
4475             mul_byte(destval);
4476             break;
4477         case 5:
4478             DECODE_PRINTF("\n");
4479             TRACE_AND_STEP();
4480             imul_byte(destval);
4481             break;
4482         case 6:
4483             DECODE_PRINTF("\n");
4484             TRACE_AND_STEP();
4485             div_byte(destval);
4486             break;
4487         default:
4488             DECODE_PRINTF("\n");
4489             TRACE_AND_STEP();
4490             idiv_byte(destval);
4491             break;
4492         }
4493     } else {                     /* mod=11 */
4494         destreg = DECODE_RM_BYTE_REGISTER(rl);
4495         switch (rh) {
4496         case 0:         /* test byte imm */
4497             DECODE_PRINTF(",");
4498             srcval = fetch_byte_imm();
4499             DECODE_PRINTF2("%02x\n", srcval);
4500             TRACE_AND_STEP();
4501             test_byte(*destreg, srcval);
4502             break;
4503         case 1:
4504             DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4505             HALT_SYS();
4506             break;
4507         case 2:
4508             DECODE_PRINTF("\n");
4509             TRACE_AND_STEP();
4510             *destreg = not_byte(*destreg);
4511             break;
4512         case 3:
4513             DECODE_PRINTF("\n");
4514             TRACE_AND_STEP();
4515             *destreg = neg_byte(*destreg);
4516             break;
4517         case 4:
4518             DECODE_PRINTF("\n");
4519             TRACE_AND_STEP();
4520             mul_byte(*destreg);      /*!!!  */
4521             break;
4522         case 5:
4523             DECODE_PRINTF("\n");
4524             TRACE_AND_STEP();
4525             imul_byte(*destreg);
4526             break;
4527         case 6:
4528             DECODE_PRINTF("\n");
4529             TRACE_AND_STEP();
4530             div_byte(*destreg);
4531             break;
4532         default:
4533             DECODE_PRINTF("\n");
4534             TRACE_AND_STEP();
4535             idiv_byte(*destreg);
4536             break;
4537         }
4538     }
4539     DECODE_CLEAR_SEGOVR();
4540     END_OF_INSTR();
4541 }
4542
4543 /****************************************************************************
4544 REMARKS:
4545 Handles opcode 0xf7
4546 ****************************************************************************/
4547 void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1))
4548 {
4549     int mod, rl, rh;
4550     uint destoffset;
4551
4552     START_OF_INSTR();
4553     FETCH_DECODE_MODRM(mod, rh, rl);
4554     DECODE_PRINTF(opF6_names[rh]);
4555     if (mod < 3) {
4556
4557         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4558             u32 destval, srcval;
4559
4560             DECODE_PRINTF("DWORD PTR ");
4561             destoffset = decode_rmXX_address(mod, rl);
4562             destval = fetch_data_long(destoffset);
4563
4564             switch (rh) {
4565             case 0:
4566                 DECODE_PRINTF(",");
4567                 srcval = fetch_long_imm();
4568                 DECODE_PRINTF2("%x\n", srcval);
4569                 TRACE_AND_STEP();
4570                 test_long(destval, srcval);
4571                 break;
4572             case 1:
4573                 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4574                 HALT_SYS();
4575                 break;
4576             case 2:
4577                 DECODE_PRINTF("\n");
4578                 TRACE_AND_STEP();
4579                 destval = not_long(destval);
4580                 store_data_long(destoffset, destval);
4581                 break;
4582             case 3:
4583                 DECODE_PRINTF("\n");
4584                 TRACE_AND_STEP();
4585                 destval = neg_long(destval);
4586                 store_data_long(destoffset, destval);
4587                 break;
4588             case 4:
4589                 DECODE_PRINTF("\n");
4590                 TRACE_AND_STEP();
4591                 mul_long(destval);
4592                 break;
4593             case 5:
4594                 DECODE_PRINTF("\n");
4595                 TRACE_AND_STEP();
4596                 imul_long(destval);
4597                 break;
4598             case 6:
4599                 DECODE_PRINTF("\n");
4600                 TRACE_AND_STEP();
4601                 div_long(destval);
4602                 break;
4603             case 7:
4604                 DECODE_PRINTF("\n");
4605                 TRACE_AND_STEP();
4606                 idiv_long(destval);
4607                 break;
4608             }
4609         } else {
4610             u16 destval, srcval;
4611
4612             DECODE_PRINTF("WORD PTR ");
4613             destoffset = decode_rmXX_address(mod, rl);
4614             destval = fetch_data_word(destoffset);
4615
4616             switch (rh) {
4617             case 0:         /* test word imm */
4618                 DECODE_PRINTF(",");
4619                 srcval = fetch_word_imm();
4620                 DECODE_PRINTF2("%x\n", srcval);
4621                 TRACE_AND_STEP();
4622                 test_word(destval, srcval);
4623                 break;
4624             case 1:
4625                 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4626                 HALT_SYS();
4627                 break;
4628             case 2:
4629                 DECODE_PRINTF("\n");
4630                 TRACE_AND_STEP();
4631                 destval = not_word(destval);
4632                 store_data_word(destoffset, destval);
4633                 break;
4634             case 3:
4635                 DECODE_PRINTF("\n");
4636                 TRACE_AND_STEP();
4637                 destval = neg_word(destval);
4638                 store_data_word(destoffset, destval);
4639                 break;
4640             case 4:
4641                 DECODE_PRINTF("\n");
4642                 TRACE_AND_STEP();
4643                 mul_word(destval);
4644                 break;
4645             case 5:
4646                 DECODE_PRINTF("\n");
4647                 TRACE_AND_STEP();
4648                 imul_word(destval);
4649                 break;
4650             case 6:
4651                 DECODE_PRINTF("\n");
4652                 TRACE_AND_STEP();
4653                 div_word(destval);
4654                 break;
4655             case 7:
4656                 DECODE_PRINTF("\n");
4657                 TRACE_AND_STEP();
4658                 idiv_word(destval);
4659                 break;
4660             }
4661         }
4662
4663     } else {                     /* mod=11 */
4664
4665         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4666             u32 *destreg;
4667             u32 srcval;
4668
4669             destreg = DECODE_RM_LONG_REGISTER(rl);
4670
4671             switch (rh) {
4672             case 0:         /* test word imm */
4673                 DECODE_PRINTF(",");
4674                 srcval = fetch_long_imm();
4675                 DECODE_PRINTF2("%x\n", srcval);
4676                 TRACE_AND_STEP();
4677                 test_long(*destreg, srcval);
4678                 break;
4679             case 1:
4680                 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4681                 HALT_SYS();
4682                 break;
4683             case 2:
4684                 DECODE_PRINTF("\n");
4685                 TRACE_AND_STEP();
4686                 *destreg = not_long(*destreg);
4687                 break;
4688             case 3:
4689                 DECODE_PRINTF("\n");
4690                 TRACE_AND_STEP();
4691                 *destreg = neg_long(*destreg);
4692                 break;
4693             case 4:
4694                 DECODE_PRINTF("\n");
4695                 TRACE_AND_STEP();
4696                 mul_long(*destreg);      /*!!!  */
4697                 break;
4698             case 5:
4699                 DECODE_PRINTF("\n");
4700                 TRACE_AND_STEP();
4701                 imul_long(*destreg);
4702                 break;
4703             case 6:
4704                 DECODE_PRINTF("\n");
4705                 TRACE_AND_STEP();
4706                 div_long(*destreg);
4707                 break;
4708             case 7:
4709                 DECODE_PRINTF("\n");
4710                 TRACE_AND_STEP();
4711                 idiv_long(*destreg);
4712                 break;
4713             }
4714         } else {
4715             u16 *destreg;
4716             u16 srcval;
4717
4718             destreg = DECODE_RM_WORD_REGISTER(rl);
4719
4720             switch (rh) {
4721             case 0:         /* test word imm */
4722                 DECODE_PRINTF(",");
4723                 srcval = fetch_word_imm();
4724                 DECODE_PRINTF2("%x\n", srcval);
4725                 TRACE_AND_STEP();
4726                 test_word(*destreg, srcval);
4727                 break;
4728             case 1:
4729                 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4730                 HALT_SYS();
4731                 break;
4732             case 2:
4733                 DECODE_PRINTF("\n");
4734                 TRACE_AND_STEP();
4735                 *destreg = not_word(*destreg);
4736                 break;
4737             case 3:
4738                 DECODE_PRINTF("\n");
4739                 TRACE_AND_STEP();
4740                 *destreg = neg_word(*destreg);
4741                 break;
4742             case 4:
4743                 DECODE_PRINTF("\n");
4744                 TRACE_AND_STEP();
4745                 mul_word(*destreg);      /*!!!  */
4746                 break;
4747             case 5:
4748                 DECODE_PRINTF("\n");
4749                 TRACE_AND_STEP();
4750                 imul_word(*destreg);
4751                 break;
4752             case 6:
4753                 DECODE_PRINTF("\n");
4754                 TRACE_AND_STEP();
4755                 div_word(*destreg);
4756                 break;
4757             case 7:
4758                 DECODE_PRINTF("\n");
4759                 TRACE_AND_STEP();
4760                 idiv_word(*destreg);
4761                 break;
4762             }
4763         }
4764     }
4765     DECODE_CLEAR_SEGOVR();
4766     END_OF_INSTR();
4767 }
4768
4769 /****************************************************************************
4770 REMARKS:
4771 Handles opcode 0xf8
4772 ****************************************************************************/
4773 void x86emuOp_clc(u8 X86EMU_UNUSED(op1))
4774 {
4775     /* clear the carry flag. */
4776     START_OF_INSTR();
4777     DECODE_PRINTF("CLC\n");
4778     TRACE_AND_STEP();
4779     CLEAR_FLAG(F_CF);
4780     DECODE_CLEAR_SEGOVR();
4781     END_OF_INSTR();
4782 }
4783
4784 /****************************************************************************
4785 REMARKS:
4786 Handles opcode 0xf9
4787 ****************************************************************************/
4788 void x86emuOp_stc(u8 X86EMU_UNUSED(op1))
4789 {
4790     /* set the carry flag. */
4791     START_OF_INSTR();
4792     DECODE_PRINTF("STC\n");
4793     TRACE_AND_STEP();
4794     SET_FLAG(F_CF);
4795     DECODE_CLEAR_SEGOVR();
4796     END_OF_INSTR();
4797 }
4798
4799 /****************************************************************************
4800 REMARKS:
4801 Handles opcode 0xfa
4802 ****************************************************************************/
4803 void x86emuOp_cli(u8 X86EMU_UNUSED(op1))
4804 {
4805     /* clear interrupts. */
4806     START_OF_INSTR();
4807     DECODE_PRINTF("CLI\n");
4808     TRACE_AND_STEP();
4809     CLEAR_FLAG(F_IF);
4810     DECODE_CLEAR_SEGOVR();
4811     END_OF_INSTR();
4812 }
4813
4814 /****************************************************************************
4815 REMARKS:
4816 Handles opcode 0xfb
4817 ****************************************************************************/
4818 void x86emuOp_sti(u8 X86EMU_UNUSED(op1))
4819 {
4820     /* enable  interrupts. */
4821     START_OF_INSTR();
4822     DECODE_PRINTF("STI\n");
4823     TRACE_AND_STEP();
4824     SET_FLAG(F_IF);
4825     DECODE_CLEAR_SEGOVR();
4826     END_OF_INSTR();
4827 }
4828
4829 /****************************************************************************
4830 REMARKS:
4831 Handles opcode 0xfc
4832 ****************************************************************************/
4833 void x86emuOp_cld(u8 X86EMU_UNUSED(op1))
4834 {
4835     /* clear interrupts. */
4836     START_OF_INSTR();
4837     DECODE_PRINTF("CLD\n");
4838     TRACE_AND_STEP();
4839     CLEAR_FLAG(F_DF);
4840     DECODE_CLEAR_SEGOVR();
4841     END_OF_INSTR();
4842 }
4843
4844 /****************************************************************************
4845 REMARKS:
4846 Handles opcode 0xfd
4847 ****************************************************************************/
4848 void x86emuOp_std(u8 X86EMU_UNUSED(op1))
4849 {
4850     /* clear interrupts. */
4851     START_OF_INSTR();
4852     DECODE_PRINTF("STD\n");
4853     TRACE_AND_STEP();
4854     SET_FLAG(F_DF);
4855     DECODE_CLEAR_SEGOVR();
4856     END_OF_INSTR();
4857 }
4858
4859 /****************************************************************************
4860 REMARKS:
4861 Handles opcode 0xfe
4862 ****************************************************************************/
4863 void x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1))
4864 {
4865     int mod, rh, rl;
4866     u8 destval;
4867     uint destoffset;
4868     u8 *destreg;
4869
4870     /* Yet another special case instruction. */
4871     START_OF_INSTR();
4872     FETCH_DECODE_MODRM(mod, rh, rl);
4873 #ifdef DEBUG
4874     if (DEBUG_DECODE()) {
4875         /* XXX DECODE_PRINTF may be changed to something more
4876            general, so that it is important to leave the strings
4877            in the same format, even though the result is that the
4878            above test is done twice. */
4879
4880         switch (rh) {
4881         case 0:
4882             DECODE_PRINTF("INC\t");
4883             break;
4884         case 1:
4885             DECODE_PRINTF("DEC\t");
4886             break;
4887         case 2:
4888         case 3:
4889         case 4:
4890         case 5:
4891         case 6:
4892         case 7:
4893             DECODE_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x \n", mod);
4894             HALT_SYS();
4895             break;
4896         }
4897     }
4898 #endif
4899     if (mod < 3) {
4900         DECODE_PRINTF("BYTE PTR ");
4901         destoffset = decode_rmXX_address(mod, rl);
4902         DECODE_PRINTF("\n");
4903         destval = fetch_data_byte(destoffset);
4904         TRACE_AND_STEP();
4905         if (rh == 0)
4906           destval = inc_byte(destval);
4907         else
4908           destval = dec_byte(destval);
4909         store_data_byte(destoffset, destval);
4910     } else {
4911         destreg = DECODE_RM_BYTE_REGISTER(rl);
4912         DECODE_PRINTF("\n");
4913         TRACE_AND_STEP();
4914         if (rh == 0)
4915           *destreg = inc_byte(*destreg);
4916         else
4917           *destreg = dec_byte(*destreg);
4918     }
4919     DECODE_CLEAR_SEGOVR();
4920     END_OF_INSTR();
4921 }
4922
4923 /****************************************************************************
4924 REMARKS:
4925 Handles opcode 0xff
4926 ****************************************************************************/
4927 void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1))
4928 {
4929     int mod, rh, rl;
4930     uint destoffset = 0;
4931         u16 *destreg;
4932         u16 destval,destval2;
4933
4934     /* Yet another special case instruction. */
4935     START_OF_INSTR();
4936     FETCH_DECODE_MODRM(mod, rh, rl);
4937 #ifdef DEBUG
4938     if (DEBUG_DECODE()) {
4939         /* XXX DECODE_PRINTF may be changed to something more
4940            general, so that it is important to leave the strings
4941            in the same format, even though the result is that the
4942            above test is done twice. */
4943
4944         switch (rh) {
4945         case 0:
4946             if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4947                 DECODE_PRINTF("INC\tDWORD PTR ");
4948             } else {
4949                 DECODE_PRINTF("INC\tWORD PTR ");
4950             }
4951             break;
4952         case 1:
4953             if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4954                 DECODE_PRINTF("DEC\tDWORD PTR ");
4955             } else {
4956                 DECODE_PRINTF("DEC\tWORD PTR ");
4957             }
4958             break;
4959         case 2:
4960             DECODE_PRINTF("CALL\t ");
4961             break;
4962         case 3:
4963             DECODE_PRINTF("CALL\tFAR ");
4964             break;
4965         case 4:
4966             DECODE_PRINTF("JMP\t");
4967             break;
4968         case 5:
4969             DECODE_PRINTF("JMP\tFAR ");
4970             break;
4971         case 6:
4972             DECODE_PRINTF("PUSH\t");
4973             break;
4974         case 7:
4975             DECODE_PRINTF("ILLEGAL DECODING OF OPCODE FF\t");
4976             HALT_SYS();
4977             break;
4978         }
4979     }
4980 #endif
4981     if (mod < 3) {
4982         destoffset = decode_rmXX_address(mod, rl);
4983         DECODE_PRINTF("\n");
4984         switch (rh) {
4985         case 0:         /* inc word ptr ... */
4986             if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4987                 u32 destval;
4988
4989                 destval = fetch_data_long(destoffset);
4990                 TRACE_AND_STEP();
4991                 destval = inc_long(destval);
4992                 store_data_long(destoffset, destval);
4993             } else {
4994                 u16 destval;
4995
4996                 destval = fetch_data_word(destoffset);
4997                 TRACE_AND_STEP();
4998                 destval = inc_word(destval);
4999                 store_data_word(destoffset, destval);
5000             }
5001             break;
5002         case 1:         /* dec word ptr ... */
5003             if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5004                 u32 destval;
5005
5006                 destval = fetch_data_long(destoffset);
5007                 TRACE_AND_STEP();
5008                 destval = dec_long(destval);
5009                 store_data_long(destoffset, destval);
5010             } else {
5011                 u16 destval;
5012
5013                 destval = fetch_data_word(destoffset);
5014                 TRACE_AND_STEP();
5015                 destval = dec_word(destval);
5016                 store_data_word(destoffset, destval);
5017             }
5018             break;
5019         case 2:         /* call word ptr ... */
5020             destval = fetch_data_word(destoffset);
5021             TRACE_AND_STEP();
5022             push_word(M.x86.R_IP);
5023             M.x86.R_IP = destval;
5024             break;
5025         case 3:         /* call far ptr ... */
5026             destval = fetch_data_word(destoffset);
5027             destval2 = fetch_data_word(destoffset + 2);
5028             TRACE_AND_STEP();
5029             push_word(M.x86.R_CS);
5030             M.x86.R_CS = destval2;
5031             push_word(M.x86.R_IP);
5032             M.x86.R_IP = destval;
5033             break;
5034         case 4:         /* jmp word ptr ... */
5035             destval = fetch_data_word(destoffset);
5036             TRACE_AND_STEP();
5037             M.x86.R_IP = destval;
5038             break;
5039         case 5:         /* jmp far ptr ... */
5040             destval = fetch_data_word(destoffset);
5041             destval2 = fetch_data_word(destoffset + 2);
5042             TRACE_AND_STEP();
5043             M.x86.R_IP = destval;
5044             M.x86.R_CS = destval2;
5045             break;
5046         case 6:         /*  push word ptr ... */
5047             if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5048                 u32 destval;
5049
5050                 destval = fetch_data_long(destoffset);
5051                 TRACE_AND_STEP();
5052                 push_long(destval);
5053             } else {
5054                 u16 destval;
5055
5056                 destval = fetch_data_word(destoffset);
5057                 TRACE_AND_STEP();
5058                 push_word(destval);
5059             }
5060             break;
5061         }
5062     } else {
5063         switch (rh) {
5064         case 0:
5065             if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5066                 u32 *destreg;
5067
5068                 destreg = DECODE_RM_LONG_REGISTER(rl);
5069                 DECODE_PRINTF("\n");
5070                 TRACE_AND_STEP();
5071                 *destreg = inc_long(*destreg);
5072             } else {
5073                 u16 *destreg;
5074
5075                 destreg = DECODE_RM_WORD_REGISTER(rl);
5076                 DECODE_PRINTF("\n");
5077                 TRACE_AND_STEP();
5078                 *destreg = inc_word(*destreg);
5079             }
5080             break;
5081         case 1:
5082             if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5083                 u32 *destreg;
5084
5085                 destreg = DECODE_RM_LONG_REGISTER(rl);
5086                 DECODE_PRINTF("\n");
5087                 TRACE_AND_STEP();
5088                 *destreg = dec_long(*destreg);
5089             } else {
5090                 u16 *destreg;
5091
5092                 destreg = DECODE_RM_WORD_REGISTER(rl);
5093                 DECODE_PRINTF("\n");
5094                 TRACE_AND_STEP();
5095                 *destreg = dec_word(*destreg);
5096             }
5097             break;
5098         case 2:         /* call word ptr ... */
5099             destreg = DECODE_RM_WORD_REGISTER(rl);
5100             DECODE_PRINTF("\n");
5101             TRACE_AND_STEP();
5102             push_word(M.x86.R_IP);
5103             M.x86.R_IP = *destreg;
5104             break;
5105         case 3:         /* jmp far ptr ... */
5106             DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5107             TRACE_AND_STEP();
5108             HALT_SYS();
5109             break;
5110
5111         case 4:         /* jmp  ... */
5112             destreg = DECODE_RM_WORD_REGISTER(rl);
5113             DECODE_PRINTF("\n");
5114             TRACE_AND_STEP();
5115             M.x86.R_IP = (u16) (*destreg);
5116             break;
5117         case 5:         /* jmp far ptr ... */
5118             DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5119             TRACE_AND_STEP();
5120             HALT_SYS();
5121             break;
5122         case 6:
5123             if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5124                 u32 *destreg;
5125
5126                 destreg = DECODE_RM_LONG_REGISTER(rl);
5127                 DECODE_PRINTF("\n");
5128                 TRACE_AND_STEP();
5129                 push_long(*destreg);
5130             } else {
5131                 u16 *destreg;
5132
5133                 destreg = DECODE_RM_WORD_REGISTER(rl);
5134                 DECODE_PRINTF("\n");
5135                 TRACE_AND_STEP();
5136                 push_word(*destreg);
5137             }
5138             break;
5139         }
5140     }
5141     DECODE_CLEAR_SEGOVR();
5142     END_OF_INSTR();
5143 }
5144
5145 /***************************************************************************
5146  * Single byte operation code table:
5147  **************************************************************************/
5148 void (*x86emu_optab[256])(u8) __attribute__ ((section(".got2"))) =
5149 {
5150 /*  0x00 */ x86emuOp_genop_byte_RM_R,
5151 /*  0x01 */ x86emuOp_genop_word_RM_R,
5152 /*  0x02 */ x86emuOp_genop_byte_R_RM,
5153 /*  0x03 */ x86emuOp_genop_word_R_RM,
5154 /*  0x04 */ x86emuOp_genop_byte_AL_IMM,
5155 /*  0x05 */ x86emuOp_genop_word_AX_IMM,
5156 /*  0x06 */ x86emuOp_push_ES,
5157 /*  0x07 */ x86emuOp_pop_ES,
5158
5159 /*  0x08 */ x86emuOp_genop_byte_RM_R,
5160 /*  0x09 */ x86emuOp_genop_word_RM_R,
5161 /*  0x0a */ x86emuOp_genop_byte_R_RM,
5162 /*  0x0b */ x86emuOp_genop_word_R_RM,
5163 /*  0x0c */ x86emuOp_genop_byte_AL_IMM,
5164 /*  0x0d */ x86emuOp_genop_word_AX_IMM,
5165 /*  0x0e */ x86emuOp_push_CS,
5166 /*  0x0f */ x86emuOp_two_byte,
5167
5168 /*  0x10 */ x86emuOp_genop_byte_RM_R,
5169 /*  0x11 */ x86emuOp_genop_word_RM_R,
5170 /*  0x12 */ x86emuOp_genop_byte_R_RM,
5171 /*  0x13 */ x86emuOp_genop_word_R_RM,
5172 /*  0x14 */ x86emuOp_genop_byte_AL_IMM,
5173 /*  0x15 */ x86emuOp_genop_word_AX_IMM,
5174 /*  0x16 */ x86emuOp_push_SS,
5175 /*  0x17 */ x86emuOp_pop_SS,
5176
5177 /*  0x18 */ x86emuOp_genop_byte_RM_R,
5178 /*  0x19 */ x86emuOp_genop_word_RM_R,
5179 /*  0x1a */ x86emuOp_genop_byte_R_RM,
5180 /*  0x1b */ x86emuOp_genop_word_R_RM,
5181 /*  0x1c */ x86emuOp_genop_byte_AL_IMM,
5182 /*  0x1d */ x86emuOp_genop_word_AX_IMM,
5183 /*  0x1e */ x86emuOp_push_DS,
5184 /*  0x1f */ x86emuOp_pop_DS,
5185
5186 /*  0x20 */ x86emuOp_genop_byte_RM_R,
5187 /*  0x21 */ x86emuOp_genop_word_RM_R,
5188 /*  0x22 */ x86emuOp_genop_byte_R_RM,
5189 /*  0x23 */ x86emuOp_genop_word_R_RM,
5190 /*  0x24 */ x86emuOp_genop_byte_AL_IMM,
5191 /*  0x25 */ x86emuOp_genop_word_AX_IMM,
5192 /*  0x26 */ x86emuOp_segovr_ES,
5193 /*  0x27 */ x86emuOp_daa,
5194
5195 /*  0x28 */ x86emuOp_genop_byte_RM_R,
5196 /*  0x29 */ x86emuOp_genop_word_RM_R,
5197 /*  0x2a */ x86emuOp_genop_byte_R_RM,
5198 /*  0x2b */ x86emuOp_genop_word_R_RM,
5199 /*  0x2c */ x86emuOp_genop_byte_AL_IMM,
5200 /*  0x2d */ x86emuOp_genop_word_AX_IMM,
5201 /*  0x2e */ x86emuOp_segovr_CS,
5202 /*  0x2f */ x86emuOp_das,
5203
5204 /*  0x30 */ x86emuOp_genop_byte_RM_R,
5205 /*  0x31 */ x86emuOp_genop_word_RM_R,
5206 /*  0x32 */ x86emuOp_genop_byte_R_RM,
5207 /*  0x33 */ x86emuOp_genop_word_R_RM,
5208 /*  0x34 */ x86emuOp_genop_byte_AL_IMM,
5209 /*  0x35 */ x86emuOp_genop_word_AX_IMM,
5210 /*  0x36 */ x86emuOp_segovr_SS,
5211 /*  0x37 */ x86emuOp_aaa,
5212
5213 /*  0x38 */ x86emuOp_genop_byte_RM_R,
5214 /*  0x39 */ x86emuOp_genop_word_RM_R,
5215 /*  0x3a */ x86emuOp_genop_byte_R_RM,
5216 /*  0x3b */ x86emuOp_genop_word_R_RM,
5217 /*  0x3c */ x86emuOp_genop_byte_AL_IMM,
5218 /*  0x3d */ x86emuOp_genop_word_AX_IMM,
5219 /*  0x3e */ x86emuOp_segovr_DS,
5220 /*  0x3f */ x86emuOp_aas,
5221
5222 /*  0x40 */ x86emuOp_inc_register,
5223 /*  0x41 */ x86emuOp_inc_register,
5224 /*  0x42 */ x86emuOp_inc_register,
5225 /*  0x43 */ x86emuOp_inc_register,
5226 /*  0x44 */ x86emuOp_inc_register,
5227 /*  0x45 */ x86emuOp_inc_register,
5228 /*  0x46 */ x86emuOp_inc_register,
5229 /*  0x47 */ x86emuOp_inc_register,
5230
5231 /*  0x48 */ x86emuOp_dec_register,
5232 /*  0x49 */ x86emuOp_dec_register,
5233 /*  0x4a */ x86emuOp_dec_register,
5234 /*  0x4b */ x86emuOp_dec_register,
5235 /*  0x4c */ x86emuOp_dec_register,
5236 /*  0x4d */ x86emuOp_dec_register,
5237 /*  0x4e */ x86emuOp_dec_register,
5238 /*  0x4f */ x86emuOp_dec_register,
5239
5240 /*  0x50 */ x86emuOp_push_register,
5241 /*  0x51 */ x86emuOp_push_register,
5242 /*  0x52 */ x86emuOp_push_register,
5243 /*  0x53 */ x86emuOp_push_register,
5244 /*  0x54 */ x86emuOp_push_register,
5245 /*  0x55 */ x86emuOp_push_register,
5246 /*  0x56 */ x86emuOp_push_register,
5247 /*  0x57 */ x86emuOp_push_register,
5248
5249 /*  0x58 */ x86emuOp_pop_register,
5250 /*  0x59 */ x86emuOp_pop_register,
5251 /*  0x5a */ x86emuOp_pop_register,
5252 /*  0x5b */ x86emuOp_pop_register,
5253 /*  0x5c */ x86emuOp_pop_register,
5254 /*  0x5d */ x86emuOp_pop_register,
5255 /*  0x5e */ x86emuOp_pop_register,
5256 /*  0x5f */ x86emuOp_pop_register,
5257
5258 /*  0x60 */ x86emuOp_push_all,
5259 /*  0x61 */ x86emuOp_pop_all,
5260 /*  0x62 */ x86emuOp_illegal_op,   /* bound */
5261 /*  0x63 */ x86emuOp_illegal_op,   /* arpl */
5262 /*  0x64 */ x86emuOp_segovr_FS,
5263 /*  0x65 */ x86emuOp_segovr_GS,
5264 /*  0x66 */ x86emuOp_prefix_data,
5265 /*  0x67 */ x86emuOp_prefix_addr,
5266
5267 /*  0x68 */ x86emuOp_push_word_IMM,
5268 /*  0x69 */ x86emuOp_imul_word_IMM,
5269 /*  0x6a */ x86emuOp_push_byte_IMM,
5270 /*  0x6b */ x86emuOp_imul_byte_IMM,
5271 /*  0x6c */ x86emuOp_ins_byte,
5272 /*  0x6d */ x86emuOp_ins_word,
5273 /*  0x6e */ x86emuOp_outs_byte,
5274 /*  0x6f */ x86emuOp_outs_word,
5275
5276 /*  0x70 */ x86emuOp_jump_near_cond,
5277 /*  0x71 */ x86emuOp_jump_near_cond,
5278 /*  0x72 */ x86emuOp_jump_near_cond,
5279 /*  0x73 */ x86emuOp_jump_near_cond,
5280 /*  0x74 */ x86emuOp_jump_near_cond,
5281 /*  0x75 */ x86emuOp_jump_near_cond,
5282 /*  0x76 */ x86emuOp_jump_near_cond,
5283 /*  0x77 */ x86emuOp_jump_near_cond,
5284
5285 /*  0x78 */ x86emuOp_jump_near_cond,
5286 /*  0x79 */ x86emuOp_jump_near_cond,
5287 /*  0x7a */ x86emuOp_jump_near_cond,
5288 /*  0x7b */ x86emuOp_jump_near_cond,
5289 /*  0x7c */ x86emuOp_jump_near_cond,
5290 /*  0x7d */ x86emuOp_jump_near_cond,
5291 /*  0x7e */ x86emuOp_jump_near_cond,
5292 /*  0x7f */ x86emuOp_jump_near_cond,
5293
5294 /*  0x80 */ x86emuOp_opc80_byte_RM_IMM,
5295 /*  0x81 */ x86emuOp_opc81_word_RM_IMM,
5296 /*  0x82 */ x86emuOp_opc82_byte_RM_IMM,
5297 /*  0x83 */ x86emuOp_opc83_word_RM_IMM,
5298 /*  0x84 */ x86emuOp_test_byte_RM_R,
5299 /*  0x85 */ x86emuOp_test_word_RM_R,
5300 /*  0x86 */ x86emuOp_xchg_byte_RM_R,
5301 /*  0x87 */ x86emuOp_xchg_word_RM_R,
5302
5303 /*  0x88 */ x86emuOp_mov_byte_RM_R,
5304 /*  0x89 */ x86emuOp_mov_word_RM_R,
5305 /*  0x8a */ x86emuOp_mov_byte_R_RM,
5306 /*  0x8b */ x86emuOp_mov_word_R_RM,
5307 /*  0x8c */ x86emuOp_mov_word_RM_SR,
5308 /*  0x8d */ x86emuOp_lea_word_R_M,
5309 /*  0x8e */ x86emuOp_mov_word_SR_RM,
5310 /*  0x8f */ x86emuOp_pop_RM,
5311
5312 /*  0x90 */ x86emuOp_nop,
5313 /*  0x91 */ x86emuOp_xchg_word_AX_register,
5314 /*  0x92 */ x86emuOp_xchg_word_AX_register,
5315 /*  0x93 */ x86emuOp_xchg_word_AX_register,
5316 /*  0x94 */ x86emuOp_xchg_word_AX_register,
5317 /*  0x95 */ x86emuOp_xchg_word_AX_register,
5318 /*  0x96 */ x86emuOp_xchg_word_AX_register,
5319 /*  0x97 */ x86emuOp_xchg_word_AX_register,
5320
5321 /*  0x98 */ x86emuOp_cbw,
5322 /*  0x99 */ x86emuOp_cwd,
5323 /*  0x9a */ x86emuOp_call_far_IMM,
5324 /*  0x9b */ x86emuOp_wait,
5325 /*  0x9c */ x86emuOp_pushf_word,
5326 /*  0x9d */ x86emuOp_popf_word,
5327 /*  0x9e */ x86emuOp_sahf,
5328 /*  0x9f */ x86emuOp_lahf,
5329
5330 /*  0xa0 */ x86emuOp_mov_AL_M_IMM,
5331 /*  0xa1 */ x86emuOp_mov_AX_M_IMM,
5332 /*  0xa2 */ x86emuOp_mov_M_AL_IMM,
5333 /*  0xa3 */ x86emuOp_mov_M_AX_IMM,
5334 /*  0xa4 */ x86emuOp_movs_byte,
5335 /*  0xa5 */ x86emuOp_movs_word,
5336 /*  0xa6 */ x86emuOp_cmps_byte,
5337 /*  0xa7 */ x86emuOp_cmps_word,
5338 /*  0xa8 */ x86emuOp_test_AL_IMM,
5339 /*  0xa9 */ x86emuOp_test_AX_IMM,
5340 /*  0xaa */ x86emuOp_stos_byte,
5341 /*  0xab */ x86emuOp_stos_word,
5342 /*  0xac */ x86emuOp_lods_byte,
5343 /*  0xad */ x86emuOp_lods_word,
5344 /*  0xac */ x86emuOp_scas_byte,
5345 /*  0xad */ x86emuOp_scas_word,
5346
5347 /*  0xb0 */ x86emuOp_mov_byte_register_IMM,
5348 /*  0xb1 */ x86emuOp_mov_byte_register_IMM,
5349 /*  0xb2 */ x86emuOp_mov_byte_register_IMM,
5350 /*  0xb3 */ x86emuOp_mov_byte_register_IMM,
5351 /*  0xb4 */ x86emuOp_mov_byte_register_IMM,
5352 /*  0xb5 */ x86emuOp_mov_byte_register_IMM,
5353 /*  0xb6 */ x86emuOp_mov_byte_register_IMM,
5354 /*  0xb7 */ x86emuOp_mov_byte_register_IMM,
5355
5356 /*  0xb8 */ x86emuOp_mov_word_register_IMM,
5357 /*  0xb9 */ x86emuOp_mov_word_register_IMM,
5358 /*  0xba */ x86emuOp_mov_word_register_IMM,
5359 /*  0xbb */ x86emuOp_mov_word_register_IMM,
5360 /*  0xbc */ x86emuOp_mov_word_register_IMM,
5361 /*  0xbd */ x86emuOp_mov_word_register_IMM,
5362 /*  0xbe */ x86emuOp_mov_word_register_IMM,
5363 /*  0xbf */ x86emuOp_mov_word_register_IMM,
5364
5365 /*  0xc0 */ x86emuOp_opcC0_byte_RM_MEM,
5366 /*  0xc1 */ x86emuOp_opcC1_word_RM_MEM,
5367 /*  0xc2 */ x86emuOp_ret_near_IMM,
5368 /*  0xc3 */ x86emuOp_ret_near,
5369 /*  0xc4 */ x86emuOp_les_R_IMM,
5370 /*  0xc5 */ x86emuOp_lds_R_IMM,
5371 /*  0xc6 */ x86emuOp_mov_byte_RM_IMM,
5372 /*  0xc7 */ x86emuOp_mov_word_RM_IMM,
5373 /*  0xc8 */ x86emuOp_enter,
5374 /*  0xc9 */ x86emuOp_leave,
5375 /*  0xca */ x86emuOp_ret_far_IMM,
5376 /*  0xcb */ x86emuOp_ret_far,
5377 /*  0xcc */ x86emuOp_int3,
5378 /*  0xcd */ x86emuOp_int_IMM,
5379 /*  0xce */ x86emuOp_into,
5380 /*  0xcf */ x86emuOp_iret,
5381
5382 /*  0xd0 */ x86emuOp_opcD0_byte_RM_1,
5383 /*  0xd1 */ x86emuOp_opcD1_word_RM_1,
5384 /*  0xd2 */ x86emuOp_opcD2_byte_RM_CL,
5385 /*  0xd3 */ x86emuOp_opcD3_word_RM_CL,
5386 /*  0xd4 */ x86emuOp_aam,
5387 /*  0xd5 */ x86emuOp_aad,
5388 /*  0xd6 */ x86emuOp_illegal_op,   /* Undocumented SETALC instruction */
5389 /*  0xd7 */ x86emuOp_xlat,
5390 /*  0xd8 */ NULL, /*x86emuOp_esc_coprocess_d8,*/
5391 /*  0xd9 */ NULL, /*x86emuOp_esc_coprocess_d9,*/
5392 /*  0xda */ NULL, /*x86emuOp_esc_coprocess_da,*/
5393 /*  0xdb */ NULL, /*x86emuOp_esc_coprocess_db,*/
5394 /*  0xdc */ NULL, /*x86emuOp_esc_coprocess_dc,*/
5395 /*  0xdd */ NULL, /*x86emuOp_esc_coprocess_dd,*/
5396 /*  0xde */ NULL, /*x86emuOp_esc_coprocess_de,*/
5397 /*  0xdf */ NULL, /*x86emuOp_esc_coprocess_df,*/
5398
5399 /*  0xe0 */ x86emuOp_loopne,
5400 /*  0xe1 */ x86emuOp_loope,
5401 /*  0xe2 */ x86emuOp_loop,
5402 /*  0xe3 */ x86emuOp_jcxz,
5403 /*  0xe4 */ x86emuOp_in_byte_AL_IMM,
5404 /*  0xe5 */ x86emuOp_in_word_AX_IMM,
5405 /*  0xe6 */ x86emuOp_out_byte_IMM_AL,
5406 /*  0xe7 */ x86emuOp_out_word_IMM_AX,
5407
5408 /*  0xe8 */ x86emuOp_call_near_IMM,
5409 /*  0xe9 */ x86emuOp_jump_near_IMM,
5410 /*  0xea */ x86emuOp_jump_far_IMM,
5411 /*  0xeb */ x86emuOp_jump_byte_IMM,
5412 /*  0xec */ x86emuOp_in_byte_AL_DX,
5413 /*  0xed */ x86emuOp_in_word_AX_DX,
5414 /*  0xee */ x86emuOp_out_byte_DX_AL,
5415 /*  0xef */ x86emuOp_out_word_DX_AX,
5416
5417 /*  0xf0 */ x86emuOp_lock,
5418 /*  0xf1 */ x86emuOp_illegal_op,
5419 /*  0xf2 */ x86emuOp_repne,
5420 /*  0xf3 */ x86emuOp_repe,
5421 /*  0xf4 */ x86emuOp_halt,
5422 /*  0xf5 */ x86emuOp_cmc,
5423 /*  0xf6 */ x86emuOp_opcF6_byte_RM,
5424 /*  0xf7 */ x86emuOp_opcF7_word_RM,
5425
5426 /*  0xf8 */ x86emuOp_clc,
5427 /*  0xf9 */ x86emuOp_stc,
5428 /*  0xfa */ x86emuOp_cli,
5429 /*  0xfb */ x86emuOp_sti,
5430 /*  0xfc */ x86emuOp_cld,
5431 /*  0xfd */ x86emuOp_std,
5432 /*  0xfe */ x86emuOp_opcFE_byte_RM,
5433 /*  0xff */ x86emuOp_opcFF_word_RM,
5434 };
5435
5436 #endif