soc/intel/alderlake: Add ADL-P 4+4 with 28W TDP
[coreboot.git] / src / device / oprom / x86emu / ops.c
blobeeaa2035448754520e364104c9bf0d935c919b6a
1 /****************************************************************************
3 * Realmode X86 Emulator Library
5 * Copyright (C) 1991-2004 SciTech Software, Inc.
6 * Copyright (C) David Mosberger-Tang
7 * Copyright (C) 1999 Egbert Eich
9 * ========================================================================
11 * Permission to use, copy, modify, distribute, and sell this software and
12 * its documentation for any purpose is hereby granted without fee,
13 * provided that the above copyright notice appear in all copies and that
14 * both that copyright notice and this permission notice appear in
15 * supporting documentation, and that the name of the authors not be used
16 * in advertising or publicity pertaining to distribution of the software
17 * without specific, written prior permission. The authors makes no
18 * representations about the suitability of this software for any purpose.
19 * It is provided "as is" without express or implied warranty.
21 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
22 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
23 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
24 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
25 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
26 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
27 * PERFORMANCE OF THIS SOFTWARE.
29 * ========================================================================
31 * Language: ANSI C
32 * Environment: Any
33 * Developer: Kendall Bennett
35 * Description: This file includes subroutines to implement the decoding
36 * and emulation of all the x86 processor instructions.
38 * There are approximately 250 subroutines in here, which correspond
39 * to the 256 byte-"opcodes" found on the 8086. The table which
40 * dispatches this is found in the files optab.[ch].
42 * Each opcode proc has a comment preceding it which gives it's table
43 * address. Several opcodes are missing (undefined) in the table.
45 * Each proc includes information for decoding (DECODE_PRINTF and
46 * DECODE_PRINTF2), debugging (TRACE_REGS, SINGLE_STEP), and misc
47 * functions (START_OF_INSTR, END_OF_INSTR).
49 * Many of the procedures are *VERY* similar in coding. This has
50 * allowed for a very large amount of code to be generated in a fairly
51 * short amount of time (i.e. cut, paste, and modify). The result is
52 * that much of the code below could have been folded into subroutines
53 * for a large reduction in size of this file. The downside would be
54 * that there would be a penalty in execution speed. The file could
55 * also have been *MUCH* larger by inlining certain functions which
56 * were called. This could have resulted even faster execution. The
57 * prime directive I used to decide whether to inline the code or to
58 * modularize it, was basically: 1) no unnecessary subroutine calls,
59 * 2) no routines more than about 200 lines in size, and 3) modularize
60 * any code that I might not get right the first time. The fetch_*
61 * subroutines fall into the latter category. The decode_* fall
62 * into the second category. The coding of the "switch(mod){ .... }"
63 * in many of the subroutines below falls into the first category.
64 * Especially, the coding of {add,and,or,sub,...}_{byte,word}
65 * subroutines are an especially glaring case of the third guideline.
66 * Since so much of the code is cloned from other modules (compare
67 * opcode #00 to opcode #01), making the basic operations subroutine
68 * calls is especially important; otherwise mistakes in coding an
69 * "add" would represent a nightmare in maintenance.
71 ****************************************************************************/
73 #include "x86emui.h"
75 /*----------------------------- Implementation ----------------------------*/
77 /* constant arrays to do several instructions in just one function */
79 #ifdef DEBUG
80 static const char *x86emu_GenOpName[8] = {
81 "ADD", "OR", "ADC", "SBB", "AND", "SUB", "XOR", "CMP"};
82 #endif
84 /* used by several opcodes */
85 static u8 (*genop_byte_operation[])(u8 d, u8 s) =
87 add_byte, /* 00 */
88 or_byte, /* 01 */
89 adc_byte, /* 02 */
90 sbb_byte, /* 03 */
91 and_byte, /* 04 */
92 sub_byte, /* 05 */
93 xor_byte, /* 06 */
94 cmp_byte, /* 07 */
97 static u16 (*genop_word_operation[])(u16 d, u16 s) =
99 add_word, /*00 */
100 or_word, /*01 */
101 adc_word, /*02 */
102 sbb_word, /*03 */
103 and_word, /*04 */
104 sub_word, /*05 */
105 xor_word, /*06 */
106 cmp_word, /*07 */
109 static u32 (*genop_long_operation[])(u32 d, u32 s) =
111 add_long, /*00 */
112 or_long, /*01 */
113 adc_long, /*02 */
114 sbb_long, /*03 */
115 and_long, /*04 */
116 sub_long, /*05 */
117 xor_long, /*06 */
118 cmp_long, /*07 */
121 /* used by opcodes 80, c0, d0, and d2. */
122 static u8(*opcD0_byte_operation[])(u8 d, u8 s) =
124 rol_byte,
125 ror_byte,
126 rcl_byte,
127 rcr_byte,
128 shl_byte,
129 shr_byte,
130 shl_byte, /* sal_byte === shl_byte by definition */
131 sar_byte,
134 /* used by opcodes c1, d1, and d3. */
135 static u16(*opcD1_word_operation[])(u16 s, u8 d) =
137 rol_word,
138 ror_word,
139 rcl_word,
140 rcr_word,
141 shl_word,
142 shr_word,
143 shl_word, /* sal_byte === shl_byte by definition */
144 sar_word,
147 /* used by opcodes c1, d1, and d3. */
148 static u32 (*opcD1_long_operation[])(u32 s, u8 d) =
150 rol_long,
151 ror_long,
152 rcl_long,
153 rcr_long,
154 shl_long,
155 shr_long,
156 shl_long, /* sal_byte === shl_byte by definition */
157 sar_long,
160 #ifdef DEBUG
162 static const char *opF6_names[8] =
163 { "TEST\t", "", "NOT\t", "NEG\t", "MUL\t", "IMUL\t", "DIV\t", "IDIV\t" };
165 #endif
167 /****************************************************************************
168 PARAMETERS:
169 op1 - Instruction op code
171 REMARKS:
172 Handles illegal opcodes.
173 ****************************************************************************/
174 static void x86emuOp_illegal_op(
175 u8 op1)
177 START_OF_INSTR();
178 if (M.x86.R_SP != 0) {
179 DECODE_PRINTF("ILLEGAL X86 OPCODE\n");
180 TRACE_REGS();
181 DB( printf("%04x:%04x: %02X ILLEGAL X86 OPCODE!\n",
182 M.x86.R_CS, M.x86.R_IP-1,op1));
183 HALT_SYS();
185 else {
186 /* If we get here, it means the stack pointer is back to zero
187 * so we are just returning from an emulator service call
188 * so therte is no need to display an error message. We trap
189 * the emulator with an 0xF1 opcode to finish the service
190 * call.
192 X86EMU_halt_sys();
194 END_OF_INSTR();
197 /****************************************************************************
198 REMARKS:
199 Handles opcodes 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38
200 ****************************************************************************/
201 static void x86emuOp_genop_byte_RM_R(u8 op1)
203 int mod, rl, rh;
204 uint destoffset;
205 u8 *destreg, *srcreg;
206 u8 destval;
208 op1 = (op1 >> 3) & 0x7;
210 START_OF_INSTR();
211 DECODE_PRINTF(x86emu_GenOpName[op1]);
212 DECODE_PRINTF("\t");
213 FETCH_DECODE_MODRM(mod, rh, rl);
214 if (mod<3)
215 { destoffset = decode_rmXX_address(mod,rl);
216 DECODE_PRINTF(",");
217 destval = fetch_data_byte(destoffset);
218 srcreg = DECODE_RM_BYTE_REGISTER(rh);
219 DECODE_PRINTF("\n");
220 TRACE_AND_STEP();
221 destval = genop_byte_operation[op1](destval, *srcreg);
222 if (op1 != 7)
223 store_data_byte(destoffset, destval);
225 else
226 { /* register to register */
227 destreg = DECODE_RM_BYTE_REGISTER(rl);
228 DECODE_PRINTF(",");
229 srcreg = DECODE_RM_BYTE_REGISTER(rh);
230 DECODE_PRINTF("\n");
231 TRACE_AND_STEP();
232 *destreg = genop_byte_operation[op1](*destreg, *srcreg);
234 DECODE_CLEAR_SEGOVR();
235 END_OF_INSTR();
238 /****************************************************************************
239 REMARKS:
240 Handles opcodes 0x01, 0x09, 0x11, 0x19, 0x21, 0x29, 0x31, 0x39
241 ****************************************************************************/
242 static void x86emuOp_genop_word_RM_R(u8 op1)
244 int mod, rl, rh;
245 uint destoffset;
247 op1 = (op1 >> 3) & 0x7;
249 START_OF_INSTR();
250 DECODE_PRINTF(x86emu_GenOpName[op1]);
251 DECODE_PRINTF("\t");
252 FETCH_DECODE_MODRM(mod, rh, rl);
254 if (mod<3) {
255 destoffset = decode_rmXX_address(mod,rl);
256 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
257 u32 destval;
258 u32 *srcreg;
260 DECODE_PRINTF(",");
261 destval = fetch_data_long(destoffset);
262 srcreg = DECODE_RM_LONG_REGISTER(rh);
263 DECODE_PRINTF("\n");
264 TRACE_AND_STEP();
265 destval = genop_long_operation[op1](destval, *srcreg);
266 if (op1 != 7)
267 store_data_long(destoffset, destval);
268 } else {
269 u16 destval;
270 u16 *srcreg;
272 DECODE_PRINTF(",");
273 destval = fetch_data_word(destoffset);
274 srcreg = DECODE_RM_WORD_REGISTER(rh);
275 DECODE_PRINTF("\n");
276 TRACE_AND_STEP();
277 destval = genop_word_operation[op1](destval, *srcreg);
278 if (op1 != 7)
279 store_data_word(destoffset, destval);
281 } else { /* register to register */
282 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
283 u32 *destreg, *srcreg;
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;
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);
302 DECODE_CLEAR_SEGOVR();
303 END_OF_INSTR();
306 /****************************************************************************
307 REMARKS:
308 Handles opcodes 0x02, 0x0a, 0x12, 0x1a, 0x22, 0x2a, 0x32, 0x3a
309 ****************************************************************************/
310 static void x86emuOp_genop_byte_R_RM(u8 op1)
312 int mod, rl, rh;
313 u8 *destreg, *srcreg;
314 uint srcoffset;
315 u8 srcval;
317 op1 = (op1 >> 3) & 0x7;
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;
334 DECODE_PRINTF("\n");
335 TRACE_AND_STEP();
336 *destreg = genop_byte_operation[op1](*destreg, srcval);
338 DECODE_CLEAR_SEGOVR();
339 END_OF_INSTR();
342 /****************************************************************************
343 REMARKS:
344 Handles opcodes 0x03, 0x0b, 0x13, 0x1b, 0x23, 0x2b, 0x33, 0x3b
345 ****************************************************************************/
346 static void x86emuOp_genop_word_R_RM(u8 op1)
348 int mod, rl, rh;
349 uint srcoffset;
350 u32 *destreg32, srcval;
351 u16 *destreg;
353 op1 = (op1 >> 3) & 0x7;
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);
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);
395 DECODE_CLEAR_SEGOVR();
396 END_OF_INSTR();
399 /****************************************************************************
400 REMARKS:
401 Handles opcodes 0x04, 0x0c, 0x14, 0x1c, 0x24, 0x2c, 0x34, 0x3c
402 ****************************************************************************/
403 static void x86emuOp_genop_byte_AL_IMM(u8 op1)
405 u8 srcval;
407 op1 = (op1 >> 3) & 0x7;
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();
420 /****************************************************************************
421 REMARKS:
422 Handles opcodes 0x05, 0x0d, 0x15, 0x1d, 0x25, 0x2d, 0x35, 0x3d
423 ****************************************************************************/
424 static void x86emuOp_genop_word_AX_IMM(u8 op1)
426 u32 srcval;
428 op1 = (op1 >> 3) & 0x7;
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();
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);
447 DECODE_CLEAR_SEGOVR();
448 END_OF_INSTR();
451 /****************************************************************************
452 REMARKS:
453 Handles opcode 0x06
454 ****************************************************************************/
455 static void x86emuOp_push_ES(u8 X86EMU_UNUSED(op1))
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();
465 /****************************************************************************
466 REMARKS:
467 Handles opcode 0x07
468 ****************************************************************************/
469 static void x86emuOp_pop_ES(u8 X86EMU_UNUSED(op1))
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();
479 /****************************************************************************
480 REMARKS:
481 Handles opcode 0x0e
482 ****************************************************************************/
483 static void x86emuOp_push_CS(u8 X86EMU_UNUSED(op1))
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();
493 /****************************************************************************
494 REMARKS:
495 Handles opcode 0x0f. Escape for two-byte opcode (286 or better)
496 ****************************************************************************/
497 static void x86emuOp_two_byte(u8 X86EMU_UNUSED(op1))
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);
504 /****************************************************************************
505 REMARKS:
506 Handles opcode 0x16
507 ****************************************************************************/
508 static void x86emuOp_push_SS(u8 X86EMU_UNUSED(op1))
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();
518 /****************************************************************************
519 REMARKS:
520 Handles opcode 0x17
521 ****************************************************************************/
522 static void x86emuOp_pop_SS(u8 X86EMU_UNUSED(op1))
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();
532 /****************************************************************************
533 REMARKS:
534 Handles opcode 0x1e
535 ****************************************************************************/
536 static void x86emuOp_push_DS(u8 X86EMU_UNUSED(op1))
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();
546 /****************************************************************************
547 REMARKS:
548 Handles opcode 0x1f
549 ****************************************************************************/
550 static void x86emuOp_pop_DS(u8 X86EMU_UNUSED(op1))
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();
560 /****************************************************************************
561 REMARKS:
562 Handles opcode 0x26
563 ****************************************************************************/
564 static void x86emuOp_segovr_ES(u8 X86EMU_UNUSED(op1))
566 START_OF_INSTR();
567 DECODE_PRINTF("ES:\n");
568 TRACE_AND_STEP();
569 M.x86.mode |= SYSMODE_SEGOVR_ES;
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.
574 END_OF_INSTR();
577 /****************************************************************************
578 REMARKS:
579 Handles opcode 0x27
580 ****************************************************************************/
581 static void x86emuOp_daa(u8 X86EMU_UNUSED(op1))
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();
591 /****************************************************************************
592 REMARKS:
593 Handles opcode 0x2e
594 ****************************************************************************/
595 static void x86emuOp_segovr_CS(u8 X86EMU_UNUSED(op1))
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();
605 /****************************************************************************
606 REMARKS:
607 Handles opcode 0x2f
608 ****************************************************************************/
609 static void x86emuOp_das(u8 X86EMU_UNUSED(op1))
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();
619 /****************************************************************************
620 REMARKS:
621 Handles opcode 0x36
622 ****************************************************************************/
623 static void x86emuOp_segovr_SS(u8 X86EMU_UNUSED(op1))
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();
633 /****************************************************************************
634 REMARKS:
635 Handles opcode 0x37
636 ****************************************************************************/
637 static void x86emuOp_aaa(u8 X86EMU_UNUSED(op1))
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();
647 /****************************************************************************
648 REMARKS:
649 Handles opcode 0x3e
650 ****************************************************************************/
651 static void x86emuOp_segovr_DS(u8 X86EMU_UNUSED(op1))
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();
661 /****************************************************************************
662 REMARKS:
663 Handles opcode 0x3f
664 ****************************************************************************/
665 static void x86emuOp_aas(u8 X86EMU_UNUSED(op1))
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();
675 /****************************************************************************
676 REMARKS:
677 Handles opcode 0x40 - 0x47
678 ****************************************************************************/
679 static void x86emuOp_inc_register(u8 op1)
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);
697 DECODE_CLEAR_SEGOVR();
698 END_OF_INSTR();
701 /****************************************************************************
702 REMARKS:
703 Handles opcode 0x48 - 0x4F
704 ****************************************************************************/
705 static void x86emuOp_dec_register(u8 op1)
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);
723 DECODE_CLEAR_SEGOVR();
724 END_OF_INSTR();
727 /****************************************************************************
728 REMARKS:
729 Handles opcode 0x50 - 0x57
730 ****************************************************************************/
731 static void x86emuOp_push_register(u8 op1)
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);
749 DECODE_CLEAR_SEGOVR();
750 END_OF_INSTR();
753 /****************************************************************************
754 REMARKS:
755 Handles opcode 0x58 - 0x5F
756 ****************************************************************************/
757 static void x86emuOp_pop_register(u8 op1)
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();
775 DECODE_CLEAR_SEGOVR();
776 END_OF_INSTR();
779 /****************************************************************************
780 REMARKS:
781 Handles opcode 0x60
782 ****************************************************************************/
783 static void x86emuOp_push_all(u8 X86EMU_UNUSED(op1))
785 START_OF_INSTR();
786 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
787 DECODE_PRINTF("PUSHAD\n");
788 } else {
789 DECODE_PRINTF("PUSHA\n");
791 TRACE_AND_STEP();
792 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
793 u32 old_sp = M.x86.R_ESP;
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;
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);
815 DECODE_CLEAR_SEGOVR();
816 END_OF_INSTR();
819 /****************************************************************************
820 REMARKS:
821 Handles opcode 0x61
822 ****************************************************************************/
823 static void x86emuOp_pop_all(u8 X86EMU_UNUSED(op1))
825 START_OF_INSTR();
826 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
827 DECODE_PRINTF("POPAD\n");
828 } else {
829 DECODE_PRINTF("POPA\n");
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();
851 DECODE_CLEAR_SEGOVR();
852 END_OF_INSTR();
855 /*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */
856 /*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */
858 /****************************************************************************
859 REMARKS:
860 Handles opcode 0x64
861 ****************************************************************************/
862 static void x86emuOp_segovr_FS(u8 X86EMU_UNUSED(op1))
864 START_OF_INSTR();
865 DECODE_PRINTF("FS:\n");
866 TRACE_AND_STEP();
867 M.x86.mode |= SYSMODE_SEGOVR_FS;
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.
872 END_OF_INSTR();
875 /****************************************************************************
876 REMARKS:
877 Handles opcode 0x65
878 ****************************************************************************/
879 static void x86emuOp_segovr_GS(u8 X86EMU_UNUSED(op1))
881 START_OF_INSTR();
882 DECODE_PRINTF("GS:\n");
883 TRACE_AND_STEP();
884 M.x86.mode |= SYSMODE_SEGOVR_GS;
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.
889 END_OF_INSTR();
892 /****************************************************************************
893 REMARKS:
894 Handles opcode 0x66 - prefix for 32-bit register
895 ****************************************************************************/
896 static void x86emuOp_prefix_data(u8 X86EMU_UNUSED(op1))
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();
906 /****************************************************************************
907 REMARKS:
908 Handles opcode 0x67 - prefix for 32-bit address
909 ****************************************************************************/
910 static void x86emuOp_prefix_addr(u8 X86EMU_UNUSED(op1))
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();
920 /****************************************************************************
921 REMARKS:
922 Handles opcode 0x68
923 ****************************************************************************/
924 static void x86emuOp_push_word_IMM(u8 X86EMU_UNUSED(op1))
926 u32 imm;
928 START_OF_INSTR();
929 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
930 imm = fetch_long_imm();
931 } else {
932 imm = fetch_word_imm();
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);
941 DECODE_CLEAR_SEGOVR();
942 END_OF_INSTR();
945 /****************************************************************************
946 REMARKS:
947 Handles opcode 0x69
948 ****************************************************************************/
949 static void x86emuOp_imul_word_IMM(u8 X86EMU_UNUSED(op1))
951 int mod, rl, rh;
952 uint srcoffset;
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;
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);
980 *destreg = (u32)res_lo;
981 } else {
982 u16 *destreg;
983 u16 srcval;
984 u32 res;
985 s16 imm;
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);
1002 *destreg = (u16)res;
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;
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);
1025 *destreg = (u32)res_lo;
1026 } else {
1027 u16 *destreg,*srcreg;
1028 u32 res;
1029 s16 imm;
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);
1045 *destreg = (u16)res;
1048 DECODE_CLEAR_SEGOVR();
1049 END_OF_INSTR();
1052 /****************************************************************************
1053 REMARKS:
1054 Handles opcode 0x6a
1055 ****************************************************************************/
1056 static void x86emuOp_push_byte_IMM(u8 X86EMU_UNUSED(op1))
1058 s16 imm;
1060 START_OF_INSTR();
1061 imm = (s8)fetch_byte_imm();
1062 DECODE_PRINTF2("PUSH\t%d\n", imm);
1063 TRACE_AND_STEP();
1064 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1065 push_long(imm);
1066 } else {
1067 push_word(imm);
1069 DECODE_CLEAR_SEGOVR();
1070 END_OF_INSTR();
1073 /****************************************************************************
1074 REMARKS:
1075 Handles opcode 0x6b
1076 ****************************************************************************/
1077 static void x86emuOp_imul_byte_IMM(u8 X86EMU_UNUSED(op1))
1079 int mod, rl, rh;
1080 uint srcoffset;
1081 s8 imm;
1083 START_OF_INSTR();
1084 DECODE_PRINTF("IMUL\t");
1085 FETCH_DECODE_MODRM(mod, rh, rl);
1086 if (mod < 3) {
1087 srcoffset = decode_rmXX_address(mod, rl);
1088 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1089 u32 *destreg;
1090 u32 srcval;
1091 u32 res_lo,res_hi;
1093 destreg = DECODE_RM_LONG_REGISTER(rh);
1094 DECODE_PRINTF(",");
1095 srcval = fetch_data_long(srcoffset);
1096 imm = fetch_byte_imm();
1097 DECODE_PRINTF2(",%d\n", (s32)imm);
1098 TRACE_AND_STEP();
1099 imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
1100 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1101 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1102 CLEAR_FLAG(F_CF);
1103 CLEAR_FLAG(F_OF);
1104 } else {
1105 SET_FLAG(F_CF);
1106 SET_FLAG(F_OF);
1108 *destreg = (u32)res_lo;
1109 } else {
1110 u16 *destreg;
1111 u16 srcval;
1112 u32 res;
1114 destreg = DECODE_RM_WORD_REGISTER(rh);
1115 DECODE_PRINTF(",");
1116 srcval = fetch_data_word(srcoffset);
1117 imm = fetch_byte_imm();
1118 DECODE_PRINTF2(",%d\n", (s32)imm);
1119 TRACE_AND_STEP();
1120 res = (s16)srcval * (s16)imm;
1121 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1122 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1123 CLEAR_FLAG(F_CF);
1124 CLEAR_FLAG(F_OF);
1125 } else {
1126 SET_FLAG(F_CF);
1127 SET_FLAG(F_OF);
1129 *destreg = (u16)res;
1131 } else { /* register to register */
1132 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1133 u32 *destreg,*srcreg;
1134 u32 res_lo,res_hi;
1136 destreg = DECODE_RM_LONG_REGISTER(rh);
1137 DECODE_PRINTF(",");
1138 srcreg = DECODE_RM_LONG_REGISTER(rl);
1139 imm = fetch_byte_imm();
1140 DECODE_PRINTF2(",%d\n", (s32)imm);
1141 TRACE_AND_STEP();
1142 imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
1143 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1144 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1145 CLEAR_FLAG(F_CF);
1146 CLEAR_FLAG(F_OF);
1147 } else {
1148 SET_FLAG(F_CF);
1149 SET_FLAG(F_OF);
1151 *destreg = (u32)res_lo;
1152 } else {
1153 u16 *destreg,*srcreg;
1154 u32 res;
1156 destreg = DECODE_RM_WORD_REGISTER(rh);
1157 DECODE_PRINTF(",");
1158 srcreg = DECODE_RM_WORD_REGISTER(rl);
1159 imm = fetch_byte_imm();
1160 DECODE_PRINTF2(",%d\n", (s32)imm);
1161 TRACE_AND_STEP();
1162 res = (s16)*srcreg * (s16)imm;
1163 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1164 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1165 CLEAR_FLAG(F_CF);
1166 CLEAR_FLAG(F_OF);
1167 } else {
1168 SET_FLAG(F_CF);
1169 SET_FLAG(F_OF);
1171 *destreg = (u16)res;
1174 DECODE_CLEAR_SEGOVR();
1175 END_OF_INSTR();
1178 /****************************************************************************
1179 REMARKS:
1180 Handles opcode 0x6c
1181 ****************************************************************************/
1182 static void x86emuOp_ins_byte(u8 X86EMU_UNUSED(op1))
1184 START_OF_INSTR();
1185 DECODE_PRINTF("INSB\n");
1186 ins(1);
1187 TRACE_AND_STEP();
1188 DECODE_CLEAR_SEGOVR();
1189 END_OF_INSTR();
1192 /****************************************************************************
1193 REMARKS:
1194 Handles opcode 0x6d
1195 ****************************************************************************/
1196 static void x86emuOp_ins_word(u8 X86EMU_UNUSED(op1))
1198 START_OF_INSTR();
1199 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1200 DECODE_PRINTF("INSD\n");
1201 ins(4);
1202 } else {
1203 DECODE_PRINTF("INSW\n");
1204 ins(2);
1206 TRACE_AND_STEP();
1207 DECODE_CLEAR_SEGOVR();
1208 END_OF_INSTR();
1211 /****************************************************************************
1212 REMARKS:
1213 Handles opcode 0x6e
1214 ****************************************************************************/
1215 static void x86emuOp_outs_byte(u8 X86EMU_UNUSED(op1))
1217 START_OF_INSTR();
1218 DECODE_PRINTF("OUTSB\n");
1219 outs(1);
1220 TRACE_AND_STEP();
1221 DECODE_CLEAR_SEGOVR();
1222 END_OF_INSTR();
1225 /****************************************************************************
1226 REMARKS:
1227 Handles opcode 0x6f
1228 ****************************************************************************/
1229 static void x86emuOp_outs_word(u8 X86EMU_UNUSED(op1))
1231 START_OF_INSTR();
1232 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1233 DECODE_PRINTF("OUTSD\n");
1234 outs(4);
1235 } else {
1236 DECODE_PRINTF("OUTSW\n");
1237 outs(2);
1239 TRACE_AND_STEP();
1240 DECODE_CLEAR_SEGOVR();
1241 END_OF_INSTR();
1244 /****************************************************************************
1245 REMARKS:
1246 Handles opcode 0x70 - 0x7F
1247 ****************************************************************************/
1248 static void x86emuOp_jump_near_cond(u8 op1)
1250 s8 offset;
1251 u16 target;
1252 int cond;
1254 /* jump to byte offset if overflow flag is set */
1255 START_OF_INSTR();
1256 cond = x86emu_check_jump_condition(op1 & 0xF);
1257 offset = (s8)fetch_byte_imm();
1258 target = (u16)(M.x86.R_IP + (s16)offset);
1259 DECODE_PRINTF2("%x\n", target);
1260 TRACE_AND_STEP();
1261 if (cond) {
1262 M.x86.R_IP = target;
1263 JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, " NEAR COND ");
1265 DECODE_CLEAR_SEGOVR();
1266 END_OF_INSTR();
1269 /****************************************************************************
1270 REMARKS:
1271 Handles opcode 0x80
1272 ****************************************************************************/
1273 static void x86emuOp_opc80_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
1275 int mod, rl, rh;
1276 u8 *destreg;
1277 uint destoffset;
1278 u8 imm;
1279 u8 destval;
1282 * Weirdo special case instruction format. Part of the opcode
1283 * held below in "RH". Doubly nested case would result, except
1284 * that the decoded instruction
1286 START_OF_INSTR();
1287 FETCH_DECODE_MODRM(mod, rh, rl);
1288 #ifdef DEBUG
1289 if (DEBUG_DECODE()) {
1290 /* XXX DECODE_PRINTF may be changed to something more
1291 general, so that it is important to leave the strings
1292 in the same format, even though the result is that the
1293 above test is done twice. */
1295 switch (rh) {
1296 case 0:
1297 DECODE_PRINTF("ADD\t");
1298 break;
1299 case 1:
1300 DECODE_PRINTF("OR\t");
1301 break;
1302 case 2:
1303 DECODE_PRINTF("ADC\t");
1304 break;
1305 case 3:
1306 DECODE_PRINTF("SBB\t");
1307 break;
1308 case 4:
1309 DECODE_PRINTF("AND\t");
1310 break;
1311 case 5:
1312 DECODE_PRINTF("SUB\t");
1313 break;
1314 case 6:
1315 DECODE_PRINTF("XOR\t");
1316 break;
1317 case 7:
1318 DECODE_PRINTF("CMP\t");
1319 break;
1322 #endif
1323 /* know operation, decode the mod byte to find the addressing
1324 mode. */
1325 if (mod < 3) {
1326 DECODE_PRINTF("BYTE PTR ");
1327 destoffset = decode_rmXX_address(mod, rl);
1328 DECODE_PRINTF(",");
1329 destval = fetch_data_byte(destoffset);
1330 imm = fetch_byte_imm();
1331 DECODE_PRINTF2("%x\n", imm);
1332 TRACE_AND_STEP();
1333 destval = (*genop_byte_operation[rh]) (destval, imm);
1334 if (rh != 7)
1335 store_data_byte(destoffset, destval);
1336 } else { /* register to register */
1337 destreg = DECODE_RM_BYTE_REGISTER(rl);
1338 DECODE_PRINTF(",");
1339 imm = fetch_byte_imm();
1340 DECODE_PRINTF2("%x\n", imm);
1341 TRACE_AND_STEP();
1342 *destreg = (*genop_byte_operation[rh]) (*destreg, imm);
1344 DECODE_CLEAR_SEGOVR();
1345 END_OF_INSTR();
1348 /****************************************************************************
1349 REMARKS:
1350 Handles opcode 0x81
1351 ****************************************************************************/
1352 static void x86emuOp_opc81_word_RM_IMM(u8 X86EMU_UNUSED(op1))
1354 int mod, rl, rh;
1355 uint destoffset;
1358 * Weirdo special case instruction format. Part of the opcode
1359 * held below in "RH". Doubly nested case would result, except
1360 * that the decoded instruction
1362 START_OF_INSTR();
1363 FETCH_DECODE_MODRM(mod, rh, rl);
1364 #ifdef DEBUG
1365 if (DEBUG_DECODE()) {
1366 /* XXX DECODE_PRINTF may be changed to something more
1367 general, so that it is important to leave the strings
1368 in the same format, even though the result is that the
1369 above test is done twice. */
1371 switch (rh) {
1372 case 0:
1373 DECODE_PRINTF("ADD\t");
1374 break;
1375 case 1:
1376 DECODE_PRINTF("OR\t");
1377 break;
1378 case 2:
1379 DECODE_PRINTF("ADC\t");
1380 break;
1381 case 3:
1382 DECODE_PRINTF("SBB\t");
1383 break;
1384 case 4:
1385 DECODE_PRINTF("AND\t");
1386 break;
1387 case 5:
1388 DECODE_PRINTF("SUB\t");
1389 break;
1390 case 6:
1391 DECODE_PRINTF("XOR\t");
1392 break;
1393 case 7:
1394 DECODE_PRINTF("CMP\t");
1395 break;
1398 #endif
1400 * Know operation, decode the mod byte to find the addressing
1401 * mode.
1403 if (mod < 3) {
1404 DECODE_PRINTF("DWORD PTR ");
1405 destoffset = decode_rmXX_address(mod, rl);
1406 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1407 u32 destval,imm;
1409 DECODE_PRINTF(",");
1410 destval = fetch_data_long(destoffset);
1411 imm = fetch_long_imm();
1412 DECODE_PRINTF2("%x\n", imm);
1413 TRACE_AND_STEP();
1414 destval = (*genop_long_operation[rh]) (destval, imm);
1415 if (rh != 7)
1416 store_data_long(destoffset, destval);
1417 } else {
1418 u16 destval,imm;
1420 DECODE_PRINTF(",");
1421 destval = fetch_data_word(destoffset);
1422 imm = fetch_word_imm();
1423 DECODE_PRINTF2("%x\n", imm);
1424 TRACE_AND_STEP();
1425 destval = (*genop_word_operation[rh]) (destval, imm);
1426 if (rh != 7)
1427 store_data_word(destoffset, destval);
1429 } else { /* register to register */
1430 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1431 u32 *destreg, imm;
1433 destreg = DECODE_RM_LONG_REGISTER(rl);
1434 DECODE_PRINTF(",");
1435 imm = fetch_long_imm();
1436 DECODE_PRINTF2("%x\n", imm);
1437 TRACE_AND_STEP();
1438 *destreg = (*genop_long_operation[rh]) (*destreg, imm);
1439 } else {
1440 u16 *destreg, imm;
1442 destreg = DECODE_RM_WORD_REGISTER(rl);
1443 DECODE_PRINTF(",");
1444 imm = fetch_word_imm();
1445 DECODE_PRINTF2("%x\n", imm);
1446 TRACE_AND_STEP();
1447 *destreg = (*genop_word_operation[rh]) (*destreg, imm);
1450 DECODE_CLEAR_SEGOVR();
1451 END_OF_INSTR();
1454 /****************************************************************************
1455 REMARKS:
1456 Handles opcode 0x82
1457 ****************************************************************************/
1458 static void x86emuOp_opc82_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
1460 int mod, rl, rh;
1461 u8 *destreg;
1462 uint destoffset;
1463 u8 imm;
1464 u8 destval;
1467 * Weirdo special case instruction format. Part of the opcode
1468 * held below in "RH". Doubly nested case would result, except
1469 * that the decoded instruction Similar to opcode 81, except that
1470 * the immediate byte is sign extended to a word length.
1472 START_OF_INSTR();
1473 FETCH_DECODE_MODRM(mod, rh, rl);
1474 #ifdef DEBUG
1475 if (DEBUG_DECODE()) {
1476 /* XXX DECODE_PRINTF may be changed to something more
1477 general, so that it is important to leave the strings
1478 in the same format, even though the result is that the
1479 above test is done twice. */
1480 switch (rh) {
1481 case 0:
1482 DECODE_PRINTF("ADD\t");
1483 break;
1484 case 1:
1485 DECODE_PRINTF("OR\t");
1486 break;
1487 case 2:
1488 DECODE_PRINTF("ADC\t");
1489 break;
1490 case 3:
1491 DECODE_PRINTF("SBB\t");
1492 break;
1493 case 4:
1494 DECODE_PRINTF("AND\t");
1495 break;
1496 case 5:
1497 DECODE_PRINTF("SUB\t");
1498 break;
1499 case 6:
1500 DECODE_PRINTF("XOR\t");
1501 break;
1502 case 7:
1503 DECODE_PRINTF("CMP\t");
1504 break;
1507 #endif
1508 /* know operation, decode the mod byte to find the addressing
1509 mode. */
1510 if (mod < 3) {
1511 DECODE_PRINTF("BYTE PTR ");
1512 destoffset = decode_rmXX_address(mod, rl);
1513 destval = fetch_data_byte(destoffset);
1514 imm = fetch_byte_imm();
1515 DECODE_PRINTF2(",%x\n", imm);
1516 TRACE_AND_STEP();
1517 destval = (*genop_byte_operation[rh]) (destval, imm);
1518 if (rh != 7)
1519 store_data_byte(destoffset, destval);
1520 } else { /* register to register */
1521 destreg = DECODE_RM_BYTE_REGISTER(rl);
1522 imm = fetch_byte_imm();
1523 DECODE_PRINTF2(",%x\n", imm);
1524 TRACE_AND_STEP();
1525 *destreg = (*genop_byte_operation[rh]) (*destreg, imm);
1527 DECODE_CLEAR_SEGOVR();
1528 END_OF_INSTR();
1531 /****************************************************************************
1532 REMARKS:
1533 Handles opcode 0x83
1534 ****************************************************************************/
1535 static void x86emuOp_opc83_word_RM_IMM(u8 X86EMU_UNUSED(op1))
1537 int mod, rl, rh;
1538 uint destoffset;
1541 * Weirdo special case instruction format. Part of the opcode
1542 * held below in "RH". Doubly nested case would result, except
1543 * that the decoded instruction Similar to opcode 81, except that
1544 * the immediate byte is sign extended to a word length.
1546 START_OF_INSTR();
1547 FETCH_DECODE_MODRM(mod, rh, rl);
1548 #ifdef DEBUG
1549 if (DEBUG_DECODE()) {
1550 /* XXX DECODE_PRINTF may be changed to something more
1551 general, so that it is important to leave the strings
1552 in the same format, even though the result is that the
1553 above test is done twice. */
1554 switch (rh) {
1555 case 0:
1556 DECODE_PRINTF("ADD\t");
1557 break;
1558 case 1:
1559 DECODE_PRINTF("OR\t");
1560 break;
1561 case 2:
1562 DECODE_PRINTF("ADC\t");
1563 break;
1564 case 3:
1565 DECODE_PRINTF("SBB\t");
1566 break;
1567 case 4:
1568 DECODE_PRINTF("AND\t");
1569 break;
1570 case 5:
1571 DECODE_PRINTF("SUB\t");
1572 break;
1573 case 6:
1574 DECODE_PRINTF("XOR\t");
1575 break;
1576 case 7:
1577 DECODE_PRINTF("CMP\t");
1578 break;
1581 #endif
1582 /* know operation, decode the mod byte to find the addressing
1583 mode. */
1584 if (mod < 3) {
1585 DECODE_PRINTF("DWORD PTR ");
1586 destoffset = decode_rmXX_address(mod,rl);
1588 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1589 u32 destval,imm;
1591 destval = fetch_data_long(destoffset);
1592 imm = (s8) fetch_byte_imm();
1593 DECODE_PRINTF2(",%x\n", imm);
1594 TRACE_AND_STEP();
1595 destval = (*genop_long_operation[rh]) (destval, imm);
1596 if (rh != 7)
1597 store_data_long(destoffset, destval);
1598 } else {
1599 u16 destval,imm;
1601 destval = fetch_data_word(destoffset);
1602 imm = (s8) fetch_byte_imm();
1603 DECODE_PRINTF2(",%x\n", imm);
1604 TRACE_AND_STEP();
1605 destval = (*genop_word_operation[rh]) (destval, imm);
1606 if (rh != 7)
1607 store_data_word(destoffset, destval);
1609 } else { /* register to register */
1610 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1611 u32 *destreg, imm;
1613 destreg = DECODE_RM_LONG_REGISTER(rl);
1614 imm = (s8) fetch_byte_imm();
1615 DECODE_PRINTF2(",%x\n", imm);
1616 TRACE_AND_STEP();
1617 *destreg = (*genop_long_operation[rh]) (*destreg, imm);
1618 } else {
1619 u16 *destreg, imm;
1621 destreg = DECODE_RM_WORD_REGISTER(rl);
1622 imm = (s8) fetch_byte_imm();
1623 DECODE_PRINTF2(",%x\n", imm);
1624 TRACE_AND_STEP();
1625 *destreg = (*genop_word_operation[rh]) (*destreg, imm);
1628 DECODE_CLEAR_SEGOVR();
1629 END_OF_INSTR();
1632 /****************************************************************************
1633 REMARKS:
1634 Handles opcode 0x84
1635 ****************************************************************************/
1636 static void x86emuOp_test_byte_RM_R(u8 X86EMU_UNUSED(op1))
1638 int mod, rl, rh;
1639 u8 *destreg, *srcreg;
1640 uint destoffset;
1641 u8 destval;
1643 START_OF_INSTR();
1644 DECODE_PRINTF("TEST\t");
1645 FETCH_DECODE_MODRM(mod, rh, rl);
1646 if (mod < 3) {
1647 destoffset = decode_rmXX_address(mod, rl);
1648 DECODE_PRINTF(",");
1649 destval = fetch_data_byte(destoffset);
1650 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1651 DECODE_PRINTF("\n");
1652 TRACE_AND_STEP();
1653 test_byte(destval, *srcreg);
1654 } else { /* register to register */
1655 destreg = DECODE_RM_BYTE_REGISTER(rl);
1656 DECODE_PRINTF(",");
1657 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1658 DECODE_PRINTF("\n");
1659 TRACE_AND_STEP();
1660 test_byte(*destreg, *srcreg);
1662 DECODE_CLEAR_SEGOVR();
1663 END_OF_INSTR();
1666 /****************************************************************************
1667 REMARKS:
1668 Handles opcode 0x85
1669 ****************************************************************************/
1670 static void x86emuOp_test_word_RM_R(u8 X86EMU_UNUSED(op1))
1672 int mod, rl, rh;
1673 uint destoffset;
1675 START_OF_INSTR();
1676 DECODE_PRINTF("TEST\t");
1677 FETCH_DECODE_MODRM(mod, rh, rl);
1678 if (mod < 3) {
1679 destoffset = decode_rmXX_address(mod, rl);
1680 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1681 u32 destval;
1682 u32 *srcreg;
1684 DECODE_PRINTF(",");
1685 destval = fetch_data_long(destoffset);
1686 srcreg = DECODE_RM_LONG_REGISTER(rh);
1687 DECODE_PRINTF("\n");
1688 TRACE_AND_STEP();
1689 test_long(destval, *srcreg);
1690 } else {
1691 u16 destval;
1692 u16 *srcreg;
1694 DECODE_PRINTF(",");
1695 destval = fetch_data_word(destoffset);
1696 srcreg = DECODE_RM_WORD_REGISTER(rh);
1697 DECODE_PRINTF("\n");
1698 TRACE_AND_STEP();
1699 test_word(destval, *srcreg);
1701 } else { /* register to register */
1702 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1703 u32 *destreg,*srcreg;
1705 destreg = DECODE_RM_LONG_REGISTER(rl);
1706 DECODE_PRINTF(",");
1707 srcreg = DECODE_RM_LONG_REGISTER(rh);
1708 DECODE_PRINTF("\n");
1709 TRACE_AND_STEP();
1710 test_long(*destreg, *srcreg);
1711 } else {
1712 u16 *destreg,*srcreg;
1714 destreg = DECODE_RM_WORD_REGISTER(rl);
1715 DECODE_PRINTF(",");
1716 srcreg = DECODE_RM_WORD_REGISTER(rh);
1717 DECODE_PRINTF("\n");
1718 TRACE_AND_STEP();
1719 test_word(*destreg, *srcreg);
1722 DECODE_CLEAR_SEGOVR();
1723 END_OF_INSTR();
1726 /****************************************************************************
1727 REMARKS:
1728 Handles opcode 0x86
1729 ****************************************************************************/
1730 static void x86emuOp_xchg_byte_RM_R(u8 X86EMU_UNUSED(op1))
1732 int mod, rl, rh;
1733 u8 *destreg, *srcreg;
1734 uint destoffset;
1735 u8 destval;
1736 u8 tmp;
1738 START_OF_INSTR();
1739 DECODE_PRINTF("XCHG\t");
1740 FETCH_DECODE_MODRM(mod, rh, rl);
1741 if (mod < 3) {
1742 destoffset = decode_rmXX_address(mod, rl);
1743 DECODE_PRINTF(",");
1744 destval = fetch_data_byte(destoffset);
1745 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1746 DECODE_PRINTF("\n");
1747 TRACE_AND_STEP();
1748 tmp = *srcreg;
1749 *srcreg = destval;
1750 destval = tmp;
1751 store_data_byte(destoffset, destval);
1752 } else { /* register to register */
1753 destreg = DECODE_RM_BYTE_REGISTER(rl);
1754 DECODE_PRINTF(",");
1755 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1756 DECODE_PRINTF("\n");
1757 TRACE_AND_STEP();
1758 tmp = *srcreg;
1759 *srcreg = *destreg;
1760 *destreg = tmp;
1762 DECODE_CLEAR_SEGOVR();
1763 END_OF_INSTR();
1766 /****************************************************************************
1767 REMARKS:
1768 Handles opcode 0x87
1769 ****************************************************************************/
1770 static void x86emuOp_xchg_word_RM_R(u8 X86EMU_UNUSED(op1))
1772 int mod, rl, rh;
1773 uint destoffset;
1775 START_OF_INSTR();
1776 DECODE_PRINTF("XCHG\t");
1777 FETCH_DECODE_MODRM(mod, rh, rl);
1778 if (mod < 3) {
1779 destoffset = decode_rmXX_address(mod, rl);
1780 DECODE_PRINTF(",");
1781 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1782 u32 *srcreg;
1783 u32 destval,tmp;
1785 destval = fetch_data_long(destoffset);
1786 srcreg = DECODE_RM_LONG_REGISTER(rh);
1787 DECODE_PRINTF("\n");
1788 TRACE_AND_STEP();
1789 tmp = *srcreg;
1790 *srcreg = destval;
1791 destval = tmp;
1792 store_data_long(destoffset, destval);
1793 } else {
1794 u16 *srcreg;
1795 u16 destval,tmp;
1797 destval = fetch_data_word(destoffset);
1798 srcreg = DECODE_RM_WORD_REGISTER(rh);
1799 DECODE_PRINTF("\n");
1800 TRACE_AND_STEP();
1801 tmp = *srcreg;
1802 *srcreg = destval;
1803 destval = tmp;
1804 store_data_word(destoffset, destval);
1806 } else { /* register to register */
1807 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1808 u32 *destreg,*srcreg;
1809 u32 tmp;
1811 destreg = DECODE_RM_LONG_REGISTER(rl);
1812 DECODE_PRINTF(",");
1813 srcreg = DECODE_RM_LONG_REGISTER(rh);
1814 DECODE_PRINTF("\n");
1815 TRACE_AND_STEP();
1816 tmp = *srcreg;
1817 *srcreg = *destreg;
1818 *destreg = tmp;
1819 } else {
1820 u16 *destreg,*srcreg;
1821 u16 tmp;
1823 destreg = DECODE_RM_WORD_REGISTER(rl);
1824 DECODE_PRINTF(",");
1825 srcreg = DECODE_RM_WORD_REGISTER(rh);
1826 DECODE_PRINTF("\n");
1827 TRACE_AND_STEP();
1828 tmp = *srcreg;
1829 *srcreg = *destreg;
1830 *destreg = tmp;
1833 DECODE_CLEAR_SEGOVR();
1834 END_OF_INSTR();
1837 /****************************************************************************
1838 REMARKS:
1839 Handles opcode 0x88
1840 ****************************************************************************/
1841 static void x86emuOp_mov_byte_RM_R(u8 X86EMU_UNUSED(op1))
1843 int mod, rl, rh;
1844 u8 *destreg, *srcreg;
1845 uint destoffset;
1847 START_OF_INSTR();
1848 DECODE_PRINTF("MOV\t");
1849 FETCH_DECODE_MODRM(mod, rh, rl);
1850 if (mod < 3) {
1851 destoffset = decode_rmXX_address(mod, rl);
1852 DECODE_PRINTF(",");
1853 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1854 DECODE_PRINTF("\n");
1855 TRACE_AND_STEP();
1856 store_data_byte(destoffset, *srcreg);
1857 } else { /* register to register */
1858 destreg = DECODE_RM_BYTE_REGISTER(rl);
1859 DECODE_PRINTF(",");
1860 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1861 DECODE_PRINTF("\n");
1862 TRACE_AND_STEP();
1863 *destreg = *srcreg;
1865 DECODE_CLEAR_SEGOVR();
1866 END_OF_INSTR();
1869 /****************************************************************************
1870 REMARKS:
1871 Handles opcode 0x89
1872 ****************************************************************************/
1873 static void x86emuOp_mov_word_RM_R(u8 X86EMU_UNUSED(op1))
1875 int mod, rl, rh;
1876 uint destoffset;
1878 START_OF_INSTR();
1879 DECODE_PRINTF("MOV\t");
1880 FETCH_DECODE_MODRM(mod, rh, rl);
1881 if (mod < 3) {
1882 destoffset = decode_rmXX_address(mod, rl);
1883 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1884 u32 *srcreg;
1886 DECODE_PRINTF(",");
1887 srcreg = DECODE_RM_LONG_REGISTER(rh);
1888 DECODE_PRINTF("\n");
1889 TRACE_AND_STEP();
1890 store_data_long(destoffset, *srcreg);
1891 } else {
1892 u16 *srcreg;
1894 DECODE_PRINTF(",");
1895 srcreg = DECODE_RM_WORD_REGISTER(rh);
1896 DECODE_PRINTF("\n");
1897 TRACE_AND_STEP();
1898 store_data_word(destoffset, *srcreg);
1900 } else { /* register to register */
1901 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1902 u32 *destreg,*srcreg;
1904 destreg = DECODE_RM_LONG_REGISTER(rl);
1905 DECODE_PRINTF(",");
1906 srcreg = DECODE_RM_LONG_REGISTER(rh);
1907 DECODE_PRINTF("\n");
1908 TRACE_AND_STEP();
1909 *destreg = *srcreg;
1910 } else {
1911 u16 *destreg,*srcreg;
1913 destreg = DECODE_RM_WORD_REGISTER(rl);
1914 DECODE_PRINTF(",");
1915 srcreg = DECODE_RM_WORD_REGISTER(rh);
1916 DECODE_PRINTF("\n");
1917 TRACE_AND_STEP();
1918 *destreg = *srcreg;
1921 DECODE_CLEAR_SEGOVR();
1922 END_OF_INSTR();
1925 /****************************************************************************
1926 REMARKS:
1927 Handles opcode 0x8a
1928 ****************************************************************************/
1929 static void x86emuOp_mov_byte_R_RM(u8 X86EMU_UNUSED(op1))
1931 int mod, rl, rh;
1932 u8 *destreg, *srcreg;
1933 uint srcoffset;
1934 u8 srcval;
1936 START_OF_INSTR();
1937 DECODE_PRINTF("MOV\t");
1938 FETCH_DECODE_MODRM(mod, rh, rl);
1939 if (mod < 3) {
1940 destreg = DECODE_RM_BYTE_REGISTER(rh);
1941 DECODE_PRINTF(",");
1942 srcoffset = decode_rmXX_address(mod, rl);
1943 srcval = fetch_data_byte(srcoffset);
1944 DECODE_PRINTF("\n");
1945 TRACE_AND_STEP();
1946 *destreg = srcval;
1947 } else { /* register to register */
1948 destreg = DECODE_RM_BYTE_REGISTER(rh);
1949 DECODE_PRINTF(",");
1950 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1951 DECODE_PRINTF("\n");
1952 TRACE_AND_STEP();
1953 *destreg = *srcreg;
1955 DECODE_CLEAR_SEGOVR();
1956 END_OF_INSTR();
1959 /****************************************************************************
1960 REMARKS:
1961 Handles opcode 0x8b
1962 ****************************************************************************/
1963 static void x86emuOp_mov_word_R_RM(u8 X86EMU_UNUSED(op1))
1965 int mod, rl, rh;
1966 uint srcoffset;
1968 START_OF_INSTR();
1969 DECODE_PRINTF("MOV\t");
1970 FETCH_DECODE_MODRM(mod, rh, rl);
1971 if (mod < 3) {
1972 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1973 u32 *destreg;
1974 u32 srcval;
1976 destreg = DECODE_RM_LONG_REGISTER(rh);
1977 DECODE_PRINTF(",");
1978 srcoffset = decode_rmXX_address(mod, rl);
1979 srcval = fetch_data_long(srcoffset);
1980 DECODE_PRINTF("\n");
1981 TRACE_AND_STEP();
1982 *destreg = srcval;
1983 } else {
1984 u16 *destreg;
1985 u16 srcval;
1987 destreg = DECODE_RM_WORD_REGISTER(rh);
1988 DECODE_PRINTF(",");
1989 srcoffset = decode_rmXX_address(mod, rl);
1990 srcval = fetch_data_word(srcoffset);
1991 DECODE_PRINTF("\n");
1992 TRACE_AND_STEP();
1993 *destreg = srcval;
1995 } else { /* register to register */
1996 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1997 u32 *destreg, *srcreg;
1999 destreg = DECODE_RM_LONG_REGISTER(rh);
2000 DECODE_PRINTF(",");
2001 srcreg = DECODE_RM_LONG_REGISTER(rl);
2002 DECODE_PRINTF("\n");
2003 TRACE_AND_STEP();
2004 *destreg = *srcreg;
2005 } else {
2006 u16 *destreg, *srcreg;
2008 destreg = DECODE_RM_WORD_REGISTER(rh);
2009 DECODE_PRINTF(",");
2010 srcreg = DECODE_RM_WORD_REGISTER(rl);
2011 DECODE_PRINTF("\n");
2012 TRACE_AND_STEP();
2013 *destreg = *srcreg;
2016 DECODE_CLEAR_SEGOVR();
2017 END_OF_INSTR();
2020 /****************************************************************************
2021 REMARKS:
2022 Handles opcode 0x8c
2023 ****************************************************************************/
2024 static void x86emuOp_mov_word_RM_SR(u8 X86EMU_UNUSED(op1))
2026 int mod, rl, rh;
2027 u16 *destreg, *srcreg;
2028 uint destoffset;
2029 u16 destval;
2031 START_OF_INSTR();
2032 DECODE_PRINTF("MOV\t");
2033 FETCH_DECODE_MODRM(mod, rh, rl);
2034 if (mod < 3) {
2035 destoffset = decode_rmXX_address(mod, rl);
2036 DECODE_PRINTF(",");
2037 srcreg = decode_rm_seg_register(rh);
2038 DECODE_PRINTF("\n");
2039 TRACE_AND_STEP();
2040 destval = *srcreg;
2041 store_data_word(destoffset, destval);
2042 } else { /* register to register */
2043 destreg = DECODE_RM_WORD_REGISTER(rl);
2044 DECODE_PRINTF(",");
2045 srcreg = decode_rm_seg_register(rh);
2046 DECODE_PRINTF("\n");
2047 TRACE_AND_STEP();
2048 *destreg = *srcreg;
2050 DECODE_CLEAR_SEGOVR();
2051 END_OF_INSTR();
2054 /****************************************************************************
2055 REMARKS:
2056 Handles opcode 0x8d
2057 ****************************************************************************/
2058 static void x86emuOp_lea_word_R_M(u8 X86EMU_UNUSED(op1))
2060 int mod, rl, rh;
2061 uint destoffset;
2063 START_OF_INSTR();
2064 DECODE_PRINTF("LEA\t");
2065 FETCH_DECODE_MODRM(mod, rh, rl);
2066 if (mod < 3) {
2067 if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
2068 u32 *srcreg = DECODE_RM_LONG_REGISTER(rh);
2069 DECODE_PRINTF(",");
2070 destoffset = decode_rmXX_address(mod, rl);
2071 DECODE_PRINTF("\n");
2072 TRACE_AND_STEP();
2073 *srcreg = (u32)destoffset;
2074 } else {
2075 u16 *srcreg = DECODE_RM_WORD_REGISTER(rh);
2076 DECODE_PRINTF(",");
2077 destoffset = decode_rmXX_address(mod, rl);
2078 DECODE_PRINTF("\n");
2079 TRACE_AND_STEP();
2080 *srcreg = (u16)destoffset;
2083 /* else { undefined. Do nothing. } */
2084 DECODE_CLEAR_SEGOVR();
2085 END_OF_INSTR();
2088 /****************************************************************************
2089 REMARKS:
2090 Handles opcode 0x8e
2091 ****************************************************************************/
2092 static void x86emuOp_mov_word_SR_RM(u8 X86EMU_UNUSED(op1))
2094 int mod, rl, rh;
2095 u16 *destreg, *srcreg;
2096 uint srcoffset;
2097 u16 srcval;
2099 START_OF_INSTR();
2100 DECODE_PRINTF("MOV\t");
2101 FETCH_DECODE_MODRM(mod, rh, rl);
2102 if (mod < 3) {
2103 destreg = decode_rm_seg_register(rh);
2104 DECODE_PRINTF(",");
2105 srcoffset = decode_rmXX_address(mod, rl);
2106 srcval = fetch_data_word(srcoffset);
2107 DECODE_PRINTF("\n");
2108 TRACE_AND_STEP();
2109 *destreg = srcval;
2110 } else { /* register to register */
2111 destreg = decode_rm_seg_register(rh);
2112 DECODE_PRINTF(",");
2113 srcreg = DECODE_RM_WORD_REGISTER(rl);
2114 DECODE_PRINTF("\n");
2115 TRACE_AND_STEP();
2116 *destreg = *srcreg;
2119 * Clean up, and reset all the R_xSP pointers to the correct
2120 * locations. This is about 3x too much overhead (doing all the
2121 * segreg ptrs when only one is needed, but this instruction
2122 * *cannot* be that common, and this isn't too much work anyway.
2124 DECODE_CLEAR_SEGOVR();
2125 END_OF_INSTR();
2128 /****************************************************************************
2129 REMARKS:
2130 Handles opcode 0x8f
2131 ****************************************************************************/
2132 static void x86emuOp_pop_RM(u8 X86EMU_UNUSED(op1))
2134 int mod, rl, rh;
2135 uint destoffset;
2137 START_OF_INSTR();
2138 DECODE_PRINTF("POP\t");
2139 FETCH_DECODE_MODRM(mod, rh, rl);
2140 if (rh != 0) {
2141 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
2142 HALT_SYS();
2144 if (mod < 3) {
2145 destoffset = decode_rmXX_address(mod, rl);
2146 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2147 u32 destval;
2149 DECODE_PRINTF("\n");
2150 TRACE_AND_STEP();
2151 destval = pop_long();
2152 store_data_long(destoffset, destval);
2153 } else {
2154 u16 destval;
2156 DECODE_PRINTF("\n");
2157 TRACE_AND_STEP();
2158 destval = pop_word();
2159 store_data_word(destoffset, destval);
2161 } else { /* register to register */
2162 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2163 u32 *destreg;
2165 destreg = DECODE_RM_LONG_REGISTER(rl);
2166 DECODE_PRINTF("\n");
2167 TRACE_AND_STEP();
2168 *destreg = pop_long();
2169 } else {
2170 u16 *destreg;
2172 destreg = DECODE_RM_WORD_REGISTER(rl);
2173 DECODE_PRINTF("\n");
2174 TRACE_AND_STEP();
2175 *destreg = pop_word();
2178 DECODE_CLEAR_SEGOVR();
2179 END_OF_INSTR();
2182 /****************************************************************************
2183 REMARKS:
2184 Handles opcode 0x90
2185 ****************************************************************************/
2186 static void x86emuOp_nop(u8 X86EMU_UNUSED(op1))
2188 START_OF_INSTR();
2189 DECODE_PRINTF("NOP\n");
2190 TRACE_AND_STEP();
2191 DECODE_CLEAR_SEGOVR();
2192 END_OF_INSTR();
2195 /****************************************************************************
2196 REMARKS:
2197 Handles opcode 0x91-0x97
2198 ****************************************************************************/
2199 static void x86emuOp_xchg_word_AX_register(u8 X86EMU_UNUSED(op1))
2201 u32 tmp;
2203 op1 &= 0x7;
2205 START_OF_INSTR();
2207 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2208 u32 *reg32;
2209 DECODE_PRINTF("XCHG\tEAX,");
2210 reg32 = DECODE_RM_LONG_REGISTER(op1);
2211 DECODE_PRINTF("\n");
2212 TRACE_AND_STEP();
2213 tmp = M.x86.R_EAX;
2214 M.x86.R_EAX = *reg32;
2215 *reg32 = tmp;
2216 } else {
2217 u16 *reg16;
2218 DECODE_PRINTF("XCHG\tAX,");
2219 reg16 = DECODE_RM_WORD_REGISTER(op1);
2220 DECODE_PRINTF("\n");
2221 TRACE_AND_STEP();
2222 tmp = M.x86.R_AX;
2223 M.x86.R_AX = *reg16;
2224 *reg16 = (u16)tmp;
2226 DECODE_CLEAR_SEGOVR();
2227 END_OF_INSTR();
2230 /****************************************************************************
2231 REMARKS:
2232 Handles opcode 0x98
2233 ****************************************************************************/
2234 static void x86emuOp_cbw(u8 X86EMU_UNUSED(op1))
2236 START_OF_INSTR();
2237 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2238 DECODE_PRINTF("CWDE\n");
2239 } else {
2240 DECODE_PRINTF("CBW\n");
2242 TRACE_AND_STEP();
2243 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2244 if (M.x86.R_AX & 0x8000) {
2245 M.x86.R_EAX |= 0xffff0000;
2246 } else {
2247 M.x86.R_EAX &= 0x0000ffff;
2249 } else {
2250 if (M.x86.R_AL & 0x80) {
2251 M.x86.R_AH = 0xff;
2252 } else {
2253 M.x86.R_AH = 0x0;
2256 DECODE_CLEAR_SEGOVR();
2257 END_OF_INSTR();
2260 /****************************************************************************
2261 REMARKS:
2262 Handles opcode 0x99
2263 ****************************************************************************/
2264 static void x86emuOp_cwd(u8 X86EMU_UNUSED(op1))
2266 START_OF_INSTR();
2267 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2268 DECODE_PRINTF("CDQ\n");
2269 } else {
2270 DECODE_PRINTF("CWD\n");
2272 DECODE_PRINTF("CWD\n");
2273 TRACE_AND_STEP();
2274 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2275 if (M.x86.R_EAX & 0x80000000) {
2276 M.x86.R_EDX = 0xffffffff;
2277 } else {
2278 M.x86.R_EDX = 0x0;
2280 } else {
2281 if (M.x86.R_AX & 0x8000) {
2282 M.x86.R_DX = 0xffff;
2283 } else {
2284 M.x86.R_DX = 0x0;
2287 DECODE_CLEAR_SEGOVR();
2288 END_OF_INSTR();
2291 /****************************************************************************
2292 REMARKS:
2293 Handles opcode 0x9a
2294 ****************************************************************************/
2295 static void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1))
2297 u32 farseg, faroff;
2299 START_OF_INSTR();
2300 DECODE_PRINTF("CALL\t");
2301 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2302 faroff = fetch_long_imm();
2303 farseg = fetch_word_imm();
2304 } else {
2305 faroff = fetch_word_imm();
2306 farseg = fetch_word_imm();
2308 DECODE_PRINTF2("%04x:", farseg);
2309 DECODE_PRINTF2("%04x\n", faroff);
2310 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, farseg, faroff, "FAR ");
2312 /* XXX
2314 * Hooked interrupt vectors calling into our "BIOS" will cause
2315 * problems unless all intersegment stuff is checked for BIOS
2316 * access. Check needed here. For moment, let it alone.
2318 TRACE_AND_STEP();
2319 push_word(M.x86.R_CS);
2320 M.x86.R_CS = farseg;
2321 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2322 push_long(M.x86.R_EIP);
2323 } else {
2324 push_word(M.x86.R_IP);
2326 M.x86.R_EIP = faroff & 0xffff;
2327 DECODE_CLEAR_SEGOVR();
2328 END_OF_INSTR();
2331 /****************************************************************************
2332 REMARKS:
2333 Handles opcode 0x9b
2334 ****************************************************************************/
2335 static void x86emuOp_wait(u8 X86EMU_UNUSED(op1))
2337 START_OF_INSTR();
2338 DECODE_PRINTF("WAIT");
2339 TRACE_AND_STEP();
2340 /* NADA. */
2341 DECODE_CLEAR_SEGOVR();
2342 END_OF_INSTR();
2345 /****************************************************************************
2346 REMARKS:
2347 Handles opcode 0x9c
2348 ****************************************************************************/
2349 static void x86emuOp_pushf_word(u8 X86EMU_UNUSED(op1))
2351 u32 flags;
2353 START_OF_INSTR();
2354 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2355 DECODE_PRINTF("PUSHFD\n");
2356 } else {
2357 DECODE_PRINTF("PUSHF\n");
2359 TRACE_AND_STEP();
2361 /* clear out *all* bits not representing flags, and turn on real bits */
2362 flags = (M.x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
2363 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2364 push_long(flags);
2365 } else {
2366 push_word((u16)flags);
2368 DECODE_CLEAR_SEGOVR();
2369 END_OF_INSTR();
2372 /****************************************************************************
2373 REMARKS:
2374 Handles opcode 0x9d
2375 ****************************************************************************/
2376 static void x86emuOp_popf_word(u8 X86EMU_UNUSED(op1))
2378 START_OF_INSTR();
2379 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2380 DECODE_PRINTF("POPFD\n");
2381 } else {
2382 DECODE_PRINTF("POPF\n");
2384 TRACE_AND_STEP();
2385 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2386 M.x86.R_EFLG = pop_long();
2387 } else {
2388 M.x86.R_FLG = pop_word();
2390 DECODE_CLEAR_SEGOVR();
2391 END_OF_INSTR();
2394 /****************************************************************************
2395 REMARKS:
2396 Handles opcode 0x9e
2397 ****************************************************************************/
2398 static void x86emuOp_sahf(u8 X86EMU_UNUSED(op1))
2400 START_OF_INSTR();
2401 DECODE_PRINTF("SAHF\n");
2402 TRACE_AND_STEP();
2403 /* clear the lower bits of the flag register */
2404 M.x86.R_FLG &= 0xffffff00;
2405 /* or in the AH register into the flags register */
2406 M.x86.R_FLG |= M.x86.R_AH;
2407 DECODE_CLEAR_SEGOVR();
2408 END_OF_INSTR();
2411 /****************************************************************************
2412 REMARKS:
2413 Handles opcode 0x9f
2414 ****************************************************************************/
2415 static void x86emuOp_lahf(u8 X86EMU_UNUSED(op1))
2417 START_OF_INSTR();
2418 DECODE_PRINTF("LAHF\n");
2419 TRACE_AND_STEP();
2420 M.x86.R_AH = (u8)(M.x86.R_FLG & 0xff);
2421 /*undocumented TC++ behavior??? Nope. It's documented, but
2422 you have too look real hard to notice it. */
2423 M.x86.R_AH |= 0x2;
2424 DECODE_CLEAR_SEGOVR();
2425 END_OF_INSTR();
2428 /****************************************************************************
2429 REMARKS:
2430 Handles opcode 0xa0
2431 ****************************************************************************/
2432 static void x86emuOp_mov_AL_M_IMM(u8 X86EMU_UNUSED(op1))
2434 u16 offset;
2436 START_OF_INSTR();
2437 DECODE_PRINTF("MOV\tAL,");
2438 offset = fetch_word_imm();
2439 DECODE_PRINTF2("[%04x]\n", offset);
2440 TRACE_AND_STEP();
2441 M.x86.R_AL = fetch_data_byte(offset);
2442 DECODE_CLEAR_SEGOVR();
2443 END_OF_INSTR();
2446 /****************************************************************************
2447 REMARKS:
2448 Handles opcode 0xa1
2449 ****************************************************************************/
2450 static void x86emuOp_mov_AX_M_IMM(u8 X86EMU_UNUSED(op1))
2452 u16 offset;
2454 START_OF_INSTR();
2455 offset = fetch_word_imm();
2456 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2457 DECODE_PRINTF2("MOV\tEAX,[%04x]\n", offset);
2458 } else {
2459 DECODE_PRINTF2("MOV\tAX,[%04x]\n", offset);
2461 TRACE_AND_STEP();
2462 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2463 M.x86.R_EAX = fetch_data_long(offset);
2464 } else {
2465 M.x86.R_AX = fetch_data_word(offset);
2467 DECODE_CLEAR_SEGOVR();
2468 END_OF_INSTR();
2471 /****************************************************************************
2472 REMARKS:
2473 Handles opcode 0xa2
2474 ****************************************************************************/
2475 static void x86emuOp_mov_M_AL_IMM(u8 X86EMU_UNUSED(op1))
2477 u16 offset;
2479 START_OF_INSTR();
2480 DECODE_PRINTF("MOV\t");
2481 offset = fetch_word_imm();
2482 DECODE_PRINTF2("[%04x],AL\n", offset);
2483 TRACE_AND_STEP();
2484 store_data_byte(offset, M.x86.R_AL);
2485 DECODE_CLEAR_SEGOVR();
2486 END_OF_INSTR();
2489 /****************************************************************************
2490 REMARKS:
2491 Handles opcode 0xa3
2492 ****************************************************************************/
2493 static void x86emuOp_mov_M_AX_IMM(u8 X86EMU_UNUSED(op1))
2495 u16 offset;
2497 START_OF_INSTR();
2498 offset = fetch_word_imm();
2499 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2500 DECODE_PRINTF2("MOV\t[%04x],EAX\n", offset);
2501 } else {
2502 DECODE_PRINTF2("MOV\t[%04x],AX\n", offset);
2504 TRACE_AND_STEP();
2505 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2506 store_data_long(offset, M.x86.R_EAX);
2507 } else {
2508 store_data_word(offset, M.x86.R_AX);
2510 DECODE_CLEAR_SEGOVR();
2511 END_OF_INSTR();
2514 /****************************************************************************
2515 REMARKS:
2516 Handles opcode 0xa4
2517 ****************************************************************************/
2518 static void x86emuOp_movs_byte(u8 X86EMU_UNUSED(op1))
2520 u8 val;
2521 u32 count;
2522 int inc;
2524 START_OF_INSTR();
2525 DECODE_PRINTF("MOVS\tBYTE\n");
2526 if (ACCESS_FLAG(F_DF)) /* down */
2527 inc = -1;
2528 else
2529 inc = 1;
2530 TRACE_AND_STEP();
2531 count = 1;
2532 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2533 /* don't care whether REPE or REPNE */
2534 /* move them until (E)CX is ZERO. */
2535 count = (M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX;
2536 M.x86.R_CX = 0;
2537 if (M.x86.mode & SYSMODE_32BIT_REP)
2538 M.x86.R_ECX = 0;
2539 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2541 while (count--) {
2542 val = fetch_data_byte(M.x86.R_SI);
2543 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, val);
2544 M.x86.R_SI += inc;
2545 M.x86.R_DI += inc;
2546 if (M.x86.intr & INTR_HALTED)
2547 break;
2549 DECODE_CLEAR_SEGOVR();
2550 END_OF_INSTR();
2553 /****************************************************************************
2554 REMARKS:
2555 Handles opcode 0xa5
2556 ****************************************************************************/
2557 static void x86emuOp_movs_word(u8 X86EMU_UNUSED(op1))
2559 u32 val;
2560 int inc;
2561 u32 count;
2563 START_OF_INSTR();
2564 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2565 DECODE_PRINTF("MOVS\tDWORD\n");
2566 if (ACCESS_FLAG(F_DF)) /* down */
2567 inc = -4;
2568 else
2569 inc = 4;
2570 } else {
2571 DECODE_PRINTF("MOVS\tWORD\n");
2572 if (ACCESS_FLAG(F_DF)) /* down */
2573 inc = -2;
2574 else
2575 inc = 2;
2577 TRACE_AND_STEP();
2578 count = 1;
2579 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2580 /* don't care whether REPE or REPNE */
2581 /* move them until (E)CX is ZERO. */
2582 count = (M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX;
2583 M.x86.R_CX = 0;
2584 if (M.x86.mode & SYSMODE_32BIT_REP)
2585 M.x86.R_ECX = 0;
2586 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2588 while (count--) {
2589 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2590 val = fetch_data_long(M.x86.R_SI);
2591 store_data_long_abs(M.x86.R_ES, M.x86.R_DI, val);
2592 } else {
2593 val = fetch_data_word(M.x86.R_SI);
2594 store_data_word_abs(M.x86.R_ES, M.x86.R_DI, (u16)val);
2596 M.x86.R_SI += inc;
2597 M.x86.R_DI += inc;
2598 if (M.x86.intr & INTR_HALTED)
2599 break;
2601 DECODE_CLEAR_SEGOVR();
2602 END_OF_INSTR();
2605 /****************************************************************************
2606 REMARKS:
2607 Handles opcode 0xa6
2608 ****************************************************************************/
2609 static void x86emuOp_cmps_byte(u8 X86EMU_UNUSED(op1))
2611 s8 val1, val2;
2612 int inc;
2614 START_OF_INSTR();
2615 DECODE_PRINTF("CMPS\tBYTE\n");
2616 TRACE_AND_STEP();
2617 if (ACCESS_FLAG(F_DF)) /* down */
2618 inc = -1;
2619 else
2620 inc = 1;
2622 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2623 /* REPE */
2624 /* move them until (E)CX is ZERO. */
2625 while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
2626 val1 = fetch_data_byte(M.x86.R_SI);
2627 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2628 cmp_byte(val1, val2);
2629 if (M.x86.mode & SYSMODE_32BIT_REP)
2630 M.x86.R_ECX -= 1;
2631 else
2632 M.x86.R_CX -= 1;
2633 M.x86.R_SI += inc;
2634 M.x86.R_DI += inc;
2635 if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && (ACCESS_FLAG(F_ZF) == 0) ) break;
2636 if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2637 if (M.x86.intr & INTR_HALTED)
2638 break;
2640 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2641 } else {
2642 val1 = fetch_data_byte(M.x86.R_SI);
2643 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2644 cmp_byte(val1, val2);
2645 M.x86.R_SI += inc;
2646 M.x86.R_DI += inc;
2648 DECODE_CLEAR_SEGOVR();
2649 END_OF_INSTR();
2652 /****************************************************************************
2653 REMARKS:
2654 Handles opcode 0xa7
2655 ****************************************************************************/
2656 static void x86emuOp_cmps_word(u8 X86EMU_UNUSED(op1))
2658 u32 val1,val2;
2659 int inc;
2661 START_OF_INSTR();
2662 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2663 DECODE_PRINTF("CMPS\tDWORD\n");
2664 inc = 4;
2665 } else {
2666 DECODE_PRINTF("CMPS\tWORD\n");
2667 inc = 2;
2669 if (ACCESS_FLAG(F_DF)) /* down */
2670 inc = -inc;
2672 TRACE_AND_STEP();
2673 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2674 /* REPE */
2675 /* move them until (E)CX is ZERO. */
2676 while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
2677 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2678 val1 = fetch_data_long(M.x86.R_SI);
2679 val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2680 cmp_long(val1, val2);
2681 } else {
2682 val1 = fetch_data_word(M.x86.R_SI);
2683 val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2684 cmp_word((u16)val1, (u16)val2);
2686 if (M.x86.mode & SYSMODE_32BIT_REP)
2687 M.x86.R_ECX -= 1;
2688 else
2689 M.x86.R_CX -= 1;
2690 M.x86.R_SI += inc;
2691 M.x86.R_DI += inc;
2692 if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && ACCESS_FLAG(F_ZF) == 0 ) break;
2693 if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2694 if (M.x86.intr & INTR_HALTED)
2695 break;
2697 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2698 } else {
2699 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2700 val1 = fetch_data_long(M.x86.R_SI);
2701 val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2702 cmp_long(val1, val2);
2703 } else {
2704 val1 = fetch_data_word(M.x86.R_SI);
2705 val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2706 cmp_word((u16)val1, (u16)val2);
2708 M.x86.R_SI += inc;
2709 M.x86.R_DI += inc;
2711 DECODE_CLEAR_SEGOVR();
2712 END_OF_INSTR();
2715 /****************************************************************************
2716 REMARKS:
2717 Handles opcode 0xa8
2718 ****************************************************************************/
2719 static void x86emuOp_test_AL_IMM(u8 X86EMU_UNUSED(op1))
2721 int imm;
2723 START_OF_INSTR();
2724 DECODE_PRINTF("TEST\tAL,");
2725 imm = fetch_byte_imm();
2726 DECODE_PRINTF2("%04x\n", imm);
2727 TRACE_AND_STEP();
2728 test_byte(M.x86.R_AL, (u8)imm);
2729 DECODE_CLEAR_SEGOVR();
2730 END_OF_INSTR();
2733 /****************************************************************************
2734 REMARKS:
2735 Handles opcode 0xa9
2736 ****************************************************************************/
2737 static void x86emuOp_test_AX_IMM(u8 X86EMU_UNUSED(op1))
2739 u32 srcval;
2741 START_OF_INSTR();
2742 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2743 DECODE_PRINTF("TEST\tEAX,");
2744 srcval = fetch_long_imm();
2745 } else {
2746 DECODE_PRINTF("TEST\tAX,");
2747 srcval = fetch_word_imm();
2749 DECODE_PRINTF2("%x\n", srcval);
2750 TRACE_AND_STEP();
2751 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2752 test_long(M.x86.R_EAX, srcval);
2753 } else {
2754 test_word(M.x86.R_AX, (u16)srcval);
2756 DECODE_CLEAR_SEGOVR();
2757 END_OF_INSTR();
2760 /****************************************************************************
2761 REMARKS:
2762 Handles opcode 0xaa
2763 ****************************************************************************/
2764 static void x86emuOp_stos_byte(u8 X86EMU_UNUSED(op1))
2766 int inc;
2768 START_OF_INSTR();
2769 DECODE_PRINTF("STOS\tBYTE\n");
2770 if (ACCESS_FLAG(F_DF)) /* down */
2771 inc = -1;
2772 else
2773 inc = 1;
2774 TRACE_AND_STEP();
2775 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2776 /* don't care whether REPE or REPNE */
2777 /* move them until (E)CX is ZERO. */
2778 while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
2779 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
2780 if (M.x86.mode & SYSMODE_32BIT_REP)
2781 M.x86.R_ECX -= 1;
2782 else
2783 M.x86.R_CX -= 1;
2784 M.x86.R_DI += inc;
2785 if (M.x86.intr & INTR_HALTED)
2786 break;
2788 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2789 } else {
2790 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
2791 M.x86.R_DI += inc;
2793 DECODE_CLEAR_SEGOVR();
2794 END_OF_INSTR();
2797 /****************************************************************************
2798 REMARKS:
2799 Handles opcode 0xab
2800 ****************************************************************************/
2801 static void x86emuOp_stos_word(u8 X86EMU_UNUSED(op1))
2803 int inc;
2804 u32 count;
2806 START_OF_INSTR();
2807 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2808 DECODE_PRINTF("STOS\tDWORD\n");
2809 if (ACCESS_FLAG(F_DF)) /* down */
2810 inc = -4;
2811 else
2812 inc = 4;
2813 } else {
2814 DECODE_PRINTF("STOS\tWORD\n");
2815 if (ACCESS_FLAG(F_DF)) /* down */
2816 inc = -2;
2817 else
2818 inc = 2;
2820 TRACE_AND_STEP();
2821 count = 1;
2822 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2823 /* don't care whether REPE or REPNE */
2824 /* move them until (E)CX is ZERO. */
2825 count = (M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX;
2826 M.x86.R_CX = 0;
2827 if (M.x86.mode & SYSMODE_32BIT_REP)
2828 M.x86.R_ECX = 0;
2829 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2831 while (count--) {
2832 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2833 store_data_long_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_EAX);
2834 } else {
2835 store_data_word_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AX);
2837 M.x86.R_DI += inc;
2838 if (M.x86.intr & INTR_HALTED)
2839 break;
2841 DECODE_CLEAR_SEGOVR();
2842 END_OF_INSTR();
2845 /****************************************************************************
2846 REMARKS:
2847 Handles opcode 0xac
2848 ****************************************************************************/
2849 static void x86emuOp_lods_byte(u8 X86EMU_UNUSED(op1))
2851 int inc;
2853 START_OF_INSTR();
2854 DECODE_PRINTF("LODS\tBYTE\n");
2855 TRACE_AND_STEP();
2856 if (ACCESS_FLAG(F_DF)) /* down */
2857 inc = -1;
2858 else
2859 inc = 1;
2860 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2861 /* don't care whether REPE or REPNE */
2862 /* move them until (E)CX is ZERO. */
2863 while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
2864 M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
2865 if (M.x86.mode & SYSMODE_32BIT_REP)
2866 M.x86.R_ECX -= 1;
2867 else
2868 M.x86.R_CX -= 1;
2869 M.x86.R_SI += inc;
2870 if (M.x86.intr & INTR_HALTED)
2871 break;
2873 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2874 } else {
2875 M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
2876 M.x86.R_SI += inc;
2878 DECODE_CLEAR_SEGOVR();
2879 END_OF_INSTR();
2882 /****************************************************************************
2883 REMARKS:
2884 Handles opcode 0xad
2885 ****************************************************************************/
2886 static void x86emuOp_lods_word(u8 X86EMU_UNUSED(op1))
2888 int inc;
2889 u32 count;
2891 START_OF_INSTR();
2892 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2893 DECODE_PRINTF("LODS\tDWORD\n");
2894 if (ACCESS_FLAG(F_DF)) /* down */
2895 inc = -4;
2896 else
2897 inc = 4;
2898 } else {
2899 DECODE_PRINTF("LODS\tWORD\n");
2900 if (ACCESS_FLAG(F_DF)) /* down */
2901 inc = -2;
2902 else
2903 inc = 2;
2905 TRACE_AND_STEP();
2906 count = 1;
2907 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2908 /* don't care whether REPE or REPNE */
2909 /* move them until (E)CX is ZERO. */
2910 count = (M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX;
2911 M.x86.R_CX = 0;
2912 if (M.x86.mode & SYSMODE_32BIT_REP)
2913 M.x86.R_ECX = 0;
2914 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2916 while (count--) {
2917 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2918 M.x86.R_EAX = fetch_data_long(M.x86.R_SI);
2919 } else {
2920 M.x86.R_AX = fetch_data_word(M.x86.R_SI);
2922 M.x86.R_SI += inc;
2923 if (M.x86.intr & INTR_HALTED)
2924 break;
2926 DECODE_CLEAR_SEGOVR();
2927 END_OF_INSTR();
2930 /****************************************************************************
2931 REMARKS:
2932 Handles opcode 0xae
2933 ****************************************************************************/
2934 static void x86emuOp_scas_byte(u8 X86EMU_UNUSED(op1))
2936 s8 val2;
2937 int inc;
2939 START_OF_INSTR();
2940 DECODE_PRINTF("SCAS\tBYTE\n");
2941 TRACE_AND_STEP();
2942 if (ACCESS_FLAG(F_DF)) /* down */
2943 inc = -1;
2944 else
2945 inc = 1;
2946 if (M.x86.mode & SYSMODE_PREFIX_REPE) {
2947 /* REPE */
2948 /* move them until (E)CX is ZERO. */
2949 while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
2950 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2951 cmp_byte(M.x86.R_AL, val2);
2952 if (M.x86.mode & SYSMODE_32BIT_REP)
2953 M.x86.R_ECX -= 1;
2954 else
2955 M.x86.R_CX -= 1;
2956 M.x86.R_DI += inc;
2957 if (ACCESS_FLAG(F_ZF) == 0)
2958 break;
2959 if (M.x86.intr & INTR_HALTED)
2960 break;
2962 M.x86.mode &= ~SYSMODE_PREFIX_REPE;
2963 } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
2964 /* REPNE */
2965 /* move them until (E)CX is ZERO. */
2966 while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
2967 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2968 cmp_byte(M.x86.R_AL, val2);
2969 if (M.x86.mode & SYSMODE_32BIT_REP)
2970 M.x86.R_ECX -= 1;
2971 else
2972 M.x86.R_CX -= 1;
2973 M.x86.R_DI += inc;
2974 if (ACCESS_FLAG(F_ZF))
2975 break; /* zero flag set means equal */
2976 if (M.x86.intr & INTR_HALTED)
2977 break;
2979 M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
2980 } else {
2981 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2982 cmp_byte(M.x86.R_AL, val2);
2983 M.x86.R_DI += inc;
2985 DECODE_CLEAR_SEGOVR();
2986 END_OF_INSTR();
2989 /****************************************************************************
2990 REMARKS:
2991 Handles opcode 0xaf
2992 ****************************************************************************/
2993 static void x86emuOp_scas_word(u8 X86EMU_UNUSED(op1))
2995 int inc;
2996 u32 val;
2998 START_OF_INSTR();
2999 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3000 DECODE_PRINTF("SCAS\tDWORD\n");
3001 if (ACCESS_FLAG(F_DF)) /* down */
3002 inc = -4;
3003 else
3004 inc = 4;
3005 } else {
3006 DECODE_PRINTF("SCAS\tWORD\n");
3007 if (ACCESS_FLAG(F_DF)) /* down */
3008 inc = -2;
3009 else
3010 inc = 2;
3012 TRACE_AND_STEP();
3013 if (M.x86.mode & SYSMODE_PREFIX_REPE) {
3014 /* REPE */
3015 /* move them until (E)CX is ZERO. */
3016 while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
3017 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3018 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
3019 cmp_long(M.x86.R_EAX, val);
3020 } else {
3021 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
3022 cmp_word(M.x86.R_AX, (u16)val);
3024 if (M.x86.mode & SYSMODE_32BIT_REP)
3025 M.x86.R_ECX -= 1;
3026 else
3027 M.x86.R_CX -= 1;
3028 M.x86.R_DI += inc;
3029 if (ACCESS_FLAG(F_ZF) == 0)
3030 break;
3031 if (M.x86.intr & INTR_HALTED)
3032 break;
3034 M.x86.mode &= ~SYSMODE_PREFIX_REPE;
3035 } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
3036 /* REPNE */
3037 /* move them until (E)CX is ZERO. */
3038 while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
3039 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3040 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
3041 cmp_long(M.x86.R_EAX, val);
3042 } else {
3043 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
3044 cmp_word(M.x86.R_AX, (u16)val);
3046 if (M.x86.mode & SYSMODE_32BIT_REP)
3047 M.x86.R_ECX -= 1;
3048 else
3049 M.x86.R_CX -= 1;
3050 M.x86.R_DI += inc;
3051 if (ACCESS_FLAG(F_ZF))
3052 break; /* zero flag set means equal */
3053 if (M.x86.intr & INTR_HALTED)
3054 break;
3056 M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
3057 } else {
3058 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3059 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
3060 cmp_long(M.x86.R_EAX, val);
3061 } else {
3062 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
3063 cmp_word(M.x86.R_AX, (u16)val);
3065 M.x86.R_DI += inc;
3067 DECODE_CLEAR_SEGOVR();
3068 END_OF_INSTR();
3071 /****************************************************************************
3072 REMARKS:
3073 Handles opcode 0xb0 - 0xb7
3074 ****************************************************************************/
3075 static void x86emuOp_mov_byte_register_IMM(u8 op1)
3077 u8 imm, *ptr;
3079 START_OF_INSTR();
3080 DECODE_PRINTF("MOV\t");
3081 ptr = DECODE_RM_BYTE_REGISTER(op1 & 0x7);
3082 DECODE_PRINTF(",");
3083 imm = fetch_byte_imm();
3084 DECODE_PRINTF2("%x\n", imm);
3085 TRACE_AND_STEP();
3086 *ptr = imm;
3087 DECODE_CLEAR_SEGOVR();
3088 END_OF_INSTR();
3091 /****************************************************************************
3092 REMARKS:
3093 Handles opcode 0xb8 - 0xbf
3094 ****************************************************************************/
3095 static void x86emuOp_mov_word_register_IMM(u8 X86EMU_UNUSED(op1))
3097 u32 srcval;
3099 op1 &= 0x7;
3101 START_OF_INSTR();
3102 DECODE_PRINTF("MOV\t");
3103 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3104 u32 *reg32;
3105 reg32 = DECODE_RM_LONG_REGISTER(op1);
3106 srcval = fetch_long_imm();
3107 DECODE_PRINTF2(",%x\n", srcval);
3108 TRACE_AND_STEP();
3109 *reg32 = srcval;
3110 } else {
3111 u16 *reg16;
3112 reg16 = DECODE_RM_WORD_REGISTER(op1);
3113 srcval = fetch_word_imm();
3114 DECODE_PRINTF2(",%x\n", srcval);
3115 TRACE_AND_STEP();
3116 *reg16 = (u16)srcval;
3118 DECODE_CLEAR_SEGOVR();
3119 END_OF_INSTR();
3122 /****************************************************************************
3123 REMARKS:
3124 Handles opcode 0xc0
3125 ****************************************************************************/
3126 static void x86emuOp_opcC0_byte_RM_MEM(u8 X86EMU_UNUSED(op1))
3128 int mod, rl, rh;
3129 u8 *destreg;
3130 uint destoffset;
3131 u8 destval;
3132 u8 amt;
3135 * Yet another weirdo special case instruction format. Part of
3136 * the opcode held below in "RH". Doubly nested case would
3137 * result, except that the decoded instruction
3139 START_OF_INSTR();
3140 FETCH_DECODE_MODRM(mod, rh, rl);
3141 #ifdef DEBUG
3142 if (DEBUG_DECODE()) {
3143 /* XXX DECODE_PRINTF may be changed to something more
3144 general, so that it is important to leave the strings
3145 in the same format, even though the result is that the
3146 above test is done twice. */
3148 switch (rh) {
3149 case 0:
3150 DECODE_PRINTF("ROL\t");
3151 break;
3152 case 1:
3153 DECODE_PRINTF("ROR\t");
3154 break;
3155 case 2:
3156 DECODE_PRINTF("RCL\t");
3157 break;
3158 case 3:
3159 DECODE_PRINTF("RCR\t");
3160 break;
3161 case 4:
3162 DECODE_PRINTF("SHL\t");
3163 break;
3164 case 5:
3165 DECODE_PRINTF("SHR\t");
3166 break;
3167 case 6:
3168 DECODE_PRINTF("SAL\t");
3169 break;
3170 case 7:
3171 DECODE_PRINTF("SAR\t");
3172 break;
3175 #endif
3176 /* know operation, decode the mod byte to find the addressing
3177 mode. */
3178 if (mod < 3) {
3179 DECODE_PRINTF("BYTE PTR ");
3180 destoffset = decode_rmXX_address(mod, rl);
3181 amt = fetch_byte_imm();
3182 DECODE_PRINTF2(",%x\n", amt);
3183 destval = fetch_data_byte(destoffset);
3184 TRACE_AND_STEP();
3185 destval = (*opcD0_byte_operation[rh]) (destval, amt);
3186 store_data_byte(destoffset, destval);
3187 } else { /* register to register */
3188 destreg = DECODE_RM_BYTE_REGISTER(rl);
3189 amt = fetch_byte_imm();
3190 DECODE_PRINTF2(",%x\n", amt);
3191 TRACE_AND_STEP();
3192 destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3193 *destreg = destval;
3195 DECODE_CLEAR_SEGOVR();
3196 END_OF_INSTR();
3199 /****************************************************************************
3200 REMARKS:
3201 Handles opcode 0xc1
3202 ****************************************************************************/
3203 static void x86emuOp_opcC1_word_RM_MEM(u8 X86EMU_UNUSED(op1))
3205 int mod, rl, rh;
3206 uint destoffset;
3207 u8 amt;
3210 * Yet another weirdo special case instruction format. Part of
3211 * the opcode held below in "RH". Doubly nested case would
3212 * result, except that the decoded instruction
3214 START_OF_INSTR();
3215 FETCH_DECODE_MODRM(mod, rh, rl);
3216 #ifdef DEBUG
3217 if (DEBUG_DECODE()) {
3218 /* XXX DECODE_PRINTF may be changed to something more
3219 general, so that it is important to leave the strings
3220 in the same format, even though the result is that the
3221 above test is done twice. */
3223 switch (rh) {
3224 case 0:
3225 DECODE_PRINTF("ROL\t");
3226 break;
3227 case 1:
3228 DECODE_PRINTF("ROR\t");
3229 break;
3230 case 2:
3231 DECODE_PRINTF("RCL\t");
3232 break;
3233 case 3:
3234 DECODE_PRINTF("RCR\t");
3235 break;
3236 case 4:
3237 DECODE_PRINTF("SHL\t");
3238 break;
3239 case 5:
3240 DECODE_PRINTF("SHR\t");
3241 break;
3242 case 6:
3243 DECODE_PRINTF("SAL\t");
3244 break;
3245 case 7:
3246 DECODE_PRINTF("SAR\t");
3247 break;
3250 #endif
3251 /* know operation, decode the mod byte to find the addressing
3252 mode. */
3253 if (mod < 3) {
3254 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3255 u32 destval;
3257 DECODE_PRINTF("DWORD PTR ");
3258 destoffset = decode_rmXX_address(mod, rl);
3259 amt = fetch_byte_imm();
3260 DECODE_PRINTF2(",%x\n", amt);
3261 destval = fetch_data_long(destoffset);
3262 TRACE_AND_STEP();
3263 destval = (*opcD1_long_operation[rh]) (destval, amt);
3264 store_data_long(destoffset, destval);
3265 } else {
3266 u16 destval;
3268 DECODE_PRINTF("WORD PTR ");
3269 destoffset = decode_rmXX_address(mod, rl);
3270 amt = fetch_byte_imm();
3271 DECODE_PRINTF2(",%x\n", amt);
3272 destval = fetch_data_word(destoffset);
3273 TRACE_AND_STEP();
3274 destval = (*opcD1_word_operation[rh]) (destval, amt);
3275 store_data_word(destoffset, destval);
3277 } else { /* register to register */
3278 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3279 u32 *destreg;
3281 destreg = DECODE_RM_LONG_REGISTER(rl);
3282 amt = fetch_byte_imm();
3283 DECODE_PRINTF2(",%x\n", amt);
3284 TRACE_AND_STEP();
3285 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3286 } else {
3287 u16 *destreg;
3289 destreg = DECODE_RM_WORD_REGISTER(rl);
3290 amt = fetch_byte_imm();
3291 DECODE_PRINTF2(",%x\n", amt);
3292 TRACE_AND_STEP();
3293 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
3296 DECODE_CLEAR_SEGOVR();
3297 END_OF_INSTR();
3300 /****************************************************************************
3301 REMARKS:
3302 Handles opcode 0xc2
3303 ****************************************************************************/
3304 static void x86emuOp_ret_near_IMM(u8 X86EMU_UNUSED(op1))
3306 u16 imm;
3308 START_OF_INSTR();
3309 DECODE_PRINTF("RET\t");
3310 imm = fetch_word_imm();
3311 DECODE_PRINTF2("%x\n", imm);
3312 TRACE_AND_STEP();
3313 M.x86.R_IP = pop_word();
3314 RETURN_TRACE(M.x86.saved_cs,M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, "NEAR");
3315 M.x86.R_SP += imm;
3316 DECODE_CLEAR_SEGOVR();
3317 END_OF_INSTR();
3320 /****************************************************************************
3321 REMARKS:
3322 Handles opcode 0xc3
3323 ****************************************************************************/
3324 static void x86emuOp_ret_near(u8 X86EMU_UNUSED(op1))
3326 START_OF_INSTR();
3327 DECODE_PRINTF("RET\n");
3328 TRACE_AND_STEP();
3329 M.x86.R_IP = pop_word();
3330 RETURN_TRACE(M.x86.saved_cs,M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, "NEAR");
3331 DECODE_CLEAR_SEGOVR();
3332 END_OF_INSTR();
3335 /****************************************************************************
3336 REMARKS:
3337 Handles opcode 0xc4
3338 ****************************************************************************/
3339 static void x86emuOp_les_R_IMM(u8 X86EMU_UNUSED(op1))
3341 int mod, rh, rl;
3342 u16 *dstreg;
3343 uint srcoffset;
3345 START_OF_INSTR();
3346 DECODE_PRINTF("LES\t");
3347 FETCH_DECODE_MODRM(mod, rh, rl);
3348 if (mod < 3) {
3349 dstreg = DECODE_RM_WORD_REGISTER(rh);
3350 DECODE_PRINTF(",");
3351 srcoffset = decode_rmXX_address(mod, rl);
3352 DECODE_PRINTF("\n");
3353 TRACE_AND_STEP();
3354 *dstreg = fetch_data_word(srcoffset);
3355 M.x86.R_ES = fetch_data_word(srcoffset + 2);
3357 /* else UNDEFINED! register to register */
3359 DECODE_CLEAR_SEGOVR();
3360 END_OF_INSTR();
3363 /****************************************************************************
3364 REMARKS:
3365 Handles opcode 0xc5
3366 ****************************************************************************/
3367 static void x86emuOp_lds_R_IMM(u8 X86EMU_UNUSED(op1))
3369 int mod, rh, rl;
3370 u16 *dstreg;
3371 uint srcoffset;
3373 START_OF_INSTR();
3374 DECODE_PRINTF("LDS\t");
3375 FETCH_DECODE_MODRM(mod, rh, rl);
3376 if (mod < 3) {
3377 dstreg = DECODE_RM_WORD_REGISTER(rh);
3378 DECODE_PRINTF(",");
3379 srcoffset = decode_rmXX_address(mod, rl);
3380 DECODE_PRINTF("\n");
3381 TRACE_AND_STEP();
3382 *dstreg = fetch_data_word(srcoffset);
3383 M.x86.R_DS = fetch_data_word(srcoffset + 2);
3385 /* else UNDEFINED! */
3386 DECODE_CLEAR_SEGOVR();
3387 END_OF_INSTR();
3390 /****************************************************************************
3391 REMARKS:
3392 Handles opcode 0xc6
3393 ****************************************************************************/
3394 static void x86emuOp_mov_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
3396 int mod, rl, rh;
3397 u8 *destreg;
3398 uint destoffset;
3399 u8 imm;
3401 START_OF_INSTR();
3402 DECODE_PRINTF("MOV\t");
3403 FETCH_DECODE_MODRM(mod, rh, rl);
3404 if (rh != 0) {
3405 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE c6\n");
3406 HALT_SYS();
3408 if (mod < 3) {
3409 DECODE_PRINTF("BYTE PTR ");
3410 destoffset = decode_rmXX_address(mod, rl);
3411 imm = fetch_byte_imm();
3412 DECODE_PRINTF2(",%2x\n", imm);
3413 TRACE_AND_STEP();
3414 store_data_byte(destoffset, imm);
3415 } else { /* register to register */
3416 destreg = DECODE_RM_BYTE_REGISTER(rl);
3417 imm = fetch_byte_imm();
3418 DECODE_PRINTF2(",%2x\n", imm);
3419 TRACE_AND_STEP();
3420 *destreg = imm;
3422 DECODE_CLEAR_SEGOVR();
3423 END_OF_INSTR();
3426 /****************************************************************************
3427 REMARKS:
3428 Handles opcode 0xc7
3429 ****************************************************************************/
3430 static void x86emuOp_mov_word_RM_IMM(u8 X86EMU_UNUSED(op1))
3432 int mod, rl, rh;
3433 uint destoffset;
3435 START_OF_INSTR();
3436 DECODE_PRINTF("MOV\t");
3437 FETCH_DECODE_MODRM(mod, rh, rl);
3438 if (rh != 0) {
3439 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
3440 HALT_SYS();
3442 if (mod < 3) {
3443 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3444 u32 imm;
3446 DECODE_PRINTF("DWORD PTR ");
3447 destoffset = decode_rmXX_address(mod, rl);
3448 imm = fetch_long_imm();
3449 DECODE_PRINTF2(",%x\n", imm);
3450 TRACE_AND_STEP();
3451 store_data_long(destoffset, imm);
3452 } else {
3453 u16 imm;
3455 DECODE_PRINTF("WORD PTR ");
3456 destoffset = decode_rmXX_address(mod, rl);
3457 imm = fetch_word_imm();
3458 DECODE_PRINTF2(",%x\n", imm);
3459 TRACE_AND_STEP();
3460 store_data_word(destoffset, imm);
3462 } else { /* register to register */
3463 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3464 u32 *destreg;
3465 u32 imm;
3467 destreg = DECODE_RM_LONG_REGISTER(rl);
3468 imm = fetch_long_imm();
3469 DECODE_PRINTF2(",%x\n", imm);
3470 TRACE_AND_STEP();
3471 *destreg = imm;
3472 } else {
3473 u16 *destreg;
3474 u16 imm;
3476 destreg = DECODE_RM_WORD_REGISTER(rl);
3477 imm = fetch_word_imm();
3478 DECODE_PRINTF2(",%x\n", imm);
3479 TRACE_AND_STEP();
3480 *destreg = imm;
3483 DECODE_CLEAR_SEGOVR();
3484 END_OF_INSTR();
3487 /****************************************************************************
3488 REMARKS:
3489 Handles opcode 0xc8
3490 ****************************************************************************/
3491 static void x86emuOp_enter(u8 X86EMU_UNUSED(op1))
3493 u16 local,frame_pointer;
3494 u8 nesting;
3495 int i;
3497 START_OF_INSTR();
3498 local = fetch_word_imm();
3499 nesting = fetch_byte_imm();
3500 DECODE_PRINTF2("ENTER %x\n", local);
3501 DECODE_PRINTF2(",%x\n", nesting);
3502 TRACE_AND_STEP();
3503 push_word(M.x86.R_BP);
3504 frame_pointer = M.x86.R_SP;
3505 if (nesting > 0) {
3506 for (i = 1; i < nesting; i++) {
3507 M.x86.R_BP -= 2;
3508 push_word(fetch_data_word_abs(M.x86.R_SS, M.x86.R_BP));
3510 push_word(frame_pointer);
3512 M.x86.R_BP = frame_pointer;
3513 M.x86.R_SP = (u16)(M.x86.R_SP - local);
3514 DECODE_CLEAR_SEGOVR();
3515 END_OF_INSTR();
3518 /****************************************************************************
3519 REMARKS:
3520 Handles opcode 0xc9
3521 ****************************************************************************/
3522 static void x86emuOp_leave(u8 X86EMU_UNUSED(op1))
3524 START_OF_INSTR();
3525 DECODE_PRINTF("LEAVE\n");
3526 TRACE_AND_STEP();
3527 M.x86.R_SP = M.x86.R_BP;
3528 M.x86.R_BP = pop_word();
3529 DECODE_CLEAR_SEGOVR();
3530 END_OF_INSTR();
3533 /****************************************************************************
3534 REMARKS:
3535 Handles opcode 0xca
3536 ****************************************************************************/
3537 static void x86emuOp_ret_far_IMM(u8 X86EMU_UNUSED(op1))
3539 u16 imm;
3541 START_OF_INSTR();
3542 DECODE_PRINTF("RETF\t");
3543 imm = fetch_word_imm();
3544 DECODE_PRINTF2("%x\n", imm);
3545 TRACE_AND_STEP();
3546 M.x86.R_IP = pop_word();
3547 M.x86.R_CS = pop_word();
3548 RETURN_TRACE(M.x86.saved_cs,M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, "FAR");
3549 M.x86.R_SP += imm;
3550 DECODE_CLEAR_SEGOVR();
3551 END_OF_INSTR();
3554 /****************************************************************************
3555 REMARKS:
3556 Handles opcode 0xcb
3557 ****************************************************************************/
3558 static void x86emuOp_ret_far(u8 X86EMU_UNUSED(op1))
3560 START_OF_INSTR();
3561 DECODE_PRINTF("RETF\n");
3562 TRACE_AND_STEP();
3563 M.x86.R_IP = pop_word();
3564 M.x86.R_CS = pop_word();
3565 RETURN_TRACE(M.x86.saved_cs,M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, "FAR");
3566 DECODE_CLEAR_SEGOVR();
3567 END_OF_INSTR();
3570 /****************************************************************************
3571 REMARKS:
3572 Handles opcode 0xcc
3573 ****************************************************************************/
3574 static void x86emuOp_int3(u8 X86EMU_UNUSED(op1))
3576 u16 X86EMU_UNUSED(tmp);
3578 START_OF_INSTR();
3579 DECODE_PRINTF("INT 3\n");
3580 tmp = (u16) mem_access_word(3 * 4 + 2);
3581 /* access the segment register */
3582 TRACE_AND_STEP();
3583 if (_X86EMU_intrTab[3]) {
3584 (*_X86EMU_intrTab[3])(3);
3585 } else {
3586 push_word((u16)M.x86.R_FLG);
3587 CLEAR_FLAG(F_IF);
3588 CLEAR_FLAG(F_TF);
3589 push_word(M.x86.R_CS);
3590 M.x86.R_CS = mem_access_word(3 * 4 + 2);
3591 push_word(M.x86.R_IP);
3592 M.x86.R_IP = mem_access_word(3 * 4);
3594 DECODE_CLEAR_SEGOVR();
3595 END_OF_INSTR();
3598 /****************************************************************************
3599 REMARKS:
3600 Handles opcode 0xcd
3601 ****************************************************************************/
3602 static void x86emuOp_int_IMM(u8 X86EMU_UNUSED(op1))
3604 u16 X86EMU_UNUSED(tmp);
3605 u8 intnum;
3607 START_OF_INSTR();
3608 DECODE_PRINTF("INT\t");
3609 intnum = fetch_byte_imm();
3610 DECODE_PRINTF2("%x\n", intnum);
3611 tmp = mem_access_word(intnum * 4 + 2);
3612 TRACE_AND_STEP();
3613 if (_X86EMU_intrTab[intnum]) {
3614 (*_X86EMU_intrTab[intnum])(intnum);
3615 } else {
3616 push_word((u16)M.x86.R_FLG);
3617 CLEAR_FLAG(F_IF);
3618 CLEAR_FLAG(F_TF);
3619 push_word(M.x86.R_CS);
3620 M.x86.R_CS = mem_access_word(intnum * 4 + 2);
3621 push_word(M.x86.R_IP);
3622 M.x86.R_IP = mem_access_word(intnum * 4);
3624 DECODE_CLEAR_SEGOVR();
3625 END_OF_INSTR();
3628 /****************************************************************************
3629 REMARKS:
3630 Handles opcode 0xce
3631 ****************************************************************************/
3632 static void x86emuOp_into(u8 X86EMU_UNUSED(op1))
3634 u16 X86EMU_UNUSED(tmp);
3636 START_OF_INSTR();
3637 DECODE_PRINTF("INTO\n");
3638 TRACE_AND_STEP();
3639 if (ACCESS_FLAG(F_OF)) {
3640 tmp = mem_access_word(4 * 4 + 2);
3641 if (_X86EMU_intrTab[4]) {
3642 (*_X86EMU_intrTab[4])(4);
3643 } else {
3644 push_word((u16)M.x86.R_FLG);
3645 CLEAR_FLAG(F_IF);
3646 CLEAR_FLAG(F_TF);
3647 push_word(M.x86.R_CS);
3648 M.x86.R_CS = mem_access_word(4 * 4 + 2);
3649 push_word(M.x86.R_IP);
3650 M.x86.R_IP = mem_access_word(4 * 4);
3653 DECODE_CLEAR_SEGOVR();
3654 END_OF_INSTR();
3657 /****************************************************************************
3658 REMARKS:
3659 Handles opcode 0xcf
3660 ****************************************************************************/
3661 static void x86emuOp_iret(u8 X86EMU_UNUSED(op1))
3663 START_OF_INSTR();
3664 DECODE_PRINTF("IRET\n");
3666 TRACE_AND_STEP();
3668 M.x86.R_IP = pop_word();
3669 M.x86.R_CS = pop_word();
3670 M.x86.R_FLG = pop_word();
3671 DECODE_CLEAR_SEGOVR();
3672 END_OF_INSTR();
3675 /****************************************************************************
3676 REMARKS:
3677 Handles opcode 0xd0
3678 ****************************************************************************/
3679 static void x86emuOp_opcD0_byte_RM_1(u8 X86EMU_UNUSED(op1))
3681 int mod, rl, rh;
3682 u8 *destreg;
3683 uint destoffset;
3684 u8 destval;
3687 * Yet another weirdo special case instruction format. Part of
3688 * the opcode held below in "RH". Doubly nested case would
3689 * result, except that the decoded instruction
3691 START_OF_INSTR();
3692 FETCH_DECODE_MODRM(mod, rh, rl);
3693 #ifdef DEBUG
3694 if (DEBUG_DECODE()) {
3695 /* XXX DECODE_PRINTF may be changed to something more
3696 general, so that it is important to leave the strings
3697 in the same format, even though the result is that the
3698 above test is done twice. */
3699 switch (rh) {
3700 case 0:
3701 DECODE_PRINTF("ROL\t");
3702 break;
3703 case 1:
3704 DECODE_PRINTF("ROR\t");
3705 break;
3706 case 2:
3707 DECODE_PRINTF("RCL\t");
3708 break;
3709 case 3:
3710 DECODE_PRINTF("RCR\t");
3711 break;
3712 case 4:
3713 DECODE_PRINTF("SHL\t");
3714 break;
3715 case 5:
3716 DECODE_PRINTF("SHR\t");
3717 break;
3718 case 6:
3719 DECODE_PRINTF("SAL\t");
3720 break;
3721 case 7:
3722 DECODE_PRINTF("SAR\t");
3723 break;
3726 #endif
3727 /* know operation, decode the mod byte to find the addressing
3728 mode. */
3729 if (mod < 3) {
3730 DECODE_PRINTF("BYTE PTR ");
3731 destoffset = decode_rmXX_address(mod, rl);
3732 DECODE_PRINTF(",1\n");
3733 destval = fetch_data_byte(destoffset);
3734 TRACE_AND_STEP();
3735 destval = (*opcD0_byte_operation[rh]) (destval, 1);
3736 store_data_byte(destoffset, destval);
3737 } else { /* register to register */
3738 destreg = DECODE_RM_BYTE_REGISTER(rl);
3739 DECODE_PRINTF(",1\n");
3740 TRACE_AND_STEP();
3741 destval = (*opcD0_byte_operation[rh]) (*destreg, 1);
3742 *destreg = destval;
3744 DECODE_CLEAR_SEGOVR();
3745 END_OF_INSTR();
3748 /****************************************************************************
3749 REMARKS:
3750 Handles opcode 0xd1
3751 ****************************************************************************/
3752 static void x86emuOp_opcD1_word_RM_1(u8 X86EMU_UNUSED(op1))
3754 int mod, rl, rh;
3755 uint destoffset;
3758 * Yet another weirdo special case instruction format. Part of
3759 * the opcode held below in "RH". Doubly nested case would
3760 * result, except that the decoded instruction
3762 START_OF_INSTR();
3763 FETCH_DECODE_MODRM(mod, rh, rl);
3764 #ifdef DEBUG
3765 if (DEBUG_DECODE()) {
3766 /* XXX DECODE_PRINTF may be changed to something more
3767 general, so that it is important to leave the strings
3768 in the same format, even though the result is that the
3769 above test is done twice. */
3770 switch (rh) {
3771 case 0:
3772 DECODE_PRINTF("ROL\t");
3773 break;
3774 case 1:
3775 DECODE_PRINTF("ROR\t");
3776 break;
3777 case 2:
3778 DECODE_PRINTF("RCL\t");
3779 break;
3780 case 3:
3781 DECODE_PRINTF("RCR\t");
3782 break;
3783 case 4:
3784 DECODE_PRINTF("SHL\t");
3785 break;
3786 case 5:
3787 DECODE_PRINTF("SHR\t");
3788 break;
3789 case 6:
3790 DECODE_PRINTF("SAL\t");
3791 break;
3792 case 7:
3793 DECODE_PRINTF("SAR\t");
3794 break;
3797 #endif
3798 /* know operation, decode the mod byte to find the addressing
3799 mode. */
3800 if (mod < 3) {
3801 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3802 u32 destval;
3804 DECODE_PRINTF("DWORD PTR ");
3805 destoffset = decode_rmXX_address(mod, rl);
3806 DECODE_PRINTF(",1\n");
3807 destval = fetch_data_long(destoffset);
3808 TRACE_AND_STEP();
3809 destval = (*opcD1_long_operation[rh]) (destval, 1);
3810 store_data_long(destoffset, destval);
3811 } else {
3812 u16 destval;
3814 DECODE_PRINTF("WORD PTR ");
3815 destoffset = decode_rmXX_address(mod, rl);
3816 DECODE_PRINTF(",1\n");
3817 destval = fetch_data_word(destoffset);
3818 TRACE_AND_STEP();
3819 destval = (*opcD1_word_operation[rh]) (destval, 1);
3820 store_data_word(destoffset, destval);
3822 } else { /* register to register */
3823 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3824 u32 destval;
3825 u32 *destreg;
3827 destreg = DECODE_RM_LONG_REGISTER(rl);
3828 DECODE_PRINTF(",1\n");
3829 TRACE_AND_STEP();
3830 destval = (*opcD1_long_operation[rh]) (*destreg, 1);
3831 *destreg = destval;
3832 } else {
3833 u16 destval;
3834 u16 *destreg;
3836 destreg = DECODE_RM_WORD_REGISTER(rl);
3837 DECODE_PRINTF(",1\n");
3838 TRACE_AND_STEP();
3839 destval = (*opcD1_word_operation[rh]) (*destreg, 1);
3840 *destreg = destval;
3843 DECODE_CLEAR_SEGOVR();
3844 END_OF_INSTR();
3847 /****************************************************************************
3848 REMARKS:
3849 Handles opcode 0xd2
3850 ****************************************************************************/
3851 static void x86emuOp_opcD2_byte_RM_CL(u8 X86EMU_UNUSED(op1))
3853 int mod, rl, rh;
3854 u8 *destreg;
3855 uint destoffset;
3856 u8 destval;
3857 u8 amt;
3860 * Yet another weirdo special case instruction format. Part of
3861 * the opcode held below in "RH". Doubly nested case would
3862 * result, except that the decoded instruction
3864 START_OF_INSTR();
3865 FETCH_DECODE_MODRM(mod, rh, rl);
3866 #ifdef DEBUG
3867 if (DEBUG_DECODE()) {
3868 /* XXX DECODE_PRINTF may be changed to something more
3869 general, so that it is important to leave the strings
3870 in the same format, even though the result is that the
3871 above test is done twice. */
3872 switch (rh) {
3873 case 0:
3874 DECODE_PRINTF("ROL\t");
3875 break;
3876 case 1:
3877 DECODE_PRINTF("ROR\t");
3878 break;
3879 case 2:
3880 DECODE_PRINTF("RCL\t");
3881 break;
3882 case 3:
3883 DECODE_PRINTF("RCR\t");
3884 break;
3885 case 4:
3886 DECODE_PRINTF("SHL\t");
3887 break;
3888 case 5:
3889 DECODE_PRINTF("SHR\t");
3890 break;
3891 case 6:
3892 DECODE_PRINTF("SAL\t");
3893 break;
3894 case 7:
3895 DECODE_PRINTF("SAR\t");
3896 break;
3899 #endif
3900 /* know operation, decode the mod byte to find the addressing
3901 mode. */
3902 amt = M.x86.R_CL;
3903 if (mod < 3) {
3904 DECODE_PRINTF("BYTE PTR ");
3905 destoffset = decode_rmXX_address(mod, rl);
3906 DECODE_PRINTF(",CL\n");
3907 destval = fetch_data_byte(destoffset);
3908 TRACE_AND_STEP();
3909 destval = (*opcD0_byte_operation[rh]) (destval, amt);
3910 store_data_byte(destoffset, destval);
3911 } else { /* register to register */
3912 destreg = DECODE_RM_BYTE_REGISTER(rl);
3913 DECODE_PRINTF(",CL\n");
3914 TRACE_AND_STEP();
3915 destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3916 *destreg = destval;
3918 DECODE_CLEAR_SEGOVR();
3919 END_OF_INSTR();
3922 /****************************************************************************
3923 REMARKS:
3924 Handles opcode 0xd3
3925 ****************************************************************************/
3926 static void x86emuOp_opcD3_word_RM_CL(u8 X86EMU_UNUSED(op1))
3928 int mod, rl, rh;
3929 uint destoffset;
3930 u8 amt;
3933 * Yet another weirdo special case instruction format. Part of
3934 * the opcode held below in "RH". Doubly nested case would
3935 * result, except that the decoded instruction
3937 START_OF_INSTR();
3938 FETCH_DECODE_MODRM(mod, rh, rl);
3939 #ifdef DEBUG
3940 if (DEBUG_DECODE()) {
3941 /* XXX DECODE_PRINTF may be changed to something more
3942 general, so that it is important to leave the strings
3943 in the same format, even though the result is that the
3944 above test is done twice. */
3945 switch (rh) {
3946 case 0:
3947 DECODE_PRINTF("ROL\t");
3948 break;
3949 case 1:
3950 DECODE_PRINTF("ROR\t");
3951 break;
3952 case 2:
3953 DECODE_PRINTF("RCL\t");
3954 break;
3955 case 3:
3956 DECODE_PRINTF("RCR\t");
3957 break;
3958 case 4:
3959 DECODE_PRINTF("SHL\t");
3960 break;
3961 case 5:
3962 DECODE_PRINTF("SHR\t");
3963 break;
3964 case 6:
3965 DECODE_PRINTF("SAL\t");
3966 break;
3967 case 7:
3968 DECODE_PRINTF("SAR\t");
3969 break;
3972 #endif
3973 /* know operation, decode the mod byte to find the addressing
3974 mode. */
3975 amt = M.x86.R_CL;
3976 if (mod < 3) {
3977 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3978 u32 destval;
3980 DECODE_PRINTF("DWORD PTR ");
3981 destoffset = decode_rmXX_address(mod, rl);
3982 DECODE_PRINTF(",CL\n");
3983 destval = fetch_data_long(destoffset);
3984 TRACE_AND_STEP();
3985 destval = (*opcD1_long_operation[rh]) (destval, amt);
3986 store_data_long(destoffset, destval);
3987 } else {
3988 u16 destval;
3990 DECODE_PRINTF("WORD PTR ");
3991 destoffset = decode_rmXX_address(mod, rl);
3992 DECODE_PRINTF(",CL\n");
3993 destval = fetch_data_word(destoffset);
3994 TRACE_AND_STEP();
3995 destval = (*opcD1_word_operation[rh]) (destval, amt);
3996 store_data_word(destoffset, destval);
3998 } else { /* register to register */
3999 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4000 u32 *destreg;
4002 destreg = DECODE_RM_LONG_REGISTER(rl);
4003 DECODE_PRINTF(",CL\n");
4004 TRACE_AND_STEP();
4005 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
4006 } else {
4007 u16 *destreg;
4009 destreg = DECODE_RM_WORD_REGISTER(rl);
4010 DECODE_PRINTF(",CL\n");
4011 TRACE_AND_STEP();
4012 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
4015 DECODE_CLEAR_SEGOVR();
4016 END_OF_INSTR();
4019 /****************************************************************************
4020 REMARKS:
4021 Handles opcode 0xd4
4022 ****************************************************************************/
4023 static void x86emuOp_aam(u8 X86EMU_UNUSED(op1))
4025 u8 a;
4027 START_OF_INSTR();
4028 DECODE_PRINTF("AAM\n");
4029 a = fetch_byte_imm(); /* this is a stupid encoding. */
4030 if (a != 10) {
4031 DECODE_PRINTF("ERROR DECODING AAM\n");
4032 TRACE_REGS();
4033 HALT_SYS();
4035 TRACE_AND_STEP();
4036 /* note the type change here --- returning AL and AH in AX. */
4037 M.x86.R_AX = aam_word(M.x86.R_AL);
4038 DECODE_CLEAR_SEGOVR();
4039 END_OF_INSTR();
4042 /****************************************************************************
4043 REMARKS:
4044 Handles opcode 0xd5
4045 ****************************************************************************/
4046 static void x86emuOp_aad(u8 X86EMU_UNUSED(op1))
4048 u8 X86EMU_UNUSED(a);
4050 START_OF_INSTR();
4051 DECODE_PRINTF("AAD\n");
4052 a = fetch_byte_imm();
4053 TRACE_AND_STEP();
4054 M.x86.R_AX = aad_word(M.x86.R_AX);
4055 DECODE_CLEAR_SEGOVR();
4056 END_OF_INSTR();
4059 /* opcode 0xd6 ILLEGAL OPCODE */
4061 /****************************************************************************
4062 REMARKS:
4063 Handles opcode 0xd7
4064 ****************************************************************************/
4065 static void x86emuOp_xlat(u8 X86EMU_UNUSED(op1))
4067 u16 addr;
4069 START_OF_INSTR();
4070 DECODE_PRINTF("XLAT\n");
4071 TRACE_AND_STEP();
4072 addr = (u16)(M.x86.R_BX + (u8)M.x86.R_AL);
4073 M.x86.R_AL = fetch_data_byte(addr);
4074 DECODE_CLEAR_SEGOVR();
4075 END_OF_INSTR();
4078 /* Instructions D8 .. DF are in i87_ops.c */
4080 /****************************************************************************
4081 REMARKS:
4082 Handles opcode 0xe0
4083 ****************************************************************************/
4084 static void x86emuOp_loopne(u8 X86EMU_UNUSED(op1))
4086 s16 ip;
4088 START_OF_INSTR();
4089 DECODE_PRINTF("LOOPNE\t");
4090 ip = (s8) fetch_byte_imm();
4091 ip += (s16) M.x86.R_IP;
4092 DECODE_PRINTF2("%04x\n", ip);
4093 TRACE_AND_STEP();
4094 if (M.x86.mode & SYSMODE_PREFIX_ADDR)
4095 M.x86.R_ECX -= 1;
4096 else
4097 M.x86.R_CX -= 1;
4098 if (((M.x86.mode & SYSMODE_PREFIX_ADDR) ? M.x86.R_ECX : M.x86.R_CX) != 0 && !ACCESS_FLAG(F_ZF)) /* (E)CX != 0 and !ZF */
4099 M.x86.R_IP = ip;
4100 DECODE_CLEAR_SEGOVR();
4101 END_OF_INSTR();
4104 /****************************************************************************
4105 REMARKS:
4106 Handles opcode 0xe1
4107 ****************************************************************************/
4108 static void x86emuOp_loope(u8 X86EMU_UNUSED(op1))
4110 s16 ip;
4112 START_OF_INSTR();
4113 DECODE_PRINTF("LOOPE\t");
4114 ip = (s8) fetch_byte_imm();
4115 ip += (s16) M.x86.R_IP;
4116 DECODE_PRINTF2("%04x\n", ip);
4117 TRACE_AND_STEP();
4118 if (M.x86.mode & SYSMODE_PREFIX_ADDR)
4119 M.x86.R_ECX -= 1;
4120 else
4121 M.x86.R_CX -= 1;
4122 if (((M.x86.mode & SYSMODE_PREFIX_ADDR) ? M.x86.R_ECX : M.x86.R_CX) != 0 && ACCESS_FLAG(F_ZF)) /* (E)CX != 0 and ZF */
4123 M.x86.R_IP = ip;
4124 DECODE_CLEAR_SEGOVR();
4125 END_OF_INSTR();
4128 /****************************************************************************
4129 REMARKS:
4130 Handles opcode 0xe2
4131 ****************************************************************************/
4132 static void x86emuOp_loop(u8 X86EMU_UNUSED(op1))
4134 s16 ip;
4136 START_OF_INSTR();
4137 DECODE_PRINTF("LOOP\t");
4138 ip = (s8) fetch_byte_imm();
4139 ip += (s16) M.x86.R_IP;
4140 DECODE_PRINTF2("%04x\n", ip);
4141 TRACE_AND_STEP();
4142 if (M.x86.mode & SYSMODE_PREFIX_ADDR)
4143 M.x86.R_ECX -= 1;
4144 else
4145 M.x86.R_CX -= 1;
4146 if (((M.x86.mode & SYSMODE_PREFIX_ADDR) ? M.x86.R_ECX : M.x86.R_CX) != 0) /* (E)CX != 0 */
4147 M.x86.R_IP = ip;
4148 DECODE_CLEAR_SEGOVR();
4149 END_OF_INSTR();
4152 /****************************************************************************
4153 REMARKS:
4154 Handles opcode 0xe3
4155 ****************************************************************************/
4156 static void x86emuOp_jcxz(u8 X86EMU_UNUSED(op1))
4158 u16 target;
4159 s8 offset;
4161 /* jump to byte offset if overflow flag is set */
4162 START_OF_INSTR();
4163 DECODE_PRINTF("JCXZ\t");
4164 offset = (s8)fetch_byte_imm();
4165 target = (u16)(M.x86.R_IP + offset);
4166 DECODE_PRINTF2("%x\n", target);
4167 TRACE_AND_STEP();
4168 if (M.x86.R_CX == 0) {
4169 M.x86.R_IP = target;
4170 JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, " CXZ ");
4172 DECODE_CLEAR_SEGOVR();
4173 END_OF_INSTR();
4176 /****************************************************************************
4177 REMARKS:
4178 Handles opcode 0xe4
4179 ****************************************************************************/
4180 static void x86emuOp_in_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
4182 u8 port;
4184 START_OF_INSTR();
4185 DECODE_PRINTF("IN\t");
4186 port = (u8) fetch_byte_imm();
4187 DECODE_PRINTF2("%x,AL\n", port);
4188 TRACE_AND_STEP();
4189 M.x86.R_AL = (*sys_inb)(port);
4190 DECODE_CLEAR_SEGOVR();
4191 END_OF_INSTR();
4194 /****************************************************************************
4195 REMARKS:
4196 Handles opcode 0xe5
4197 ****************************************************************************/
4198 static void x86emuOp_in_word_AX_IMM(u8 X86EMU_UNUSED(op1))
4200 u8 port;
4202 START_OF_INSTR();
4203 DECODE_PRINTF("IN\t");
4204 port = (u8) fetch_byte_imm();
4205 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4206 DECODE_PRINTF2("EAX,%x\n", port);
4207 } else {
4208 DECODE_PRINTF2("AX,%x\n", port);
4210 TRACE_AND_STEP();
4211 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4212 M.x86.R_EAX = (*sys_inl)(port);
4213 } else {
4214 M.x86.R_AX = (*sys_inw)(port);
4216 DECODE_CLEAR_SEGOVR();
4217 END_OF_INSTR();
4220 /****************************************************************************
4221 REMARKS:
4222 Handles opcode 0xe6
4223 ****************************************************************************/
4224 static void x86emuOp_out_byte_IMM_AL(u8 X86EMU_UNUSED(op1))
4226 u8 port;
4228 START_OF_INSTR();
4229 DECODE_PRINTF("OUT\t");
4230 port = (u8) fetch_byte_imm();
4231 DECODE_PRINTF2("%x,AL\n", port);
4232 TRACE_AND_STEP();
4233 (*sys_outb)(port, M.x86.R_AL);
4234 DECODE_CLEAR_SEGOVR();
4235 END_OF_INSTR();
4238 /****************************************************************************
4239 REMARKS:
4240 Handles opcode 0xe7
4241 ****************************************************************************/
4242 static void x86emuOp_out_word_IMM_AX(u8 X86EMU_UNUSED(op1))
4244 u8 port;
4246 START_OF_INSTR();
4247 DECODE_PRINTF("OUT\t");
4248 port = (u8) fetch_byte_imm();
4249 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4250 DECODE_PRINTF2("%x,EAX\n", port);
4251 } else {
4252 DECODE_PRINTF2("%x,AX\n", port);
4254 TRACE_AND_STEP();
4255 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4256 (*sys_outl)(port, M.x86.R_EAX);
4257 } else {
4258 (*sys_outw)(port, M.x86.R_AX);
4260 DECODE_CLEAR_SEGOVR();
4261 END_OF_INSTR();
4264 /****************************************************************************
4265 REMARKS:
4266 Handles opcode 0xe8
4267 ****************************************************************************/
4268 static void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1))
4270 s16 ip16 = 0; /* Initialize to keep GCC silent */
4271 s32 ip32 = 0;
4273 START_OF_INSTR();
4274 DECODE_PRINTF("CALL\t");
4275 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4276 ip32 = (s32) fetch_long_imm();
4277 ip32 += (s16) M.x86.R_IP; /* CHECK SIGN */
4278 DECODE_PRINTF2("%04x\n", (u16)ip32);
4279 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip32, "");
4280 } else {
4281 ip16 = (s16) fetch_word_imm();
4282 ip16 += (s16) M.x86.R_IP; /* CHECK SIGN */
4283 DECODE_PRINTF2("%04x\n", ip16);
4284 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip16, "");
4286 TRACE_AND_STEP();
4287 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4288 push_long(M.x86.R_EIP);
4289 M.x86.R_EIP = ip32 & 0xffff;
4290 } else {
4291 push_word(M.x86.R_IP);
4292 M.x86.R_EIP = ip16;
4294 DECODE_CLEAR_SEGOVR();
4295 END_OF_INSTR();
4298 /****************************************************************************
4299 REMARKS:
4300 Handles opcode 0xe9
4301 ****************************************************************************/
4302 static void x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1))
4304 u32 ip;
4306 START_OF_INSTR();
4307 DECODE_PRINTF("JMP\t");
4308 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4309 ip = (u32)fetch_long_imm();
4310 ip += (u32)M.x86.R_EIP;
4311 DECODE_PRINTF2("%08x\n", (u32)ip);
4312 JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, " NEAR ");
4313 TRACE_AND_STEP();
4314 M.x86.R_EIP = (u32)ip;
4315 } else {
4316 ip = (s16)fetch_word_imm();
4317 ip += (s16)M.x86.R_IP;
4318 DECODE_PRINTF2("%04x\n", (u16)ip);
4319 JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, " NEAR ");
4320 TRACE_AND_STEP();
4321 M.x86.R_IP = (u16)ip;
4323 DECODE_CLEAR_SEGOVR();
4324 END_OF_INSTR();
4327 /****************************************************************************
4328 REMARKS:
4329 Handles opcode 0xea
4330 ****************************************************************************/
4331 static void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1))
4333 u16 cs;
4334 u32 ip;
4336 START_OF_INSTR();
4337 DECODE_PRINTF("JMP\tFAR ");
4338 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4339 ip = fetch_long_imm();
4340 } else {
4341 ip = fetch_word_imm();
4343 cs = fetch_word_imm();
4344 DECODE_PRINTF2("%04x:", cs);
4345 DECODE_PRINTF2("%04x\n", ip);
4346 JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, cs, ip, " FAR ");
4347 TRACE_AND_STEP();
4348 M.x86.R_EIP = ip & 0xffff;
4349 M.x86.R_CS = cs;
4350 DECODE_CLEAR_SEGOVR();
4351 END_OF_INSTR();
4354 /****************************************************************************
4355 REMARKS:
4356 Handles opcode 0xeb
4357 ****************************************************************************/
4358 static void x86emuOp_jump_byte_IMM(u8 X86EMU_UNUSED(op1))
4360 u16 target;
4361 s8 offset;
4363 START_OF_INSTR();
4364 DECODE_PRINTF("JMP\t");
4365 offset = (s8)fetch_byte_imm();
4366 target = (u16)(M.x86.R_IP + offset);
4367 DECODE_PRINTF2("%x\n", target);
4368 JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, target, " BYTE ");
4369 TRACE_AND_STEP();
4370 M.x86.R_IP = target;
4371 DECODE_CLEAR_SEGOVR();
4372 END_OF_INSTR();
4375 /****************************************************************************
4376 REMARKS:
4377 Handles opcode 0xec
4378 ****************************************************************************/
4379 static void x86emuOp_in_byte_AL_DX(u8 X86EMU_UNUSED(op1))
4381 START_OF_INSTR();
4382 DECODE_PRINTF("IN\tAL,DX\n");
4383 TRACE_AND_STEP();
4384 M.x86.R_AL = (*sys_inb)(M.x86.R_DX);
4385 DECODE_CLEAR_SEGOVR();
4386 END_OF_INSTR();
4389 /****************************************************************************
4390 REMARKS:
4391 Handles opcode 0xed
4392 ****************************************************************************/
4393 static void x86emuOp_in_word_AX_DX(u8 X86EMU_UNUSED(op1))
4395 START_OF_INSTR();
4396 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4397 DECODE_PRINTF("IN\tEAX,DX\n");
4398 } else {
4399 DECODE_PRINTF("IN\tAX,DX\n");
4401 TRACE_AND_STEP();
4402 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4403 M.x86.R_EAX = (*sys_inl)(M.x86.R_DX);
4404 } else {
4405 M.x86.R_AX = (*sys_inw)(M.x86.R_DX);
4407 DECODE_CLEAR_SEGOVR();
4408 END_OF_INSTR();
4411 /****************************************************************************
4412 REMARKS:
4413 Handles opcode 0xee
4414 ****************************************************************************/
4415 static void x86emuOp_out_byte_DX_AL(u8 X86EMU_UNUSED(op1))
4417 START_OF_INSTR();
4418 DECODE_PRINTF("OUT\tDX,AL\n");
4419 TRACE_AND_STEP();
4420 (*sys_outb)(M.x86.R_DX, M.x86.R_AL);
4421 DECODE_CLEAR_SEGOVR();
4422 END_OF_INSTR();
4425 /****************************************************************************
4426 REMARKS:
4427 Handles opcode 0xef
4428 ****************************************************************************/
4429 static void x86emuOp_out_word_DX_AX(u8 X86EMU_UNUSED(op1))
4431 START_OF_INSTR();
4432 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4433 DECODE_PRINTF("OUT\tDX,EAX\n");
4434 } else {
4435 DECODE_PRINTF("OUT\tDX,AX\n");
4437 TRACE_AND_STEP();
4438 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4439 (*sys_outl)(M.x86.R_DX, M.x86.R_EAX);
4440 } else {
4441 (*sys_outw)(M.x86.R_DX, M.x86.R_AX);
4443 DECODE_CLEAR_SEGOVR();
4444 END_OF_INSTR();
4447 /****************************************************************************
4448 REMARKS:
4449 Handles opcode 0xf0
4450 ****************************************************************************/
4451 static void x86emuOp_lock(u8 X86EMU_UNUSED(op1))
4453 START_OF_INSTR();
4454 DECODE_PRINTF("LOCK:\n");
4455 TRACE_AND_STEP();
4456 DECODE_CLEAR_SEGOVR();
4457 END_OF_INSTR();
4460 /*opcode 0xf1 ILLEGAL OPERATION */
4462 /****************************************************************************
4463 REMARKS:
4464 Handles opcode 0xf2
4465 ****************************************************************************/
4466 static void x86emuOp_repne(u8 X86EMU_UNUSED(op1))
4468 START_OF_INSTR();
4469 DECODE_PRINTF("REPNE\n");
4470 TRACE_AND_STEP();
4471 M.x86.mode |= SYSMODE_PREFIX_REPNE;
4472 if (M.x86.mode & SYSMODE_PREFIX_ADDR)
4473 M.x86.mode |= SYSMODE_32BIT_REP;
4474 DECODE_CLEAR_SEGOVR();
4475 END_OF_INSTR();
4478 /****************************************************************************
4479 REMARKS:
4480 Handles opcode 0xf3
4481 ****************************************************************************/
4482 static void x86emuOp_repe(u8 X86EMU_UNUSED(op1))
4484 START_OF_INSTR();
4485 DECODE_PRINTF("REPE\n");
4486 TRACE_AND_STEP();
4487 M.x86.mode |= SYSMODE_PREFIX_REPE;
4488 if (M.x86.mode & SYSMODE_PREFIX_ADDR)
4489 M.x86.mode |= SYSMODE_32BIT_REP;
4490 DECODE_CLEAR_SEGOVR();
4491 END_OF_INSTR();
4494 /****************************************************************************
4495 REMARKS:
4496 Handles opcode 0xf4
4497 ****************************************************************************/
4498 static void x86emuOp_halt(u8 X86EMU_UNUSED(op1))
4500 START_OF_INSTR();
4501 DECODE_PRINTF("HALT\n");
4502 TRACE_AND_STEP();
4503 HALT_SYS();
4504 DECODE_CLEAR_SEGOVR();
4505 END_OF_INSTR();
4508 /****************************************************************************
4509 REMARKS:
4510 Handles opcode 0xf5
4511 ****************************************************************************/
4512 static void x86emuOp_cmc(u8 X86EMU_UNUSED(op1))
4514 /* complement the carry flag. */
4515 START_OF_INSTR();
4516 DECODE_PRINTF("CMC\n");
4517 TRACE_AND_STEP();
4518 TOGGLE_FLAG(F_CF);
4519 DECODE_CLEAR_SEGOVR();
4520 END_OF_INSTR();
4523 /****************************************************************************
4524 REMARKS:
4525 Handles opcode 0xf6
4526 ****************************************************************************/
4527 static void x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1))
4529 int mod, rl, rh;
4530 u8 *destreg;
4531 uint destoffset;
4532 u8 destval, srcval;
4534 /* long, drawn out code follows. Double switch for a total
4535 of 32 cases. */
4536 START_OF_INSTR();
4537 FETCH_DECODE_MODRM(mod, rh, rl);
4538 DECODE_PRINTF(opF6_names[rh]);
4539 if (mod < 3) {
4540 DECODE_PRINTF("BYTE PTR ");
4541 destoffset = decode_rmXX_address(mod, rl);
4542 destval = fetch_data_byte(destoffset);
4544 switch (rh) {
4545 case 0: /* test byte imm */
4546 DECODE_PRINTF(",");
4547 srcval = fetch_byte_imm();
4548 DECODE_PRINTF2("%02x\n", srcval);
4549 TRACE_AND_STEP();
4550 test_byte(destval, srcval);
4551 break;
4552 case 1:
4553 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4554 HALT_SYS();
4555 break;
4556 case 2:
4557 DECODE_PRINTF("\n");
4558 TRACE_AND_STEP();
4559 destval = not_byte(destval);
4560 store_data_byte(destoffset, destval);
4561 break;
4562 case 3:
4563 DECODE_PRINTF("\n");
4564 TRACE_AND_STEP();
4565 destval = neg_byte(destval);
4566 store_data_byte(destoffset, destval);
4567 break;
4568 case 4:
4569 DECODE_PRINTF("\n");
4570 TRACE_AND_STEP();
4571 mul_byte(destval);
4572 break;
4573 case 5:
4574 DECODE_PRINTF("\n");
4575 TRACE_AND_STEP();
4576 imul_byte(destval);
4577 break;
4578 case 6:
4579 DECODE_PRINTF("\n");
4580 TRACE_AND_STEP();
4581 div_byte(destval);
4582 break;
4583 default:
4584 DECODE_PRINTF("\n");
4585 TRACE_AND_STEP();
4586 idiv_byte(destval);
4587 break;
4589 } else { /* mod=11 */
4590 destreg = DECODE_RM_BYTE_REGISTER(rl);
4591 switch (rh) {
4592 case 0: /* test byte imm */
4593 DECODE_PRINTF(",");
4594 srcval = fetch_byte_imm();
4595 DECODE_PRINTF2("%02x\n", srcval);
4596 TRACE_AND_STEP();
4597 test_byte(*destreg, srcval);
4598 break;
4599 case 1:
4600 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4601 HALT_SYS();
4602 break;
4603 case 2:
4604 DECODE_PRINTF("\n");
4605 TRACE_AND_STEP();
4606 *destreg = not_byte(*destreg);
4607 break;
4608 case 3:
4609 DECODE_PRINTF("\n");
4610 TRACE_AND_STEP();
4611 *destreg = neg_byte(*destreg);
4612 break;
4613 case 4:
4614 DECODE_PRINTF("\n");
4615 TRACE_AND_STEP();
4616 mul_byte(*destreg); /*!!! */
4617 break;
4618 case 5:
4619 DECODE_PRINTF("\n");
4620 TRACE_AND_STEP();
4621 imul_byte(*destreg);
4622 break;
4623 case 6:
4624 DECODE_PRINTF("\n");
4625 TRACE_AND_STEP();
4626 div_byte(*destreg);
4627 break;
4628 default:
4629 DECODE_PRINTF("\n");
4630 TRACE_AND_STEP();
4631 idiv_byte(*destreg);
4632 break;
4635 DECODE_CLEAR_SEGOVR();
4636 END_OF_INSTR();
4639 /****************************************************************************
4640 REMARKS:
4641 Handles opcode 0xf7
4642 ****************************************************************************/
4643 static void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1))
4645 int mod, rl, rh;
4646 uint destoffset;
4648 START_OF_INSTR();
4649 FETCH_DECODE_MODRM(mod, rh, rl);
4650 DECODE_PRINTF(opF6_names[rh]);
4651 if (mod < 3) {
4653 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4654 u32 destval, srcval;
4656 DECODE_PRINTF("DWORD PTR ");
4657 destoffset = decode_rmXX_address(mod, rl);
4658 destval = fetch_data_long(destoffset);
4660 switch (rh) {
4661 case 0:
4662 DECODE_PRINTF(",");
4663 srcval = fetch_long_imm();
4664 DECODE_PRINTF2("%x\n", srcval);
4665 TRACE_AND_STEP();
4666 test_long(destval, srcval);
4667 break;
4668 case 1:
4669 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4670 HALT_SYS();
4671 break;
4672 case 2:
4673 DECODE_PRINTF("\n");
4674 TRACE_AND_STEP();
4675 destval = not_long(destval);
4676 store_data_long(destoffset, destval);
4677 break;
4678 case 3:
4679 DECODE_PRINTF("\n");
4680 TRACE_AND_STEP();
4681 destval = neg_long(destval);
4682 store_data_long(destoffset, destval);
4683 break;
4684 case 4:
4685 DECODE_PRINTF("\n");
4686 TRACE_AND_STEP();
4687 mul_long(destval);
4688 break;
4689 case 5:
4690 DECODE_PRINTF("\n");
4691 TRACE_AND_STEP();
4692 imul_long(destval);
4693 break;
4694 case 6:
4695 DECODE_PRINTF("\n");
4696 TRACE_AND_STEP();
4697 div_long(destval);
4698 break;
4699 case 7:
4700 DECODE_PRINTF("\n");
4701 TRACE_AND_STEP();
4702 idiv_long(destval);
4703 break;
4705 } else {
4706 u16 destval, srcval;
4708 DECODE_PRINTF("WORD PTR ");
4709 destoffset = decode_rmXX_address(mod, rl);
4710 destval = fetch_data_word(destoffset);
4712 switch (rh) {
4713 case 0: /* test word imm */
4714 DECODE_PRINTF(",");
4715 srcval = fetch_word_imm();
4716 DECODE_PRINTF2("%x\n", srcval);
4717 TRACE_AND_STEP();
4718 test_word(destval, srcval);
4719 break;
4720 case 1:
4721 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4722 HALT_SYS();
4723 break;
4724 case 2:
4725 DECODE_PRINTF("\n");
4726 TRACE_AND_STEP();
4727 destval = not_word(destval);
4728 store_data_word(destoffset, destval);
4729 break;
4730 case 3:
4731 DECODE_PRINTF("\n");
4732 TRACE_AND_STEP();
4733 destval = neg_word(destval);
4734 store_data_word(destoffset, destval);
4735 break;
4736 case 4:
4737 DECODE_PRINTF("\n");
4738 TRACE_AND_STEP();
4739 mul_word(destval);
4740 break;
4741 case 5:
4742 DECODE_PRINTF("\n");
4743 TRACE_AND_STEP();
4744 imul_word(destval);
4745 break;
4746 case 6:
4747 DECODE_PRINTF("\n");
4748 TRACE_AND_STEP();
4749 div_word(destval);
4750 break;
4751 case 7:
4752 DECODE_PRINTF("\n");
4753 TRACE_AND_STEP();
4754 idiv_word(destval);
4755 break;
4759 } else { /* mod=11 */
4761 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4762 u32 *destreg;
4763 u32 srcval;
4765 destreg = DECODE_RM_LONG_REGISTER(rl);
4767 switch (rh) {
4768 case 0: /* test word imm */
4769 DECODE_PRINTF(",");
4770 srcval = fetch_long_imm();
4771 DECODE_PRINTF2("%x\n", srcval);
4772 TRACE_AND_STEP();
4773 test_long(*destreg, srcval);
4774 break;
4775 case 1:
4776 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4777 HALT_SYS();
4778 break;
4779 case 2:
4780 DECODE_PRINTF("\n");
4781 TRACE_AND_STEP();
4782 *destreg = not_long(*destreg);
4783 break;
4784 case 3:
4785 DECODE_PRINTF("\n");
4786 TRACE_AND_STEP();
4787 *destreg = neg_long(*destreg);
4788 break;
4789 case 4:
4790 DECODE_PRINTF("\n");
4791 TRACE_AND_STEP();
4792 mul_long(*destreg); /*!!! */
4793 break;
4794 case 5:
4795 DECODE_PRINTF("\n");
4796 TRACE_AND_STEP();
4797 imul_long(*destreg);
4798 break;
4799 case 6:
4800 DECODE_PRINTF("\n");
4801 TRACE_AND_STEP();
4802 div_long(*destreg);
4803 break;
4804 case 7:
4805 DECODE_PRINTF("\n");
4806 TRACE_AND_STEP();
4807 idiv_long(*destreg);
4808 break;
4810 } else {
4811 u16 *destreg;
4812 u16 srcval;
4814 destreg = DECODE_RM_WORD_REGISTER(rl);
4816 switch (rh) {
4817 case 0: /* test word imm */
4818 DECODE_PRINTF(",");
4819 srcval = fetch_word_imm();
4820 DECODE_PRINTF2("%x\n", srcval);
4821 TRACE_AND_STEP();
4822 test_word(*destreg, srcval);
4823 break;
4824 case 1:
4825 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4826 HALT_SYS();
4827 break;
4828 case 2:
4829 DECODE_PRINTF("\n");
4830 TRACE_AND_STEP();
4831 *destreg = not_word(*destreg);
4832 break;
4833 case 3:
4834 DECODE_PRINTF("\n");
4835 TRACE_AND_STEP();
4836 *destreg = neg_word(*destreg);
4837 break;
4838 case 4:
4839 DECODE_PRINTF("\n");
4840 TRACE_AND_STEP();
4841 mul_word(*destreg); /*!!! */
4842 break;
4843 case 5:
4844 DECODE_PRINTF("\n");
4845 TRACE_AND_STEP();
4846 imul_word(*destreg);
4847 break;
4848 case 6:
4849 DECODE_PRINTF("\n");
4850 TRACE_AND_STEP();
4851 div_word(*destreg);
4852 break;
4853 case 7:
4854 DECODE_PRINTF("\n");
4855 TRACE_AND_STEP();
4856 idiv_word(*destreg);
4857 break;
4861 DECODE_CLEAR_SEGOVR();
4862 END_OF_INSTR();
4865 /****************************************************************************
4866 REMARKS:
4867 Handles opcode 0xf8
4868 ****************************************************************************/
4869 static void x86emuOp_clc(u8 X86EMU_UNUSED(op1))
4871 /* clear the carry flag. */
4872 START_OF_INSTR();
4873 DECODE_PRINTF("CLC\n");
4874 TRACE_AND_STEP();
4875 CLEAR_FLAG(F_CF);
4876 DECODE_CLEAR_SEGOVR();
4877 END_OF_INSTR();
4880 /****************************************************************************
4881 REMARKS:
4882 Handles opcode 0xf9
4883 ****************************************************************************/
4884 static void x86emuOp_stc(u8 X86EMU_UNUSED(op1))
4886 /* set the carry flag. */
4887 START_OF_INSTR();
4888 DECODE_PRINTF("STC\n");
4889 TRACE_AND_STEP();
4890 SET_FLAG(F_CF);
4891 DECODE_CLEAR_SEGOVR();
4892 END_OF_INSTR();
4895 /****************************************************************************
4896 REMARKS:
4897 Handles opcode 0xfa
4898 ****************************************************************************/
4899 static void x86emuOp_cli(u8 X86EMU_UNUSED(op1))
4901 /* clear interrupts. */
4902 START_OF_INSTR();
4903 DECODE_PRINTF("CLI\n");
4904 TRACE_AND_STEP();
4905 CLEAR_FLAG(F_IF);
4906 DECODE_CLEAR_SEGOVR();
4907 END_OF_INSTR();
4910 /****************************************************************************
4911 REMARKS:
4912 Handles opcode 0xfb
4913 ****************************************************************************/
4914 static void x86emuOp_sti(u8 X86EMU_UNUSED(op1))
4916 /* enable interrupts. */
4917 START_OF_INSTR();
4918 DECODE_PRINTF("STI\n");
4919 TRACE_AND_STEP();
4920 SET_FLAG(F_IF);
4921 DECODE_CLEAR_SEGOVR();
4922 END_OF_INSTR();
4925 /****************************************************************************
4926 REMARKS:
4927 Handles opcode 0xfc
4928 ****************************************************************************/
4929 static void x86emuOp_cld(u8 X86EMU_UNUSED(op1))
4931 /* clear interrupts. */
4932 START_OF_INSTR();
4933 DECODE_PRINTF("CLD\n");
4934 TRACE_AND_STEP();
4935 CLEAR_FLAG(F_DF);
4936 DECODE_CLEAR_SEGOVR();
4937 END_OF_INSTR();
4940 /****************************************************************************
4941 REMARKS:
4942 Handles opcode 0xfd
4943 ****************************************************************************/
4944 static void x86emuOp_std(u8 X86EMU_UNUSED(op1))
4946 /* clear interrupts. */
4947 START_OF_INSTR();
4948 DECODE_PRINTF("STD\n");
4949 TRACE_AND_STEP();
4950 SET_FLAG(F_DF);
4951 DECODE_CLEAR_SEGOVR();
4952 END_OF_INSTR();
4955 /****************************************************************************
4956 REMARKS:
4957 Handles opcode 0xfe
4958 ****************************************************************************/
4959 static void x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1))
4961 int mod, rh, rl;
4962 u8 destval;
4963 uint destoffset;
4964 u8 *destreg;
4966 /* Yet another special case instruction. */
4967 START_OF_INSTR();
4968 FETCH_DECODE_MODRM(mod, rh, rl);
4969 #ifdef DEBUG
4970 if (DEBUG_DECODE()) {
4971 /* XXX DECODE_PRINTF may be changed to something more
4972 general, so that it is important to leave the strings
4973 in the same format, even though the result is that the
4974 above test is done twice. */
4976 switch (rh) {
4977 case 0:
4978 DECODE_PRINTF("INC\t");
4979 break;
4980 case 1:
4981 DECODE_PRINTF("DEC\t");
4982 break;
4983 case 2:
4984 case 3:
4985 case 4:
4986 case 5:
4987 case 6:
4988 case 7:
4989 DECODE_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x\n", mod);
4990 HALT_SYS();
4991 break;
4994 #endif
4995 if (mod < 3) {
4996 DECODE_PRINTF("BYTE PTR ");
4997 destoffset = decode_rmXX_address(mod, rl);
4998 DECODE_PRINTF("\n");
4999 destval = fetch_data_byte(destoffset);
5000 TRACE_AND_STEP();
5001 if (rh == 0)
5002 destval = inc_byte(destval);
5003 else
5004 destval = dec_byte(destval);
5005 store_data_byte(destoffset, destval);
5006 } else {
5007 destreg = DECODE_RM_BYTE_REGISTER(rl);
5008 DECODE_PRINTF("\n");
5009 TRACE_AND_STEP();
5010 if (rh == 0)
5011 *destreg = inc_byte(*destreg);
5012 else
5013 *destreg = dec_byte(*destreg);
5015 DECODE_CLEAR_SEGOVR();
5016 END_OF_INSTR();
5019 /****************************************************************************
5020 REMARKS:
5021 Handles opcode 0xff
5022 ****************************************************************************/
5023 static void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1))
5025 int mod, rh, rl;
5026 uint destoffset = 0;
5027 u16 *destreg;
5028 u32 *destreg32;
5029 u16 destval,destval2;
5030 u32 destval32;
5032 /* Yet another special case instruction. */
5033 START_OF_INSTR();
5034 FETCH_DECODE_MODRM(mod, rh, rl);
5035 #ifdef DEBUG
5036 if (DEBUG_DECODE()) {
5037 /* XXX DECODE_PRINTF may be changed to something more
5038 general, so that it is important to leave the strings
5039 in the same format, even though the result is that the
5040 above test is done twice. */
5042 switch (rh) {
5043 case 0:
5044 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5045 DECODE_PRINTF("INC\tDWORD PTR ");
5046 } else {
5047 DECODE_PRINTF("INC\tWORD PTR ");
5049 break;
5050 case 1:
5051 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5052 DECODE_PRINTF("DEC\tDWORD PTR ");
5053 } else {
5054 DECODE_PRINTF("DEC\tWORD PTR ");
5056 break;
5057 case 2:
5058 DECODE_PRINTF("CALL\t ");
5059 break;
5060 case 3:
5061 DECODE_PRINTF("CALL\tFAR ");
5062 break;
5063 case 4:
5064 DECODE_PRINTF("JMP\t");
5065 break;
5066 case 5:
5067 DECODE_PRINTF("JMP\tFAR ");
5068 break;
5069 case 6:
5070 DECODE_PRINTF("PUSH\t");
5071 break;
5072 case 7:
5073 DECODE_PRINTF("ILLEGAL DECODING OF OPCODE FF\t");
5074 HALT_SYS();
5075 break;
5078 #endif
5079 if (mod < 3) {
5080 destoffset = decode_rmXX_address(mod, rl);
5081 DECODE_PRINTF("\n");
5082 switch (rh) {
5083 case 0: /* inc word ptr ... */
5084 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5085 destval32 = fetch_data_long(destoffset);
5086 TRACE_AND_STEP();
5087 destval32 = inc_long(destval32);
5088 store_data_long(destoffset, destval32);
5089 } else {
5090 destval = fetch_data_word(destoffset);
5091 TRACE_AND_STEP();
5092 destval = inc_word(destval);
5093 store_data_word(destoffset, destval);
5095 break;
5096 case 1: /* dec word ptr ... */
5097 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5098 destval32 = fetch_data_long(destoffset);
5099 TRACE_AND_STEP();
5100 destval32 = dec_long(destval32);
5101 store_data_long(destoffset, destval32);
5102 } else {
5103 destval = fetch_data_word(destoffset);
5104 TRACE_AND_STEP();
5105 destval = dec_word(destval);
5106 store_data_word(destoffset, destval);
5108 break;
5109 case 2: /* call word ptr ... */
5110 destval = fetch_data_word(destoffset);
5111 TRACE_AND_STEP();
5112 push_word(M.x86.R_IP);
5113 M.x86.R_IP = destval;
5114 break;
5115 case 3: /* call far ptr ... */
5116 destval = fetch_data_word(destoffset);
5117 destval2 = fetch_data_word(destoffset + 2);
5118 TRACE_AND_STEP();
5119 push_word(M.x86.R_CS);
5120 M.x86.R_CS = destval2;
5121 push_word(M.x86.R_IP);
5122 M.x86.R_IP = destval;
5123 break;
5124 case 4: /* jmp word ptr ... */
5125 destval = fetch_data_word(destoffset);
5126 JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, destval, " WORD ");
5127 TRACE_AND_STEP();
5128 M.x86.R_IP = destval;
5129 break;
5130 case 5: /* jmp far ptr ... */
5131 destval = fetch_data_word(destoffset);
5132 destval2 = fetch_data_word(destoffset + 2);
5133 JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, destval2, destval, " FAR ");
5134 TRACE_AND_STEP();
5135 M.x86.R_IP = destval;
5136 M.x86.R_CS = destval2;
5137 break;
5138 case 6: /* push word ptr ... */
5139 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5140 destval32 = fetch_data_long(destoffset);
5141 TRACE_AND_STEP();
5142 push_long(destval32);
5143 } else {
5144 destval = fetch_data_word(destoffset);
5145 TRACE_AND_STEP();
5146 push_word(destval);
5148 break;
5150 } else {
5151 switch (rh) {
5152 case 0:
5153 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5154 destreg32 = DECODE_RM_LONG_REGISTER(rl);
5155 DECODE_PRINTF("\n");
5156 TRACE_AND_STEP();
5157 *destreg32 = inc_long(*destreg32);
5158 } else {
5159 destreg = DECODE_RM_WORD_REGISTER(rl);
5160 DECODE_PRINTF("\n");
5161 TRACE_AND_STEP();
5162 *destreg = inc_word(*destreg);
5164 break;
5165 case 1:
5166 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5167 destreg32 = DECODE_RM_LONG_REGISTER(rl);
5168 DECODE_PRINTF("\n");
5169 TRACE_AND_STEP();
5170 *destreg32 = dec_long(*destreg32);
5171 } else {
5172 destreg = DECODE_RM_WORD_REGISTER(rl);
5173 DECODE_PRINTF("\n");
5174 TRACE_AND_STEP();
5175 *destreg = dec_word(*destreg);
5177 break;
5178 case 2: /* call word ptr ... */
5179 destreg = DECODE_RM_WORD_REGISTER(rl);
5180 DECODE_PRINTF("\n");
5181 TRACE_AND_STEP();
5182 push_word(M.x86.R_IP);
5183 M.x86.R_IP = *destreg;
5184 break;
5185 case 3: /* jmp far ptr ... */
5186 DECODE_PRINTF("OPERATION UNDEFINED 0XFF\n");
5187 TRACE_AND_STEP();
5188 HALT_SYS();
5189 break;
5191 case 4: /* jmp ... */
5192 destreg = DECODE_RM_WORD_REGISTER(rl);
5193 DECODE_PRINTF("\n");
5194 TRACE_AND_STEP();
5195 M.x86.R_IP = (u16) (*destreg);
5196 break;
5197 case 5: /* jmp far ptr ... */
5198 DECODE_PRINTF("OPERATION UNDEFINED 0XFF\n");
5199 TRACE_AND_STEP();
5200 HALT_SYS();
5201 break;
5202 case 6:
5203 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5204 destreg32 = DECODE_RM_LONG_REGISTER(rl);
5205 DECODE_PRINTF("\n");
5206 TRACE_AND_STEP();
5207 push_long(*destreg32);
5208 } else {
5209 destreg = DECODE_RM_WORD_REGISTER(rl);
5210 DECODE_PRINTF("\n");
5211 TRACE_AND_STEP();
5212 push_word(*destreg);
5214 break;
5217 DECODE_CLEAR_SEGOVR();
5218 END_OF_INSTR();
5221 /***************************************************************************
5222 * Single byte operation code table:
5223 **************************************************************************/
5224 void (*x86emu_optab[256])(u8) =
5226 /* 0x00 */ x86emuOp_genop_byte_RM_R,
5227 /* 0x01 */ x86emuOp_genop_word_RM_R,
5228 /* 0x02 */ x86emuOp_genop_byte_R_RM,
5229 /* 0x03 */ x86emuOp_genop_word_R_RM,
5230 /* 0x04 */ x86emuOp_genop_byte_AL_IMM,
5231 /* 0x05 */ x86emuOp_genop_word_AX_IMM,
5232 /* 0x06 */ x86emuOp_push_ES,
5233 /* 0x07 */ x86emuOp_pop_ES,
5235 /* 0x08 */ x86emuOp_genop_byte_RM_R,
5236 /* 0x09 */ x86emuOp_genop_word_RM_R,
5237 /* 0x0a */ x86emuOp_genop_byte_R_RM,
5238 /* 0x0b */ x86emuOp_genop_word_R_RM,
5239 /* 0x0c */ x86emuOp_genop_byte_AL_IMM,
5240 /* 0x0d */ x86emuOp_genop_word_AX_IMM,
5241 /* 0x0e */ x86emuOp_push_CS,
5242 /* 0x0f */ x86emuOp_two_byte,
5244 /* 0x10 */ x86emuOp_genop_byte_RM_R,
5245 /* 0x11 */ x86emuOp_genop_word_RM_R,
5246 /* 0x12 */ x86emuOp_genop_byte_R_RM,
5247 /* 0x13 */ x86emuOp_genop_word_R_RM,
5248 /* 0x14 */ x86emuOp_genop_byte_AL_IMM,
5249 /* 0x15 */ x86emuOp_genop_word_AX_IMM,
5250 /* 0x16 */ x86emuOp_push_SS,
5251 /* 0x17 */ x86emuOp_pop_SS,
5253 /* 0x18 */ x86emuOp_genop_byte_RM_R,
5254 /* 0x19 */ x86emuOp_genop_word_RM_R,
5255 /* 0x1a */ x86emuOp_genop_byte_R_RM,
5256 /* 0x1b */ x86emuOp_genop_word_R_RM,
5257 /* 0x1c */ x86emuOp_genop_byte_AL_IMM,
5258 /* 0x1d */ x86emuOp_genop_word_AX_IMM,
5259 /* 0x1e */ x86emuOp_push_DS,
5260 /* 0x1f */ x86emuOp_pop_DS,
5262 /* 0x20 */ x86emuOp_genop_byte_RM_R,
5263 /* 0x21 */ x86emuOp_genop_word_RM_R,
5264 /* 0x22 */ x86emuOp_genop_byte_R_RM,
5265 /* 0x23 */ x86emuOp_genop_word_R_RM,
5266 /* 0x24 */ x86emuOp_genop_byte_AL_IMM,
5267 /* 0x25 */ x86emuOp_genop_word_AX_IMM,
5268 /* 0x26 */ x86emuOp_segovr_ES,
5269 /* 0x27 */ x86emuOp_daa,
5271 /* 0x28 */ x86emuOp_genop_byte_RM_R,
5272 /* 0x29 */ x86emuOp_genop_word_RM_R,
5273 /* 0x2a */ x86emuOp_genop_byte_R_RM,
5274 /* 0x2b */ x86emuOp_genop_word_R_RM,
5275 /* 0x2c */ x86emuOp_genop_byte_AL_IMM,
5276 /* 0x2d */ x86emuOp_genop_word_AX_IMM,
5277 /* 0x2e */ x86emuOp_segovr_CS,
5278 /* 0x2f */ x86emuOp_das,
5280 /* 0x30 */ x86emuOp_genop_byte_RM_R,
5281 /* 0x31 */ x86emuOp_genop_word_RM_R,
5282 /* 0x32 */ x86emuOp_genop_byte_R_RM,
5283 /* 0x33 */ x86emuOp_genop_word_R_RM,
5284 /* 0x34 */ x86emuOp_genop_byte_AL_IMM,
5285 /* 0x35 */ x86emuOp_genop_word_AX_IMM,
5286 /* 0x36 */ x86emuOp_segovr_SS,
5287 /* 0x37 */ x86emuOp_aaa,
5289 /* 0x38 */ x86emuOp_genop_byte_RM_R,
5290 /* 0x39 */ x86emuOp_genop_word_RM_R,
5291 /* 0x3a */ x86emuOp_genop_byte_R_RM,
5292 /* 0x3b */ x86emuOp_genop_word_R_RM,
5293 /* 0x3c */ x86emuOp_genop_byte_AL_IMM,
5294 /* 0x3d */ x86emuOp_genop_word_AX_IMM,
5295 /* 0x3e */ x86emuOp_segovr_DS,
5296 /* 0x3f */ x86emuOp_aas,
5298 /* 0x40 */ x86emuOp_inc_register,
5299 /* 0x41 */ x86emuOp_inc_register,
5300 /* 0x42 */ x86emuOp_inc_register,
5301 /* 0x43 */ x86emuOp_inc_register,
5302 /* 0x44 */ x86emuOp_inc_register,
5303 /* 0x45 */ x86emuOp_inc_register,
5304 /* 0x46 */ x86emuOp_inc_register,
5305 /* 0x47 */ x86emuOp_inc_register,
5307 /* 0x48 */ x86emuOp_dec_register,
5308 /* 0x49 */ x86emuOp_dec_register,
5309 /* 0x4a */ x86emuOp_dec_register,
5310 /* 0x4b */ x86emuOp_dec_register,
5311 /* 0x4c */ x86emuOp_dec_register,
5312 /* 0x4d */ x86emuOp_dec_register,
5313 /* 0x4e */ x86emuOp_dec_register,
5314 /* 0x4f */ x86emuOp_dec_register,
5316 /* 0x50 */ x86emuOp_push_register,
5317 /* 0x51 */ x86emuOp_push_register,
5318 /* 0x52 */ x86emuOp_push_register,
5319 /* 0x53 */ x86emuOp_push_register,
5320 /* 0x54 */ x86emuOp_push_register,
5321 /* 0x55 */ x86emuOp_push_register,
5322 /* 0x56 */ x86emuOp_push_register,
5323 /* 0x57 */ x86emuOp_push_register,
5325 /* 0x58 */ x86emuOp_pop_register,
5326 /* 0x59 */ x86emuOp_pop_register,
5327 /* 0x5a */ x86emuOp_pop_register,
5328 /* 0x5b */ x86emuOp_pop_register,
5329 /* 0x5c */ x86emuOp_pop_register,
5330 /* 0x5d */ x86emuOp_pop_register,
5331 /* 0x5e */ x86emuOp_pop_register,
5332 /* 0x5f */ x86emuOp_pop_register,
5334 /* 0x60 */ x86emuOp_push_all,
5335 /* 0x61 */ x86emuOp_pop_all,
5336 /* 0x62 */ x86emuOp_illegal_op, /* bound */
5337 /* 0x63 */ x86emuOp_illegal_op, /* arpl */
5338 /* 0x64 */ x86emuOp_segovr_FS,
5339 /* 0x65 */ x86emuOp_segovr_GS,
5340 /* 0x66 */ x86emuOp_prefix_data,
5341 /* 0x67 */ x86emuOp_prefix_addr,
5343 /* 0x68 */ x86emuOp_push_word_IMM,
5344 /* 0x69 */ x86emuOp_imul_word_IMM,
5345 /* 0x6a */ x86emuOp_push_byte_IMM,
5346 /* 0x6b */ x86emuOp_imul_byte_IMM,
5347 /* 0x6c */ x86emuOp_ins_byte,
5348 /* 0x6d */ x86emuOp_ins_word,
5349 /* 0x6e */ x86emuOp_outs_byte,
5350 /* 0x6f */ x86emuOp_outs_word,
5352 /* 0x70 */ x86emuOp_jump_near_cond,
5353 /* 0x71 */ x86emuOp_jump_near_cond,
5354 /* 0x72 */ x86emuOp_jump_near_cond,
5355 /* 0x73 */ x86emuOp_jump_near_cond,
5356 /* 0x74 */ x86emuOp_jump_near_cond,
5357 /* 0x75 */ x86emuOp_jump_near_cond,
5358 /* 0x76 */ x86emuOp_jump_near_cond,
5359 /* 0x77 */ x86emuOp_jump_near_cond,
5361 /* 0x78 */ x86emuOp_jump_near_cond,
5362 /* 0x79 */ x86emuOp_jump_near_cond,
5363 /* 0x7a */ x86emuOp_jump_near_cond,
5364 /* 0x7b */ x86emuOp_jump_near_cond,
5365 /* 0x7c */ x86emuOp_jump_near_cond,
5366 /* 0x7d */ x86emuOp_jump_near_cond,
5367 /* 0x7e */ x86emuOp_jump_near_cond,
5368 /* 0x7f */ x86emuOp_jump_near_cond,
5370 /* 0x80 */ x86emuOp_opc80_byte_RM_IMM,
5371 /* 0x81 */ x86emuOp_opc81_word_RM_IMM,
5372 /* 0x82 */ x86emuOp_opc82_byte_RM_IMM,
5373 /* 0x83 */ x86emuOp_opc83_word_RM_IMM,
5374 /* 0x84 */ x86emuOp_test_byte_RM_R,
5375 /* 0x85 */ x86emuOp_test_word_RM_R,
5376 /* 0x86 */ x86emuOp_xchg_byte_RM_R,
5377 /* 0x87 */ x86emuOp_xchg_word_RM_R,
5379 /* 0x88 */ x86emuOp_mov_byte_RM_R,
5380 /* 0x89 */ x86emuOp_mov_word_RM_R,
5381 /* 0x8a */ x86emuOp_mov_byte_R_RM,
5382 /* 0x8b */ x86emuOp_mov_word_R_RM,
5383 /* 0x8c */ x86emuOp_mov_word_RM_SR,
5384 /* 0x8d */ x86emuOp_lea_word_R_M,
5385 /* 0x8e */ x86emuOp_mov_word_SR_RM,
5386 /* 0x8f */ x86emuOp_pop_RM,
5388 /* 0x90 */ x86emuOp_nop,
5389 /* 0x91 */ x86emuOp_xchg_word_AX_register,
5390 /* 0x92 */ x86emuOp_xchg_word_AX_register,
5391 /* 0x93 */ x86emuOp_xchg_word_AX_register,
5392 /* 0x94 */ x86emuOp_xchg_word_AX_register,
5393 /* 0x95 */ x86emuOp_xchg_word_AX_register,
5394 /* 0x96 */ x86emuOp_xchg_word_AX_register,
5395 /* 0x97 */ x86emuOp_xchg_word_AX_register,
5397 /* 0x98 */ x86emuOp_cbw,
5398 /* 0x99 */ x86emuOp_cwd,
5399 /* 0x9a */ x86emuOp_call_far_IMM,
5400 /* 0x9b */ x86emuOp_wait,
5401 /* 0x9c */ x86emuOp_pushf_word,
5402 /* 0x9d */ x86emuOp_popf_word,
5403 /* 0x9e */ x86emuOp_sahf,
5404 /* 0x9f */ x86emuOp_lahf,
5406 /* 0xa0 */ x86emuOp_mov_AL_M_IMM,
5407 /* 0xa1 */ x86emuOp_mov_AX_M_IMM,
5408 /* 0xa2 */ x86emuOp_mov_M_AL_IMM,
5409 /* 0xa3 */ x86emuOp_mov_M_AX_IMM,
5410 /* 0xa4 */ x86emuOp_movs_byte,
5411 /* 0xa5 */ x86emuOp_movs_word,
5412 /* 0xa6 */ x86emuOp_cmps_byte,
5413 /* 0xa7 */ x86emuOp_cmps_word,
5414 /* 0xa8 */ x86emuOp_test_AL_IMM,
5415 /* 0xa9 */ x86emuOp_test_AX_IMM,
5416 /* 0xaa */ x86emuOp_stos_byte,
5417 /* 0xab */ x86emuOp_stos_word,
5418 /* 0xac */ x86emuOp_lods_byte,
5419 /* 0xad */ x86emuOp_lods_word,
5420 /* 0xac */ x86emuOp_scas_byte,
5421 /* 0xad */ x86emuOp_scas_word,
5423 /* 0xb0 */ x86emuOp_mov_byte_register_IMM,
5424 /* 0xb1 */ x86emuOp_mov_byte_register_IMM,
5425 /* 0xb2 */ x86emuOp_mov_byte_register_IMM,
5426 /* 0xb3 */ x86emuOp_mov_byte_register_IMM,
5427 /* 0xb4 */ x86emuOp_mov_byte_register_IMM,
5428 /* 0xb5 */ x86emuOp_mov_byte_register_IMM,
5429 /* 0xb6 */ x86emuOp_mov_byte_register_IMM,
5430 /* 0xb7 */ x86emuOp_mov_byte_register_IMM,
5432 /* 0xb8 */ x86emuOp_mov_word_register_IMM,
5433 /* 0xb9 */ x86emuOp_mov_word_register_IMM,
5434 /* 0xba */ x86emuOp_mov_word_register_IMM,
5435 /* 0xbb */ x86emuOp_mov_word_register_IMM,
5436 /* 0xbc */ x86emuOp_mov_word_register_IMM,
5437 /* 0xbd */ x86emuOp_mov_word_register_IMM,
5438 /* 0xbe */ x86emuOp_mov_word_register_IMM,
5439 /* 0xbf */ x86emuOp_mov_word_register_IMM,
5441 /* 0xc0 */ x86emuOp_opcC0_byte_RM_MEM,
5442 /* 0xc1 */ x86emuOp_opcC1_word_RM_MEM,
5443 /* 0xc2 */ x86emuOp_ret_near_IMM,
5444 /* 0xc3 */ x86emuOp_ret_near,
5445 /* 0xc4 */ x86emuOp_les_R_IMM,
5446 /* 0xc5 */ x86emuOp_lds_R_IMM,
5447 /* 0xc6 */ x86emuOp_mov_byte_RM_IMM,
5448 /* 0xc7 */ x86emuOp_mov_word_RM_IMM,
5449 /* 0xc8 */ x86emuOp_enter,
5450 /* 0xc9 */ x86emuOp_leave,
5451 /* 0xca */ x86emuOp_ret_far_IMM,
5452 /* 0xcb */ x86emuOp_ret_far,
5453 /* 0xcc */ x86emuOp_int3,
5454 /* 0xcd */ x86emuOp_int_IMM,
5455 /* 0xce */ x86emuOp_into,
5456 /* 0xcf */ x86emuOp_iret,
5458 /* 0xd0 */ x86emuOp_opcD0_byte_RM_1,
5459 /* 0xd1 */ x86emuOp_opcD1_word_RM_1,
5460 /* 0xd2 */ x86emuOp_opcD2_byte_RM_CL,
5461 /* 0xd3 */ x86emuOp_opcD3_word_RM_CL,
5462 /* 0xd4 */ x86emuOp_aam,
5463 /* 0xd5 */ x86emuOp_aad,
5464 /* 0xd6 */ x86emuOp_illegal_op, /* Undocumented SETALC instruction */
5465 /* 0xd7 */ x86emuOp_xlat,
5466 /* 0xd8 */ x86emuOp_esc_coprocess_d8,
5467 /* 0xd9 */ x86emuOp_esc_coprocess_d9,
5468 /* 0xda */ x86emuOp_esc_coprocess_da,
5469 /* 0xdb */ x86emuOp_esc_coprocess_db,
5470 /* 0xdc */ x86emuOp_esc_coprocess_dc,
5471 /* 0xdd */ x86emuOp_esc_coprocess_dd,
5472 /* 0xde */ x86emuOp_esc_coprocess_de,
5473 /* 0xdf */ x86emuOp_esc_coprocess_df,
5475 /* 0xe0 */ x86emuOp_loopne,
5476 /* 0xe1 */ x86emuOp_loope,
5477 /* 0xe2 */ x86emuOp_loop,
5478 /* 0xe3 */ x86emuOp_jcxz,
5479 /* 0xe4 */ x86emuOp_in_byte_AL_IMM,
5480 /* 0xe5 */ x86emuOp_in_word_AX_IMM,
5481 /* 0xe6 */ x86emuOp_out_byte_IMM_AL,
5482 /* 0xe7 */ x86emuOp_out_word_IMM_AX,
5484 /* 0xe8 */ x86emuOp_call_near_IMM,
5485 /* 0xe9 */ x86emuOp_jump_near_IMM,
5486 /* 0xea */ x86emuOp_jump_far_IMM,
5487 /* 0xeb */ x86emuOp_jump_byte_IMM,
5488 /* 0xec */ x86emuOp_in_byte_AL_DX,
5489 /* 0xed */ x86emuOp_in_word_AX_DX,
5490 /* 0xee */ x86emuOp_out_byte_DX_AL,
5491 /* 0xef */ x86emuOp_out_word_DX_AX,
5493 /* 0xf0 */ x86emuOp_lock,
5494 /* 0xf1 */ x86emuOp_illegal_op,
5495 /* 0xf2 */ x86emuOp_repne,
5496 /* 0xf3 */ x86emuOp_repe,
5497 /* 0xf4 */ x86emuOp_halt,
5498 /* 0xf5 */ x86emuOp_cmc,
5499 /* 0xf6 */ x86emuOp_opcF6_byte_RM,
5500 /* 0xf7 */ x86emuOp_opcF7_word_RM,
5502 /* 0xf8 */ x86emuOp_clc,
5503 /* 0xf9 */ x86emuOp_stc,
5504 /* 0xfa */ x86emuOp_cli,
5505 /* 0xfb */ x86emuOp_sti,
5506 /* 0xfc */ x86emuOp_cld,
5507 /* 0xfd */ x86emuOp_std,
5508 /* 0xfe */ x86emuOp_opcFE_byte_RM,
5509 /* 0xff */ x86emuOp_opcFF_word_RM,