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