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