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