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