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