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