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