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