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