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