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