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