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