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