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