blob: d63c99fd218d0f555672e8233d4ee7132d0a5bec [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>
Michal Simek5b4de932007-08-15 21:15:05 +020079#include "x86emu/x86emui.h"
80
Jason Jinece92f82007-07-06 08:34:56 +080081/*----------------------------- Implementation ----------------------------*/
82
83/* constant arrays to do several instructions in just one function */
84
85#ifdef DEBUG
86static char *x86emu_GenOpName[8] = {
87 "ADD", "OR", "ADC", "SBB", "AND", "SUB", "XOR", "CMP"};
88#endif
89
90/* used by several opcodes */
Anatolij Gustschin30c6a242008-02-15 20:09:01 +010091static u8 (*genop_byte_operation[])(u8 d, u8 s) __attribute__ ((section(GOT2_TYPE))) =
Jason Jinece92f82007-07-06 08:34:56 +080092{
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +020093 add_byte, /* 00 */
94 or_byte, /* 01 */
95 adc_byte, /* 02 */
96 sbb_byte, /* 03 */
97 and_byte, /* 04 */
98 sub_byte, /* 05 */
99 xor_byte, /* 06 */
100 cmp_byte, /* 07 */
Jason Jinece92f82007-07-06 08:34:56 +0800101};
102
Anatolij Gustschin30c6a242008-02-15 20:09:01 +0100103static u16 (*genop_word_operation[])(u16 d, u16 s) __attribute__ ((section(GOT2_TYPE))) =
Jason Jinece92f82007-07-06 08:34:56 +0800104{
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200105 add_word, /*00 */
106 or_word, /*01 */
107 adc_word, /*02 */
108 sbb_word, /*03 */
109 and_word, /*04 */
110 sub_word, /*05 */
111 xor_word, /*06 */
112 cmp_word, /*07 */
Jason Jinece92f82007-07-06 08:34:56 +0800113};
114
Anatolij Gustschin30c6a242008-02-15 20:09:01 +0100115static u32 (*genop_long_operation[])(u32 d, u32 s) __attribute__ ((section(GOT2_TYPE))) =
Jason Jinece92f82007-07-06 08:34:56 +0800116{
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200117 add_long, /*00 */
118 or_long, /*01 */
119 adc_long, /*02 */
120 sbb_long, /*03 */
121 and_long, /*04 */
122 sub_long, /*05 */
123 xor_long, /*06 */
124 cmp_long, /*07 */
Jason Jinece92f82007-07-06 08:34:56 +0800125};
126
127/* used by opcodes 80, c0, d0, and d2. */
Anatolij Gustschin30c6a242008-02-15 20:09:01 +0100128static u8(*opcD0_byte_operation[])(u8 d, u8 s) __attribute__ ((section(GOT2_TYPE))) =
Jason Jinece92f82007-07-06 08:34:56 +0800129{
130 rol_byte,
131 ror_byte,
132 rcl_byte,
133 rcr_byte,
134 shl_byte,
135 shr_byte,
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200136 shl_byte, /* sal_byte === shl_byte by definition */
Jason Jinece92f82007-07-06 08:34:56 +0800137 sar_byte,
138};
139
140/* used by opcodes c1, d1, and d3. */
Anatolij Gustschin30c6a242008-02-15 20:09:01 +0100141static u16(*opcD1_word_operation[])(u16 s, u8 d) __attribute__ ((section(GOT2_TYPE))) =
Jason Jinece92f82007-07-06 08:34:56 +0800142{
143 rol_word,
144 ror_word,
145 rcl_word,
146 rcr_word,
147 shl_word,
148 shr_word,
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200149 shl_word, /* sal_byte === shl_byte by definition */
Jason Jinece92f82007-07-06 08:34:56 +0800150 sar_word,
151};
152
153/* used by opcodes c1, d1, and d3. */
Anatolij Gustschin30c6a242008-02-15 20:09:01 +0100154static u32 (*opcD1_long_operation[])(u32 s, u8 d) __attribute__ ((section(GOT2_TYPE))) =
Jason Jinece92f82007-07-06 08:34:56 +0800155{
156 rol_long,
157 ror_long,
158 rcl_long,
159 rcr_long,
160 shl_long,
161 shr_long,
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200162 shl_long, /* sal_byte === shl_byte by definition */
Jason Jinece92f82007-07-06 08:34:56 +0800163 sar_long,
164};
165
166#ifdef DEBUG
167
168static char *opF6_names[8] =
169 { "TEST\t", "", "NOT\t", "NEG\t", "MUL\t", "IMUL\t", "DIV\t", "IDIV\t" };
170
171#endif
172
173/****************************************************************************
174PARAMETERS:
175op1 - Instruction op code
176
177REMARKS:
178Handles illegal opcodes.
179****************************************************************************/
180void x86emuOp_illegal_op(
181 u8 op1)
182{
183 START_OF_INSTR();
184 if (M.x86.R_SP != 0) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200185 DECODE_PRINTF("ILLEGAL X86 OPCODE\n");
186 TRACE_REGS();
187 DB( printk("%04x:%04x: %02X ILLEGAL X86 OPCODE!\n",
188 M.x86.R_CS, M.x86.R_IP-1,op1));
189 HALT_SYS();
190 }
Jason Jinece92f82007-07-06 08:34:56 +0800191 else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200192 /* If we get here, it means the stack pointer is back to zero
193 * so we are just returning from an emulator service call
194 * so therte is no need to display an error message. We trap
195 * the emulator with an 0xF1 opcode to finish the service
196 * call.
197 */
198 X86EMU_halt_sys();
199 }
Jason Jinece92f82007-07-06 08:34:56 +0800200 END_OF_INSTR();
201}
202
203/****************************************************************************
204REMARKS:
205Handles opcodes 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38
206****************************************************************************/
207void x86emuOp_genop_byte_RM_R(u8 op1)
208{
209 int mod, rl, rh;
210 uint destoffset;
211 u8 *destreg, *srcreg;
212 u8 destval;
213
214 op1 = (op1 >> 3) & 0x7;
215
216 START_OF_INSTR();
217 DECODE_PRINTF(x86emu_GenOpName[op1]);
218 DECODE_PRINTF("\t");
219 FETCH_DECODE_MODRM(mod, rh, rl);
220 if(mod<3)
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200221 { destoffset = decode_rmXX_address(mod,rl);
222 DECODE_PRINTF(",");
223 destval = fetch_data_byte(destoffset);
224 srcreg = DECODE_RM_BYTE_REGISTER(rh);
225 DECODE_PRINTF("\n");
226 TRACE_AND_STEP();
227 destval = genop_byte_operation[op1](destval, *srcreg);
228 store_data_byte(destoffset, destval);
229 }
Jason Jinece92f82007-07-06 08:34:56 +0800230 else
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200231 { /* register to register */
232 destreg = DECODE_RM_BYTE_REGISTER(rl);
233 DECODE_PRINTF(",");
234 srcreg = DECODE_RM_BYTE_REGISTER(rh);
235 DECODE_PRINTF("\n");
236 TRACE_AND_STEP();
237 *destreg = genop_byte_operation[op1](*destreg, *srcreg);
238 }
Jason Jinece92f82007-07-06 08:34:56 +0800239 DECODE_CLEAR_SEGOVR();
240 END_OF_INSTR();
241}
242
243/****************************************************************************
244REMARKS:
245Handles opcodes 0x01, 0x09, 0x11, 0x19, 0x21, 0x29, 0x31, 0x39
246****************************************************************************/
247void x86emuOp_genop_word_RM_R(u8 op1)
248{
249 int mod, rl, rh;
250 uint destoffset;
251
252 op1 = (op1 >> 3) & 0x7;
253
254 START_OF_INSTR();
255 DECODE_PRINTF(x86emu_GenOpName[op1]);
256 DECODE_PRINTF("\t");
257 FETCH_DECODE_MODRM(mod, rh, rl);
258
259 if(mod<3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200260 destoffset = decode_rmXX_address(mod,rl);
261 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
262 u32 destval;
263 u32 *srcreg;
Jason Jinece92f82007-07-06 08:34:56 +0800264
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200265 DECODE_PRINTF(",");
266 destval = fetch_data_long(destoffset);
267 srcreg = DECODE_RM_LONG_REGISTER(rh);
268 DECODE_PRINTF("\n");
269 TRACE_AND_STEP();
270 destval = genop_long_operation[op1](destval, *srcreg);
271 store_data_long(destoffset, destval);
272 } else {
273 u16 destval;
274 u16 *srcreg;
Jason Jinece92f82007-07-06 08:34:56 +0800275
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200276 DECODE_PRINTF(",");
277 destval = fetch_data_word(destoffset);
278 srcreg = DECODE_RM_WORD_REGISTER(rh);
279 DECODE_PRINTF("\n");
280 TRACE_AND_STEP();
281 destval = genop_word_operation[op1](destval, *srcreg);
282 store_data_word(destoffset, destval);
283 }
284 } else { /* register to register */
285 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
286 u32 *destreg,*srcreg;
Jason Jinece92f82007-07-06 08:34:56 +0800287
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200288 destreg = DECODE_RM_LONG_REGISTER(rl);
289 DECODE_PRINTF(",");
290 srcreg = DECODE_RM_LONG_REGISTER(rh);
291 DECODE_PRINTF("\n");
292 TRACE_AND_STEP();
293 *destreg = genop_long_operation[op1](*destreg, *srcreg);
294 } else {
295 u16 *destreg,*srcreg;
Jason Jinece92f82007-07-06 08:34:56 +0800296
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200297 destreg = DECODE_RM_WORD_REGISTER(rl);
298 DECODE_PRINTF(",");
299 srcreg = DECODE_RM_WORD_REGISTER(rh);
300 DECODE_PRINTF("\n");
301 TRACE_AND_STEP();
302 *destreg = genop_word_operation[op1](*destreg, *srcreg);
303 }
Jason Jinece92f82007-07-06 08:34:56 +0800304 }
305 DECODE_CLEAR_SEGOVR();
306 END_OF_INSTR();
307}
308
309/****************************************************************************
310REMARKS:
311Handles opcodes 0x02, 0x0a, 0x12, 0x1a, 0x22, 0x2a, 0x32, 0x3a
312****************************************************************************/
313void x86emuOp_genop_byte_R_RM(u8 op1)
314{
315 int mod, rl, rh;
316 u8 *destreg, *srcreg;
317 uint srcoffset;
318 u8 srcval;
319
320 op1 = (op1 >> 3) & 0x7;
321
322 START_OF_INSTR();
323 DECODE_PRINTF(x86emu_GenOpName[op1]);
324 DECODE_PRINTF("\t");
325 FETCH_DECODE_MODRM(mod, rh, rl);
326 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200327 destreg = DECODE_RM_BYTE_REGISTER(rh);
328 DECODE_PRINTF(",");
329 srcoffset = decode_rmXX_address(mod,rl);
330 srcval = fetch_data_byte(srcoffset);
331 } else { /* register to register */
332 destreg = DECODE_RM_BYTE_REGISTER(rh);
333 DECODE_PRINTF(",");
334 srcreg = DECODE_RM_BYTE_REGISTER(rl);
335 srcval = *srcreg;
Jason Jinece92f82007-07-06 08:34:56 +0800336 }
337 DECODE_PRINTF("\n");
338 TRACE_AND_STEP();
339 *destreg = genop_byte_operation[op1](*destreg, srcval);
340
341 DECODE_CLEAR_SEGOVR();
342 END_OF_INSTR();
343}
344
345/****************************************************************************
346REMARKS:
347Handles opcodes 0x03, 0x0b, 0x13, 0x1b, 0x23, 0x2b, 0x33, 0x3b
348****************************************************************************/
349void x86emuOp_genop_word_R_RM(u8 op1)
350{
351 int mod, rl, rh;
352 uint srcoffset;
353 u32 *destreg32, srcval;
354 u16 *destreg;
355
356 op1 = (op1 >> 3) & 0x7;
357
358 START_OF_INSTR();
359 DECODE_PRINTF(x86emu_GenOpName[op1]);
360 DECODE_PRINTF("\t");
361 FETCH_DECODE_MODRM(mod, rh, rl);
362 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200363 srcoffset = decode_rmXX_address(mod,rl);
364 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
365 destreg32 = DECODE_RM_LONG_REGISTER(rh);
366 DECODE_PRINTF(",");
367 srcval = fetch_data_long(srcoffset);
368 DECODE_PRINTF("\n");
369 TRACE_AND_STEP();
370 *destreg32 = genop_long_operation[op1](*destreg32, srcval);
371 } else {
372 destreg = DECODE_RM_WORD_REGISTER(rh);
373 DECODE_PRINTF(",");
374 srcval = fetch_data_word(srcoffset);
375 DECODE_PRINTF("\n");
376 TRACE_AND_STEP();
377 *destreg = genop_word_operation[op1](*destreg, srcval);
378 }
379 } else { /* register to register */
380 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
381 u32 *srcreg;
382 destreg32 = DECODE_RM_LONG_REGISTER(rh);
383 DECODE_PRINTF(",");
384 srcreg = DECODE_RM_LONG_REGISTER(rl);
385 DECODE_PRINTF("\n");
386 TRACE_AND_STEP();
387 *destreg32 = genop_long_operation[op1](*destreg32, *srcreg);
388 } else {
389 u16 *srcreg;
390 destreg = DECODE_RM_WORD_REGISTER(rh);
391 DECODE_PRINTF(",");
392 srcreg = DECODE_RM_WORD_REGISTER(rl);
393 DECODE_PRINTF("\n");
394 TRACE_AND_STEP();
395 *destreg = genop_word_operation[op1](*destreg, *srcreg);
396 }
Jason Jinece92f82007-07-06 08:34:56 +0800397 }
398 DECODE_CLEAR_SEGOVR();
399 END_OF_INSTR();
400}
401
402/****************************************************************************
403REMARKS:
404Handles opcodes 0x04, 0x0c, 0x14, 0x1c, 0x24, 0x2c, 0x34, 0x3c
405****************************************************************************/
406void x86emuOp_genop_byte_AL_IMM(u8 op1)
407{
408 u8 srcval;
409
410 op1 = (op1 >> 3) & 0x7;
411
412 START_OF_INSTR();
413 DECODE_PRINTF(x86emu_GenOpName[op1]);
414 DECODE_PRINTF("\tAL,");
415 srcval = fetch_byte_imm();
416 DECODE_PRINTF2("%x\n", srcval);
417 TRACE_AND_STEP();
418 M.x86.R_AL = genop_byte_operation[op1](M.x86.R_AL, srcval);
419 DECODE_CLEAR_SEGOVR();
420 END_OF_INSTR();
421}
422
423/****************************************************************************
424REMARKS:
425Handles opcodes 0x05, 0x0d, 0x15, 0x1d, 0x25, 0x2d, 0x35, 0x3d
426****************************************************************************/
427void x86emuOp_genop_word_AX_IMM(u8 op1)
428{
429 u32 srcval;
430
431 op1 = (op1 >> 3) & 0x7;
432
433 START_OF_INSTR();
434 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200435 DECODE_PRINTF(x86emu_GenOpName[op1]);
436 DECODE_PRINTF("\tEAX,");
437 srcval = fetch_long_imm();
Jason Jinece92f82007-07-06 08:34:56 +0800438 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200439 DECODE_PRINTF(x86emu_GenOpName[op1]);
440 DECODE_PRINTF("\tAX,");
441 srcval = fetch_word_imm();
Jason Jinece92f82007-07-06 08:34:56 +0800442 }
443 DECODE_PRINTF2("%x\n", srcval);
444 TRACE_AND_STEP();
445 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200446 M.x86.R_EAX = genop_long_operation[op1](M.x86.R_EAX, srcval);
Jason Jinece92f82007-07-06 08:34:56 +0800447 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200448 M.x86.R_AX = genop_word_operation[op1](M.x86.R_AX, (u16)srcval);
Jason Jinece92f82007-07-06 08:34:56 +0800449 }
450 DECODE_CLEAR_SEGOVR();
451 END_OF_INSTR();
452}
453
454/****************************************************************************
455REMARKS:
456Handles opcode 0x06
457****************************************************************************/
458void x86emuOp_push_ES(u8 X86EMU_UNUSED(op1))
459{
460 START_OF_INSTR();
461 DECODE_PRINTF("PUSH\tES\n");
462 TRACE_AND_STEP();
463 push_word(M.x86.R_ES);
464 DECODE_CLEAR_SEGOVR();
465 END_OF_INSTR();
466}
467
468/****************************************************************************
469REMARKS:
470Handles opcode 0x07
471****************************************************************************/
472void x86emuOp_pop_ES(u8 X86EMU_UNUSED(op1))
473{
474 START_OF_INSTR();
475 DECODE_PRINTF("POP\tES\n");
476 TRACE_AND_STEP();
477 M.x86.R_ES = pop_word();
478 DECODE_CLEAR_SEGOVR();
479 END_OF_INSTR();
480}
481
482/****************************************************************************
483REMARKS:
484Handles opcode 0x0e
485****************************************************************************/
486void x86emuOp_push_CS(u8 X86EMU_UNUSED(op1))
487{
488 START_OF_INSTR();
489 DECODE_PRINTF("PUSH\tCS\n");
490 TRACE_AND_STEP();
491 push_word(M.x86.R_CS);
492 DECODE_CLEAR_SEGOVR();
493 END_OF_INSTR();
494}
495
496/****************************************************************************
497REMARKS:
498Handles opcode 0x0f. Escape for two-byte opcode (286 or better)
499****************************************************************************/
500void x86emuOp_two_byte(u8 X86EMU_UNUSED(op1))
501{
502 u8 op2 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
503 INC_DECODED_INST_LEN(1);
504 (*x86emu_optab2[op2])(op2);
505}
506
507/****************************************************************************
508REMARKS:
509Handles opcode 0x16
510****************************************************************************/
511void x86emuOp_push_SS(u8 X86EMU_UNUSED(op1))
512{
513 START_OF_INSTR();
514 DECODE_PRINTF("PUSH\tSS\n");
515 TRACE_AND_STEP();
516 push_word(M.x86.R_SS);
517 DECODE_CLEAR_SEGOVR();
518 END_OF_INSTR();
519}
520
521/****************************************************************************
522REMARKS:
523Handles opcode 0x17
524****************************************************************************/
525void x86emuOp_pop_SS(u8 X86EMU_UNUSED(op1))
526{
527 START_OF_INSTR();
528 DECODE_PRINTF("POP\tSS\n");
529 TRACE_AND_STEP();
530 M.x86.R_SS = pop_word();
531 DECODE_CLEAR_SEGOVR();
532 END_OF_INSTR();
533}
534
535/****************************************************************************
536REMARKS:
537Handles opcode 0x1e
538****************************************************************************/
539void x86emuOp_push_DS(u8 X86EMU_UNUSED(op1))
540{
541 START_OF_INSTR();
542 DECODE_PRINTF("PUSH\tDS\n");
543 TRACE_AND_STEP();
544 push_word(M.x86.R_DS);
545 DECODE_CLEAR_SEGOVR();
546 END_OF_INSTR();
547}
548
549/****************************************************************************
550REMARKS:
551Handles opcode 0x1f
552****************************************************************************/
553void x86emuOp_pop_DS(u8 X86EMU_UNUSED(op1))
554{
555 START_OF_INSTR();
556 DECODE_PRINTF("POP\tDS\n");
557 TRACE_AND_STEP();
558 M.x86.R_DS = pop_word();
559 DECODE_CLEAR_SEGOVR();
560 END_OF_INSTR();
561}
562
563/****************************************************************************
564REMARKS:
565Handles opcode 0x26
566****************************************************************************/
567void x86emuOp_segovr_ES(u8 X86EMU_UNUSED(op1))
568{
569 START_OF_INSTR();
570 DECODE_PRINTF("ES:\n");
571 TRACE_AND_STEP();
572 M.x86.mode |= SYSMODE_SEGOVR_ES;
573 /*
574 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
575 * opcode subroutines we do not want to do this.
576 */
577 END_OF_INSTR();
578}
579
580/****************************************************************************
581REMARKS:
582Handles opcode 0x27
583****************************************************************************/
584void x86emuOp_daa(u8 X86EMU_UNUSED(op1))
585{
586 START_OF_INSTR();
587 DECODE_PRINTF("DAA\n");
588 TRACE_AND_STEP();
589 M.x86.R_AL = daa_byte(M.x86.R_AL);
590 DECODE_CLEAR_SEGOVR();
591 END_OF_INSTR();
592}
593
594/****************************************************************************
595REMARKS:
596Handles opcode 0x2e
597****************************************************************************/
598void x86emuOp_segovr_CS(u8 X86EMU_UNUSED(op1))
599{
600 START_OF_INSTR();
601 DECODE_PRINTF("CS:\n");
602 TRACE_AND_STEP();
603 M.x86.mode |= SYSMODE_SEGOVR_CS;
604 /* note no DECODE_CLEAR_SEGOVR here. */
605 END_OF_INSTR();
606}
607
608/****************************************************************************
609REMARKS:
610Handles opcode 0x2f
611****************************************************************************/
612void x86emuOp_das(u8 X86EMU_UNUSED(op1))
613{
614 START_OF_INSTR();
615 DECODE_PRINTF("DAS\n");
616 TRACE_AND_STEP();
617 M.x86.R_AL = das_byte(M.x86.R_AL);
618 DECODE_CLEAR_SEGOVR();
619 END_OF_INSTR();
620}
621
622/****************************************************************************
623REMARKS:
624Handles opcode 0x36
625****************************************************************************/
626void x86emuOp_segovr_SS(u8 X86EMU_UNUSED(op1))
627{
628 START_OF_INSTR();
629 DECODE_PRINTF("SS:\n");
630 TRACE_AND_STEP();
631 M.x86.mode |= SYSMODE_SEGOVR_SS;
632 /* no DECODE_CLEAR_SEGOVR ! */
633 END_OF_INSTR();
634}
635
636/****************************************************************************
637REMARKS:
638Handles opcode 0x37
639****************************************************************************/
640void x86emuOp_aaa(u8 X86EMU_UNUSED(op1))
641{
642 START_OF_INSTR();
643 DECODE_PRINTF("AAA\n");
644 TRACE_AND_STEP();
645 M.x86.R_AX = aaa_word(M.x86.R_AX);
646 DECODE_CLEAR_SEGOVR();
647 END_OF_INSTR();
648}
649
650/****************************************************************************
651REMARKS:
652Handles opcode 0x3e
653****************************************************************************/
654void x86emuOp_segovr_DS(u8 X86EMU_UNUSED(op1))
655{
656 START_OF_INSTR();
657 DECODE_PRINTF("DS:\n");
658 TRACE_AND_STEP();
659 M.x86.mode |= SYSMODE_SEGOVR_DS;
660 /* NO DECODE_CLEAR_SEGOVR! */
661 END_OF_INSTR();
662}
663
664/****************************************************************************
665REMARKS:
666Handles opcode 0x3f
667****************************************************************************/
668void x86emuOp_aas(u8 X86EMU_UNUSED(op1))
669{
670 START_OF_INSTR();
671 DECODE_PRINTF("AAS\n");
672 TRACE_AND_STEP();
673 M.x86.R_AX = aas_word(M.x86.R_AX);
674 DECODE_CLEAR_SEGOVR();
675 END_OF_INSTR();
676}
677
678/****************************************************************************
679REMARKS:
680Handles opcode 0x40 - 0x47
681****************************************************************************/
682void x86emuOp_inc_register(u8 op1)
683{
684 START_OF_INSTR();
685 op1 &= 0x7;
686 DECODE_PRINTF("INC\t");
687 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200688 u32 *reg;
689 reg = DECODE_RM_LONG_REGISTER(op1);
690 DECODE_PRINTF("\n");
691 TRACE_AND_STEP();
692 *reg = inc_long(*reg);
Jason Jinece92f82007-07-06 08:34:56 +0800693 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200694 u16 *reg;
695 reg = DECODE_RM_WORD_REGISTER(op1);
696 DECODE_PRINTF("\n");
697 TRACE_AND_STEP();
698 *reg = inc_word(*reg);
Jason Jinece92f82007-07-06 08:34:56 +0800699 }
700 DECODE_CLEAR_SEGOVR();
701 END_OF_INSTR();
702}
703
704/****************************************************************************
705REMARKS:
706Handles opcode 0x48 - 0x4F
707****************************************************************************/
708void x86emuOp_dec_register(u8 op1)
709{
710 START_OF_INSTR();
711 op1 &= 0x7;
712 DECODE_PRINTF("DEC\t");
713 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200714 u32 *reg;
715 reg = DECODE_RM_LONG_REGISTER(op1);
716 DECODE_PRINTF("\n");
717 TRACE_AND_STEP();
718 *reg = dec_long(*reg);
Jason Jinece92f82007-07-06 08:34:56 +0800719 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200720 u16 *reg;
721 reg = DECODE_RM_WORD_REGISTER(op1);
722 DECODE_PRINTF("\n");
723 TRACE_AND_STEP();
724 *reg = dec_word(*reg);
Jason Jinece92f82007-07-06 08:34:56 +0800725 }
726 DECODE_CLEAR_SEGOVR();
727 END_OF_INSTR();
728}
729
730/****************************************************************************
731REMARKS:
732Handles opcode 0x50 - 0x57
733****************************************************************************/
734void x86emuOp_push_register(u8 op1)
735{
736 START_OF_INSTR();
737 op1 &= 0x7;
738 DECODE_PRINTF("PUSH\t");
739 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200740 u32 *reg;
741 reg = DECODE_RM_LONG_REGISTER(op1);
742 DECODE_PRINTF("\n");
743 TRACE_AND_STEP();
744 push_long(*reg);
Jason Jinece92f82007-07-06 08:34:56 +0800745 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200746 u16 *reg;
747 reg = DECODE_RM_WORD_REGISTER(op1);
748 DECODE_PRINTF("\n");
749 TRACE_AND_STEP();
750 push_word(*reg);
Jason Jinece92f82007-07-06 08:34:56 +0800751 }
752 DECODE_CLEAR_SEGOVR();
753 END_OF_INSTR();
754}
755
756/****************************************************************************
757REMARKS:
758Handles opcode 0x58 - 0x5F
759****************************************************************************/
760void x86emuOp_pop_register(u8 op1)
761{
762 START_OF_INSTR();
763 op1 &= 0x7;
764 DECODE_PRINTF("POP\t");
765 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200766 u32 *reg;
767 reg = DECODE_RM_LONG_REGISTER(op1);
768 DECODE_PRINTF("\n");
769 TRACE_AND_STEP();
770 *reg = pop_long();
Jason Jinece92f82007-07-06 08:34:56 +0800771 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200772 u16 *reg;
773 reg = DECODE_RM_WORD_REGISTER(op1);
774 DECODE_PRINTF("\n");
775 TRACE_AND_STEP();
776 *reg = pop_word();
Jason Jinece92f82007-07-06 08:34:56 +0800777 }
778 DECODE_CLEAR_SEGOVR();
779 END_OF_INSTR();
780}
781
782/****************************************************************************
783REMARKS:
784Handles opcode 0x60
785****************************************************************************/
786void x86emuOp_push_all(u8 X86EMU_UNUSED(op1))
787{
788 START_OF_INSTR();
789 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200790 DECODE_PRINTF("PUSHAD\n");
Jason Jinece92f82007-07-06 08:34:56 +0800791 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200792 DECODE_PRINTF("PUSHA\n");
Jason Jinece92f82007-07-06 08:34:56 +0800793 }
794 TRACE_AND_STEP();
795 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200796 u32 old_sp = M.x86.R_ESP;
Jason Jinece92f82007-07-06 08:34:56 +0800797
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200798 push_long(M.x86.R_EAX);
799 push_long(M.x86.R_ECX);
800 push_long(M.x86.R_EDX);
801 push_long(M.x86.R_EBX);
802 push_long(old_sp);
803 push_long(M.x86.R_EBP);
804 push_long(M.x86.R_ESI);
805 push_long(M.x86.R_EDI);
Jason Jinece92f82007-07-06 08:34:56 +0800806 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200807 u16 old_sp = M.x86.R_SP;
Jason Jinece92f82007-07-06 08:34:56 +0800808
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200809 push_word(M.x86.R_AX);
810 push_word(M.x86.R_CX);
811 push_word(M.x86.R_DX);
812 push_word(M.x86.R_BX);
813 push_word(old_sp);
814 push_word(M.x86.R_BP);
815 push_word(M.x86.R_SI);
816 push_word(M.x86.R_DI);
Jason Jinece92f82007-07-06 08:34:56 +0800817 }
818 DECODE_CLEAR_SEGOVR();
819 END_OF_INSTR();
820}
821
822/****************************************************************************
823REMARKS:
824Handles opcode 0x61
825****************************************************************************/
826void x86emuOp_pop_all(u8 X86EMU_UNUSED(op1))
827{
828 START_OF_INSTR();
829 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200830 DECODE_PRINTF("POPAD\n");
Jason Jinece92f82007-07-06 08:34:56 +0800831 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200832 DECODE_PRINTF("POPA\n");
Jason Jinece92f82007-07-06 08:34:56 +0800833 }
834 TRACE_AND_STEP();
835 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200836 M.x86.R_EDI = pop_long();
837 M.x86.R_ESI = pop_long();
838 M.x86.R_EBP = pop_long();
839 M.x86.R_ESP += 4; /* skip ESP */
840 M.x86.R_EBX = pop_long();
841 M.x86.R_EDX = pop_long();
842 M.x86.R_ECX = pop_long();
843 M.x86.R_EAX = pop_long();
Jason Jinece92f82007-07-06 08:34:56 +0800844 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200845 M.x86.R_DI = pop_word();
846 M.x86.R_SI = pop_word();
847 M.x86.R_BP = pop_word();
848 M.x86.R_SP += 2; /* skip SP */
849 M.x86.R_BX = pop_word();
850 M.x86.R_DX = pop_word();
851 M.x86.R_CX = pop_word();
852 M.x86.R_AX = pop_word();
Jason Jinece92f82007-07-06 08:34:56 +0800853 }
854 DECODE_CLEAR_SEGOVR();
855 END_OF_INSTR();
856}
857
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200858/*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */
859/*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */
Jason Jinece92f82007-07-06 08:34:56 +0800860
861/****************************************************************************
862REMARKS:
863Handles opcode 0x64
864****************************************************************************/
865void x86emuOp_segovr_FS(u8 X86EMU_UNUSED(op1))
866{
867 START_OF_INSTR();
868 DECODE_PRINTF("FS:\n");
869 TRACE_AND_STEP();
870 M.x86.mode |= SYSMODE_SEGOVR_FS;
871 /*
872 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
873 * opcode subroutines we do not want to do this.
874 */
875 END_OF_INSTR();
876}
877
878/****************************************************************************
879REMARKS:
880Handles opcode 0x65
881****************************************************************************/
882void x86emuOp_segovr_GS(u8 X86EMU_UNUSED(op1))
883{
884 START_OF_INSTR();
885 DECODE_PRINTF("GS:\n");
886 TRACE_AND_STEP();
887 M.x86.mode |= SYSMODE_SEGOVR_GS;
888 /*
889 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
890 * opcode subroutines we do not want to do this.
891 */
892 END_OF_INSTR();
893}
894
895/****************************************************************************
896REMARKS:
897Handles opcode 0x66 - prefix for 32-bit register
898****************************************************************************/
899void x86emuOp_prefix_data(u8 X86EMU_UNUSED(op1))
900{
901 START_OF_INSTR();
902 DECODE_PRINTF("DATA:\n");
903 TRACE_AND_STEP();
904 M.x86.mode |= SYSMODE_PREFIX_DATA;
905 /* note no DECODE_CLEAR_SEGOVR here. */
906 END_OF_INSTR();
907}
908
909/****************************************************************************
910REMARKS:
911Handles opcode 0x67 - prefix for 32-bit address
912****************************************************************************/
913void x86emuOp_prefix_addr(u8 X86EMU_UNUSED(op1))
914{
915 START_OF_INSTR();
916 DECODE_PRINTF("ADDR:\n");
917 TRACE_AND_STEP();
918 M.x86.mode |= SYSMODE_PREFIX_ADDR;
919 /* note no DECODE_CLEAR_SEGOVR here. */
920 END_OF_INSTR();
921}
922
923/****************************************************************************
924REMARKS:
925Handles opcode 0x68
926****************************************************************************/
927void x86emuOp_push_word_IMM(u8 X86EMU_UNUSED(op1))
928{
929 u32 imm;
930
931 START_OF_INSTR();
932 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200933 imm = fetch_long_imm();
Jason Jinece92f82007-07-06 08:34:56 +0800934 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200935 imm = fetch_word_imm();
Jason Jinece92f82007-07-06 08:34:56 +0800936 }
937 DECODE_PRINTF2("PUSH\t%x\n", imm);
938 TRACE_AND_STEP();
939 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200940 push_long(imm);
Jason Jinece92f82007-07-06 08:34:56 +0800941 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200942 push_word((u16)imm);
Jason Jinece92f82007-07-06 08:34:56 +0800943 }
944 DECODE_CLEAR_SEGOVR();
945 END_OF_INSTR();
946}
947
948/****************************************************************************
949REMARKS:
950Handles opcode 0x69
951****************************************************************************/
952void x86emuOp_imul_word_IMM(u8 X86EMU_UNUSED(op1))
953{
954 int mod, rl, rh;
955 uint srcoffset;
956
957 START_OF_INSTR();
958 DECODE_PRINTF("IMUL\t");
959 FETCH_DECODE_MODRM(mod, rh, rl);
960 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200961 srcoffset = decode_rmXX_address(mod, rl);
962 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
963 u32 *destreg;
964 u32 srcval;
965 u32 res_lo,res_hi;
966 s32 imm;
Jason Jinece92f82007-07-06 08:34:56 +0800967
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200968 destreg = DECODE_RM_LONG_REGISTER(rh);
969 DECODE_PRINTF(",");
970 srcval = fetch_data_long(srcoffset);
971 imm = fetch_long_imm();
972 DECODE_PRINTF2(",%d\n", (s32)imm);
973 TRACE_AND_STEP();
974 imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
975 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
976 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
977 CLEAR_FLAG(F_CF);
978 CLEAR_FLAG(F_OF);
979 } else {
980 SET_FLAG(F_CF);
981 SET_FLAG(F_OF);
982 }
983 *destreg = (u32)res_lo;
984 } else {
985 u16 *destreg;
986 u16 srcval;
987 u32 res;
988 s16 imm;
Jason Jinece92f82007-07-06 08:34:56 +0800989
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200990 destreg = DECODE_RM_WORD_REGISTER(rh);
991 DECODE_PRINTF(",");
992 srcval = fetch_data_word(srcoffset);
993 imm = fetch_word_imm();
994 DECODE_PRINTF2(",%d\n", (s32)imm);
995 TRACE_AND_STEP();
996 res = (s16)srcval * (s16)imm;
997 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
998 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
999 CLEAR_FLAG(F_CF);
1000 CLEAR_FLAG(F_OF);
1001 } else {
1002 SET_FLAG(F_CF);
1003 SET_FLAG(F_OF);
1004 }
1005 *destreg = (u16)res;
1006 }
1007 } else { /* register to register */
1008 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1009 u32 *destreg,*srcreg;
1010 u32 res_lo,res_hi;
1011 s32 imm;
Jason Jinece92f82007-07-06 08:34:56 +08001012
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001013 destreg = DECODE_RM_LONG_REGISTER(rh);
1014 DECODE_PRINTF(",");
1015 srcreg = DECODE_RM_LONG_REGISTER(rl);
1016 imm = fetch_long_imm();
1017 DECODE_PRINTF2(",%d\n", (s32)imm);
1018 TRACE_AND_STEP();
1019 imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
1020 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1021 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1022 CLEAR_FLAG(F_CF);
1023 CLEAR_FLAG(F_OF);
1024 } else {
1025 SET_FLAG(F_CF);
1026 SET_FLAG(F_OF);
1027 }
1028 *destreg = (u32)res_lo;
1029 } else {
1030 u16 *destreg,*srcreg;
1031 u32 res;
1032 s16 imm;
Jason Jinece92f82007-07-06 08:34:56 +08001033
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001034 destreg = DECODE_RM_WORD_REGISTER(rh);
1035 DECODE_PRINTF(",");
1036 srcreg = DECODE_RM_WORD_REGISTER(rl);
1037 imm = fetch_word_imm();
1038 DECODE_PRINTF2(",%d\n", (s32)imm);
1039 res = (s16)*srcreg * (s16)imm;
1040 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1041 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1042 CLEAR_FLAG(F_CF);
1043 CLEAR_FLAG(F_OF);
1044 } else {
1045 SET_FLAG(F_CF);
1046 SET_FLAG(F_OF);
1047 }
1048 *destreg = (u16)res;
1049 }
Jason Jinece92f82007-07-06 08:34:56 +08001050 }
1051 DECODE_CLEAR_SEGOVR();
1052 END_OF_INSTR();
1053}
1054
1055/****************************************************************************
1056REMARKS:
1057Handles opcode 0x6a
1058****************************************************************************/
1059void x86emuOp_push_byte_IMM(u8 X86EMU_UNUSED(op1))
1060{
1061 s16 imm;
1062
1063 START_OF_INSTR();
1064 imm = (s8)fetch_byte_imm();
1065 DECODE_PRINTF2("PUSH\t%d\n", imm);
1066 TRACE_AND_STEP();
1067 push_word(imm);
1068 DECODE_CLEAR_SEGOVR();
1069 END_OF_INSTR();
1070}
1071
1072/****************************************************************************
1073REMARKS:
1074Handles opcode 0x6b
1075****************************************************************************/
1076void x86emuOp_imul_byte_IMM(u8 X86EMU_UNUSED(op1))
1077{
1078 int mod, rl, rh;
1079 uint srcoffset;
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001080 s8 imm;
Jason Jinece92f82007-07-06 08:34:56 +08001081
1082 START_OF_INSTR();
1083 DECODE_PRINTF("IMUL\t");
1084 FETCH_DECODE_MODRM(mod, rh, rl);
1085 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001086 srcoffset = decode_rmXX_address(mod, rl);
1087 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1088 u32 *destreg;
1089 u32 srcval;
1090 u32 res_lo,res_hi;
Jason Jinece92f82007-07-06 08:34:56 +08001091
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001092 destreg = DECODE_RM_LONG_REGISTER(rh);
1093 DECODE_PRINTF(",");
1094 srcval = fetch_data_long(srcoffset);
1095 imm = fetch_byte_imm();
1096 DECODE_PRINTF2(",%d\n", (s32)imm);
1097 TRACE_AND_STEP();
1098 imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
1099 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1100 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1101 CLEAR_FLAG(F_CF);
1102 CLEAR_FLAG(F_OF);
1103 } else {
1104 SET_FLAG(F_CF);
1105 SET_FLAG(F_OF);
1106 }
1107 *destreg = (u32)res_lo;
1108 } else {
1109 u16 *destreg;
1110 u16 srcval;
1111 u32 res;
Jason Jinece92f82007-07-06 08:34:56 +08001112
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001113 destreg = DECODE_RM_WORD_REGISTER(rh);
1114 DECODE_PRINTF(",");
1115 srcval = fetch_data_word(srcoffset);
1116 imm = fetch_byte_imm();
1117 DECODE_PRINTF2(",%d\n", (s32)imm);
1118 TRACE_AND_STEP();
1119 res = (s16)srcval * (s16)imm;
1120 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1121 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1122 CLEAR_FLAG(F_CF);
1123 CLEAR_FLAG(F_OF);
1124 } else {
1125 SET_FLAG(F_CF);
1126 SET_FLAG(F_OF);
1127 }
1128 *destreg = (u16)res;
1129 }
1130 } else { /* register to register */
1131 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1132 u32 *destreg,*srcreg;
1133 u32 res_lo,res_hi;
Jason Jinece92f82007-07-06 08:34:56 +08001134
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001135 destreg = DECODE_RM_LONG_REGISTER(rh);
1136 DECODE_PRINTF(",");
1137 srcreg = DECODE_RM_LONG_REGISTER(rl);
1138 imm = fetch_byte_imm();
1139 DECODE_PRINTF2(",%d\n", (s32)imm);
1140 TRACE_AND_STEP();
1141 imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
1142 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1143 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1144 CLEAR_FLAG(F_CF);
1145 CLEAR_FLAG(F_OF);
1146 } else {
1147 SET_FLAG(F_CF);
1148 SET_FLAG(F_OF);
1149 }
1150 *destreg = (u32)res_lo;
1151 } else {
1152 u16 *destreg,*srcreg;
1153 u32 res;
Jason Jinece92f82007-07-06 08:34:56 +08001154
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001155 destreg = DECODE_RM_WORD_REGISTER(rh);
1156 DECODE_PRINTF(",");
1157 srcreg = DECODE_RM_WORD_REGISTER(rl);
1158 imm = fetch_byte_imm();
1159 DECODE_PRINTF2(",%d\n", (s32)imm);
1160 TRACE_AND_STEP();
1161 res = (s16)*srcreg * (s16)imm;
1162 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1163 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1164 CLEAR_FLAG(F_CF);
1165 CLEAR_FLAG(F_OF);
1166 } else {
1167 SET_FLAG(F_CF);
1168 SET_FLAG(F_OF);
1169 }
1170 *destreg = (u16)res;
1171 }
Jason Jinece92f82007-07-06 08:34:56 +08001172 }
1173 DECODE_CLEAR_SEGOVR();
1174 END_OF_INSTR();
1175}
1176
1177/****************************************************************************
1178REMARKS:
1179Handles opcode 0x6c
1180****************************************************************************/
1181void x86emuOp_ins_byte(u8 X86EMU_UNUSED(op1))
1182{
1183 START_OF_INSTR();
1184 DECODE_PRINTF("INSB\n");
1185 ins(1);
1186 TRACE_AND_STEP();
1187 DECODE_CLEAR_SEGOVR();
1188 END_OF_INSTR();
1189}
1190
1191/****************************************************************************
1192REMARKS:
1193Handles opcode 0x6d
1194****************************************************************************/
1195void x86emuOp_ins_word(u8 X86EMU_UNUSED(op1))
1196{
1197 START_OF_INSTR();
1198 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001199 DECODE_PRINTF("INSD\n");
1200 ins(4);
Jason Jinece92f82007-07-06 08:34:56 +08001201 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001202 DECODE_PRINTF("INSW\n");
1203 ins(2);
Jason Jinece92f82007-07-06 08:34:56 +08001204 }
1205 TRACE_AND_STEP();
1206 DECODE_CLEAR_SEGOVR();
1207 END_OF_INSTR();
1208}
1209
1210/****************************************************************************
1211REMARKS:
1212Handles opcode 0x6e
1213****************************************************************************/
1214void x86emuOp_outs_byte(u8 X86EMU_UNUSED(op1))
1215{
1216 START_OF_INSTR();
1217 DECODE_PRINTF("OUTSB\n");
1218 outs(1);
1219 TRACE_AND_STEP();
1220 DECODE_CLEAR_SEGOVR();
1221 END_OF_INSTR();
1222}
1223
1224/****************************************************************************
1225REMARKS:
1226Handles opcode 0x6f
1227****************************************************************************/
1228void x86emuOp_outs_word(u8 X86EMU_UNUSED(op1))
1229{
1230 START_OF_INSTR();
1231 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001232 DECODE_PRINTF("OUTSD\n");
1233 outs(4);
Jason Jinece92f82007-07-06 08:34:56 +08001234 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001235 DECODE_PRINTF("OUTSW\n");
1236 outs(2);
Jason Jinece92f82007-07-06 08:34:56 +08001237 }
1238 TRACE_AND_STEP();
1239 DECODE_CLEAR_SEGOVR();
1240 END_OF_INSTR();
1241}
1242
1243/****************************************************************************
1244REMARKS:
1245Handles opcode 0x70 - 0x7F
1246****************************************************************************/
1247int x86emu_check_jump_condition(u8 op);
1248
1249void x86emuOp_jump_near_cond(u8 op1)
1250{
1251 s8 offset;
1252 u16 target;
1253 int cond;
1254
1255 /* jump to byte offset if overflow flag is set */
1256 START_OF_INSTR();
1257 cond = x86emu_check_jump_condition(op1 & 0xF);
1258 offset = (s8)fetch_byte_imm();
1259 target = (u16)(M.x86.R_IP + (s16)offset);
1260 DECODE_PRINTF2("%x\n", target);
1261 TRACE_AND_STEP();
1262 if (cond)
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001263 M.x86.R_IP = target;
Jason Jinece92f82007-07-06 08:34:56 +08001264 DECODE_CLEAR_SEGOVR();
1265 END_OF_INSTR();
1266}
1267
1268/****************************************************************************
1269REMARKS:
1270Handles opcode 0x80
1271****************************************************************************/
1272void x86emuOp_opc80_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
1273{
1274 int mod, rl, rh;
1275 u8 *destreg;
1276 uint destoffset;
1277 u8 imm;
1278 u8 destval;
1279
1280 /*
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001281 * Weirdo special case instruction format. Part of the opcode
Jason Jinece92f82007-07-06 08:34:56 +08001282 * held below in "RH". Doubly nested case would result, except
1283 * that the decoded instruction
1284 */
1285 START_OF_INSTR();
1286 FETCH_DECODE_MODRM(mod, rh, rl);
1287#ifdef DEBUG
1288 if (DEBUG_DECODE()) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001289 /* XXX DECODE_PRINTF may be changed to something more
1290 general, so that it is important to leave the strings
1291 in the same format, even though the result is that the
1292 above test is done twice. */
Jason Jinece92f82007-07-06 08:34:56 +08001293
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001294 switch (rh) {
1295 case 0:
1296 DECODE_PRINTF("ADD\t");
1297 break;
1298 case 1:
1299 DECODE_PRINTF("OR\t");
1300 break;
1301 case 2:
1302 DECODE_PRINTF("ADC\t");
1303 break;
1304 case 3:
1305 DECODE_PRINTF("SBB\t");
1306 break;
1307 case 4:
1308 DECODE_PRINTF("AND\t");
1309 break;
1310 case 5:
1311 DECODE_PRINTF("SUB\t");
1312 break;
1313 case 6:
1314 DECODE_PRINTF("XOR\t");
1315 break;
1316 case 7:
1317 DECODE_PRINTF("CMP\t");
1318 break;
1319 }
Jason Jinece92f82007-07-06 08:34:56 +08001320 }
1321#endif
1322 /* know operation, decode the mod byte to find the addressing
1323 mode. */
1324 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001325 DECODE_PRINTF("BYTE PTR ");
1326 destoffset = decode_rmXX_address(mod, rl);
1327 DECODE_PRINTF(",");
1328 destval = fetch_data_byte(destoffset);
1329 imm = fetch_byte_imm();
1330 DECODE_PRINTF2("%x\n", imm);
1331 TRACE_AND_STEP();
1332 destval = (*genop_byte_operation[rh]) (destval, imm);
1333 if (rh != 7)
1334 store_data_byte(destoffset, destval);
1335 } else { /* register to register */
1336 destreg = DECODE_RM_BYTE_REGISTER(rl);
1337 DECODE_PRINTF(",");
1338 imm = fetch_byte_imm();
1339 DECODE_PRINTF2("%x\n", imm);
1340 TRACE_AND_STEP();
1341 destval = (*genop_byte_operation[rh]) (*destreg, imm);
1342 if (rh != 7)
1343 *destreg = destval;
Jason Jinece92f82007-07-06 08:34:56 +08001344 }
1345 DECODE_CLEAR_SEGOVR();
1346 END_OF_INSTR();
1347}
1348
1349/****************************************************************************
1350REMARKS:
1351Handles opcode 0x81
1352****************************************************************************/
1353void x86emuOp_opc81_word_RM_IMM(u8 X86EMU_UNUSED(op1))
1354{
1355 int mod, rl, rh;
1356 uint destoffset;
1357
1358 /*
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001359 * Weirdo special case instruction format. Part of the opcode
Jason Jinece92f82007-07-06 08:34:56 +08001360 * held below in "RH". Doubly nested case would result, except
1361 * that the decoded instruction
1362 */
1363 START_OF_INSTR();
1364 FETCH_DECODE_MODRM(mod, rh, rl);
1365#ifdef DEBUG
1366 if (DEBUG_DECODE()) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001367 /* XXX DECODE_PRINTF may be changed to something more
1368 general, so that it is important to leave the strings
1369 in the same format, even though the result is that the
1370 above test is done twice. */
Jason Jinece92f82007-07-06 08:34:56 +08001371
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001372 switch (rh) {
1373 case 0:
1374 DECODE_PRINTF("ADD\t");
1375 break;
1376 case 1:
1377 DECODE_PRINTF("OR\t");
1378 break;
1379 case 2:
1380 DECODE_PRINTF("ADC\t");
1381 break;
1382 case 3:
1383 DECODE_PRINTF("SBB\t");
1384 break;
1385 case 4:
1386 DECODE_PRINTF("AND\t");
1387 break;
1388 case 5:
1389 DECODE_PRINTF("SUB\t");
1390 break;
1391 case 6:
1392 DECODE_PRINTF("XOR\t");
1393 break;
1394 case 7:
1395 DECODE_PRINTF("CMP\t");
1396 break;
1397 }
Jason Jinece92f82007-07-06 08:34:56 +08001398 }
1399#endif
1400 /*
1401 * Know operation, decode the mod byte to find the addressing
1402 * mode.
1403 */
1404 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001405 DECODE_PRINTF("DWORD PTR ");
1406 destoffset = decode_rmXX_address(mod, rl);
1407 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1408 u32 destval,imm;
Jason Jinece92f82007-07-06 08:34:56 +08001409
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001410 DECODE_PRINTF(",");
1411 destval = fetch_data_long(destoffset);
1412 imm = fetch_long_imm();
1413 DECODE_PRINTF2("%x\n", imm);
1414 TRACE_AND_STEP();
1415 destval = (*genop_long_operation[rh]) (destval, imm);
1416 if (rh != 7)
1417 store_data_long(destoffset, destval);
1418 } else {
1419 u16 destval,imm;
Jason Jinece92f82007-07-06 08:34:56 +08001420
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001421 DECODE_PRINTF(",");
1422 destval = fetch_data_word(destoffset);
1423 imm = fetch_word_imm();
1424 DECODE_PRINTF2("%x\n", imm);
1425 TRACE_AND_STEP();
1426 destval = (*genop_word_operation[rh]) (destval, imm);
1427 if (rh != 7)
1428 store_data_word(destoffset, destval);
1429 }
1430 } else { /* register to register */
1431 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1432 u32 *destreg;
1433 u32 destval,imm;
Jason Jinece92f82007-07-06 08:34:56 +08001434
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001435 destreg = DECODE_RM_LONG_REGISTER(rl);
1436 DECODE_PRINTF(",");
1437 imm = fetch_long_imm();
1438 DECODE_PRINTF2("%x\n", imm);
1439 TRACE_AND_STEP();
1440 destval = (*genop_long_operation[rh]) (*destreg, imm);
1441 if (rh != 7)
1442 *destreg = destval;
1443 } else {
1444 u16 *destreg;
1445 u16 destval,imm;
Jason Jinece92f82007-07-06 08:34:56 +08001446
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001447 destreg = DECODE_RM_WORD_REGISTER(rl);
1448 DECODE_PRINTF(",");
1449 imm = fetch_word_imm();
1450 DECODE_PRINTF2("%x\n", imm);
1451 TRACE_AND_STEP();
1452 destval = (*genop_word_operation[rh]) (*destreg, imm);
1453 if (rh != 7)
1454 *destreg = destval;
1455 }
Jason Jinece92f82007-07-06 08:34:56 +08001456 }
1457 DECODE_CLEAR_SEGOVR();
1458 END_OF_INSTR();
1459}
1460
1461/****************************************************************************
1462REMARKS:
1463Handles opcode 0x82
1464****************************************************************************/
1465void x86emuOp_opc82_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
1466{
1467 int mod, rl, rh;
1468 u8 *destreg;
1469 uint destoffset;
1470 u8 imm;
1471 u8 destval;
1472
1473 /*
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001474 * Weirdo special case instruction format. Part of the opcode
Jason Jinece92f82007-07-06 08:34:56 +08001475 * held below in "RH". Doubly nested case would result, except
1476 * that the decoded instruction Similar to opcode 81, except that
1477 * the immediate byte is sign extended to a word length.
1478 */
1479 START_OF_INSTR();
1480 FETCH_DECODE_MODRM(mod, rh, rl);
1481#ifdef DEBUG
1482 if (DEBUG_DECODE()) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001483 /* XXX DECODE_PRINTF may be changed to something more
1484 general, so that it is important to leave the strings
1485 in the same format, even though the result is that the
1486 above test is done twice. */
1487 switch (rh) {
1488 case 0:
1489 DECODE_PRINTF("ADD\t");
1490 break;
1491 case 1:
1492 DECODE_PRINTF("OR\t");
1493 break;
1494 case 2:
1495 DECODE_PRINTF("ADC\t");
1496 break;
1497 case 3:
1498 DECODE_PRINTF("SBB\t");
1499 break;
1500 case 4:
1501 DECODE_PRINTF("AND\t");
1502 break;
1503 case 5:
1504 DECODE_PRINTF("SUB\t");
1505 break;
1506 case 6:
1507 DECODE_PRINTF("XOR\t");
1508 break;
1509 case 7:
1510 DECODE_PRINTF("CMP\t");
1511 break;
1512 }
Jason Jinece92f82007-07-06 08:34:56 +08001513 }
1514#endif
1515 /* know operation, decode the mod byte to find the addressing
1516 mode. */
1517 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001518 DECODE_PRINTF("BYTE PTR ");
1519 destoffset = decode_rmXX_address(mod, rl);
1520 destval = fetch_data_byte(destoffset);
1521 imm = fetch_byte_imm();
1522 DECODE_PRINTF2(",%x\n", imm);
1523 TRACE_AND_STEP();
1524 destval = (*genop_byte_operation[rh]) (destval, imm);
1525 if (rh != 7)
1526 store_data_byte(destoffset, destval);
1527 } else { /* register to register */
1528 destreg = DECODE_RM_BYTE_REGISTER(rl);
1529 imm = fetch_byte_imm();
1530 DECODE_PRINTF2(",%x\n", imm);
1531 TRACE_AND_STEP();
1532 destval = (*genop_byte_operation[rh]) (*destreg, imm);
1533 if (rh != 7)
1534 *destreg = destval;
Jason Jinece92f82007-07-06 08:34:56 +08001535 }
1536 DECODE_CLEAR_SEGOVR();
1537 END_OF_INSTR();
1538}
1539
1540/****************************************************************************
1541REMARKS:
1542Handles opcode 0x83
1543****************************************************************************/
1544void x86emuOp_opc83_word_RM_IMM(u8 X86EMU_UNUSED(op1))
1545{
1546 int mod, rl, rh;
1547 uint destoffset;
1548
1549 /*
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001550 * Weirdo special case instruction format. Part of the opcode
Jason Jinece92f82007-07-06 08:34:56 +08001551 * held below in "RH". Doubly nested case would result, except
1552 * that the decoded instruction Similar to opcode 81, except that
1553 * the immediate byte is sign extended to a word length.
1554 */
1555 START_OF_INSTR();
1556 FETCH_DECODE_MODRM(mod, rh, rl);
1557#ifdef DEBUG
1558 if (DEBUG_DECODE()) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001559 /* XXX DECODE_PRINTF may be changed to something more
1560 general, so that it is important to leave the strings
1561 in the same format, even though the result is that the
1562 above test is done twice. */
Jason Jinece92f82007-07-06 08:34:56 +08001563 switch (rh) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001564 case 0:
1565 DECODE_PRINTF("ADD\t");
1566 break;
1567 case 1:
1568 DECODE_PRINTF("OR\t");
1569 break;
1570 case 2:
1571 DECODE_PRINTF("ADC\t");
1572 break;
1573 case 3:
1574 DECODE_PRINTF("SBB\t");
1575 break;
1576 case 4:
1577 DECODE_PRINTF("AND\t");
1578 break;
1579 case 5:
1580 DECODE_PRINTF("SUB\t");
1581 break;
1582 case 6:
1583 DECODE_PRINTF("XOR\t");
1584 break;
1585 case 7:
1586 DECODE_PRINTF("CMP\t");
1587 break;
1588 }
Jason Jinece92f82007-07-06 08:34:56 +08001589 }
1590#endif
1591 /* know operation, decode the mod byte to find the addressing
1592 mode. */
1593 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001594 DECODE_PRINTF("DWORD PTR ");
1595 destoffset = decode_rmXX_address(mod,rl);
Jason Jinece92f82007-07-06 08:34:56 +08001596
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001597 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1598 u32 destval,imm;
Jason Jinece92f82007-07-06 08:34:56 +08001599
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001600 destval = fetch_data_long(destoffset);
1601 imm = (s8) fetch_byte_imm();
1602 DECODE_PRINTF2(",%x\n", imm);
1603 TRACE_AND_STEP();
1604 destval = (*genop_long_operation[rh]) (destval, imm);
1605 if (rh != 7)
1606 store_data_long(destoffset, destval);
1607 } else {
1608 u16 destval,imm;
Jason Jinece92f82007-07-06 08:34:56 +08001609
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001610 destval = fetch_data_word(destoffset);
1611 imm = (s8) fetch_byte_imm();
1612 DECODE_PRINTF2(",%x\n", imm);
1613 TRACE_AND_STEP();
1614 destval = (*genop_word_operation[rh]) (destval, imm);
1615 if (rh != 7)
1616 store_data_word(destoffset, destval);
1617 }
1618 } else { /* register to register */
1619 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1620 u32 *destreg;
1621 u32 destval,imm;
Jason Jinece92f82007-07-06 08:34:56 +08001622
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001623 destreg = DECODE_RM_LONG_REGISTER(rl);
1624 imm = (s8) fetch_byte_imm();
1625 DECODE_PRINTF2(",%x\n", imm);
1626 TRACE_AND_STEP();
1627 destval = (*genop_long_operation[rh]) (*destreg, imm);
1628 if (rh != 7)
1629 *destreg = destval;
1630 } else {
1631 u16 *destreg;
1632 u16 destval,imm;
Jason Jinece92f82007-07-06 08:34:56 +08001633
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001634 destreg = DECODE_RM_WORD_REGISTER(rl);
1635 imm = (s8) fetch_byte_imm();
1636 DECODE_PRINTF2(",%x\n", imm);
1637 TRACE_AND_STEP();
1638 destval = (*genop_word_operation[rh]) (*destreg, imm);
1639 if (rh != 7)
1640 *destreg = destval;
1641 }
Jason Jinece92f82007-07-06 08:34:56 +08001642 }
1643 DECODE_CLEAR_SEGOVR();
1644 END_OF_INSTR();
1645}
1646
1647/****************************************************************************
1648REMARKS:
1649Handles opcode 0x84
1650****************************************************************************/
1651void x86emuOp_test_byte_RM_R(u8 X86EMU_UNUSED(op1))
1652{
1653 int mod, rl, rh;
1654 u8 *destreg, *srcreg;
1655 uint destoffset;
1656 u8 destval;
1657
1658 START_OF_INSTR();
1659 DECODE_PRINTF("TEST\t");
1660 FETCH_DECODE_MODRM(mod, rh, rl);
1661 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001662 destoffset = decode_rmXX_address(mod, rl);
1663 DECODE_PRINTF(",");
1664 destval = fetch_data_byte(destoffset);
1665 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1666 DECODE_PRINTF("\n");
1667 TRACE_AND_STEP();
1668 test_byte(destval, *srcreg);
1669 } else { /* register to register */
1670 destreg = DECODE_RM_BYTE_REGISTER(rl);
1671 DECODE_PRINTF(",");
1672 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1673 DECODE_PRINTF("\n");
1674 TRACE_AND_STEP();
1675 test_byte(*destreg, *srcreg);
Jason Jinece92f82007-07-06 08:34:56 +08001676 }
1677 DECODE_CLEAR_SEGOVR();
1678 END_OF_INSTR();
1679}
1680
1681/****************************************************************************
1682REMARKS:
1683Handles opcode 0x85
1684****************************************************************************/
1685void x86emuOp_test_word_RM_R(u8 X86EMU_UNUSED(op1))
1686{
1687 int mod, rl, rh;
1688 uint destoffset;
1689
1690 START_OF_INSTR();
1691 DECODE_PRINTF("TEST\t");
1692 FETCH_DECODE_MODRM(mod, rh, rl);
1693 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001694 destoffset = decode_rmXX_address(mod, rl);
1695 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1696 u32 destval;
1697 u32 *srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08001698
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001699 DECODE_PRINTF(",");
1700 destval = fetch_data_long(destoffset);
1701 srcreg = DECODE_RM_LONG_REGISTER(rh);
1702 DECODE_PRINTF("\n");
1703 TRACE_AND_STEP();
1704 test_long(destval, *srcreg);
1705 } else {
1706 u16 destval;
1707 u16 *srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08001708
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001709 DECODE_PRINTF(",");
1710 destval = fetch_data_word(destoffset);
1711 srcreg = DECODE_RM_WORD_REGISTER(rh);
1712 DECODE_PRINTF("\n");
1713 TRACE_AND_STEP();
1714 test_word(destval, *srcreg);
1715 }
1716 } else { /* register to register */
1717 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1718 u32 *destreg,*srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08001719
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001720 destreg = DECODE_RM_LONG_REGISTER(rl);
1721 DECODE_PRINTF(",");
1722 srcreg = DECODE_RM_LONG_REGISTER(rh);
1723 DECODE_PRINTF("\n");
1724 TRACE_AND_STEP();
1725 test_long(*destreg, *srcreg);
1726 } else {
1727 u16 *destreg,*srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08001728
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001729 destreg = DECODE_RM_WORD_REGISTER(rl);
1730 DECODE_PRINTF(",");
1731 srcreg = DECODE_RM_WORD_REGISTER(rh);
1732 DECODE_PRINTF("\n");
1733 TRACE_AND_STEP();
1734 test_word(*destreg, *srcreg);
1735 }
Jason Jinece92f82007-07-06 08:34:56 +08001736 }
1737 DECODE_CLEAR_SEGOVR();
1738 END_OF_INSTR();
1739}
1740
1741/****************************************************************************
1742REMARKS:
1743Handles opcode 0x86
1744****************************************************************************/
1745void x86emuOp_xchg_byte_RM_R(u8 X86EMU_UNUSED(op1))
1746{
1747 int mod, rl, rh;
1748 u8 *destreg, *srcreg;
1749 uint destoffset;
1750 u8 destval;
1751 u8 tmp;
1752
1753 START_OF_INSTR();
1754 DECODE_PRINTF("XCHG\t");
1755 FETCH_DECODE_MODRM(mod, rh, rl);
1756 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001757 destoffset = decode_rmXX_address(mod, rl);
1758 DECODE_PRINTF(",");
1759 destval = fetch_data_byte(destoffset);
1760 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1761 DECODE_PRINTF("\n");
1762 TRACE_AND_STEP();
1763 tmp = *srcreg;
1764 *srcreg = destval;
1765 destval = tmp;
1766 store_data_byte(destoffset, destval);
1767 } else { /* register to register */
1768 destreg = DECODE_RM_BYTE_REGISTER(rl);
1769 DECODE_PRINTF(",");
1770 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1771 DECODE_PRINTF("\n");
1772 TRACE_AND_STEP();
1773 tmp = *srcreg;
1774 *srcreg = *destreg;
1775 *destreg = tmp;
Jason Jinece92f82007-07-06 08:34:56 +08001776 }
1777 DECODE_CLEAR_SEGOVR();
1778 END_OF_INSTR();
1779}
1780
1781/****************************************************************************
1782REMARKS:
1783Handles opcode 0x87
1784****************************************************************************/
1785void x86emuOp_xchg_word_RM_R(u8 X86EMU_UNUSED(op1))
1786{
1787 int mod, rl, rh;
1788 uint destoffset;
1789
1790 START_OF_INSTR();
1791 DECODE_PRINTF("XCHG\t");
1792 FETCH_DECODE_MODRM(mod, rh, rl);
1793 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001794 destoffset = decode_rmXX_address(mod, rl);
1795 DECODE_PRINTF(",");
1796 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1797 u32 *srcreg;
1798 u32 destval,tmp;
Jason Jinece92f82007-07-06 08:34:56 +08001799
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001800 destval = fetch_data_long(destoffset);
1801 srcreg = DECODE_RM_LONG_REGISTER(rh);
1802 DECODE_PRINTF("\n");
1803 TRACE_AND_STEP();
1804 tmp = *srcreg;
1805 *srcreg = destval;
1806 destval = tmp;
1807 store_data_long(destoffset, destval);
1808 } else {
1809 u16 *srcreg;
1810 u16 destval,tmp;
Jason Jinece92f82007-07-06 08:34:56 +08001811
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001812 destval = fetch_data_word(destoffset);
1813 srcreg = DECODE_RM_WORD_REGISTER(rh);
1814 DECODE_PRINTF("\n");
1815 TRACE_AND_STEP();
1816 tmp = *srcreg;
1817 *srcreg = destval;
1818 destval = tmp;
1819 store_data_word(destoffset, destval);
1820 }
1821 } else { /* register to register */
1822 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1823 u32 *destreg,*srcreg;
1824 u32 tmp;
Jason Jinece92f82007-07-06 08:34:56 +08001825
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001826 destreg = DECODE_RM_LONG_REGISTER(rl);
1827 DECODE_PRINTF(",");
1828 srcreg = DECODE_RM_LONG_REGISTER(rh);
1829 DECODE_PRINTF("\n");
1830 TRACE_AND_STEP();
1831 tmp = *srcreg;
1832 *srcreg = *destreg;
1833 *destreg = tmp;
1834 } else {
1835 u16 *destreg,*srcreg;
1836 u16 tmp;
Jason Jinece92f82007-07-06 08:34:56 +08001837
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001838 destreg = DECODE_RM_WORD_REGISTER(rl);
1839 DECODE_PRINTF(",");
1840 srcreg = DECODE_RM_WORD_REGISTER(rh);
1841 DECODE_PRINTF("\n");
1842 TRACE_AND_STEP();
1843 tmp = *srcreg;
1844 *srcreg = *destreg;
1845 *destreg = tmp;
1846 }
Jason Jinece92f82007-07-06 08:34:56 +08001847 }
1848 DECODE_CLEAR_SEGOVR();
1849 END_OF_INSTR();
1850}
1851
1852/****************************************************************************
1853REMARKS:
1854Handles opcode 0x88
1855****************************************************************************/
1856void x86emuOp_mov_byte_RM_R(u8 X86EMU_UNUSED(op1))
1857{
1858 int mod, rl, rh;
1859 u8 *destreg, *srcreg;
1860 uint destoffset;
1861
1862 START_OF_INSTR();
1863 DECODE_PRINTF("MOV\t");
1864 FETCH_DECODE_MODRM(mod, rh, rl);
1865 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001866 destoffset = decode_rmXX_address(mod, rl);
1867 DECODE_PRINTF(",");
1868 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1869 DECODE_PRINTF("\n");
1870 TRACE_AND_STEP();
1871 store_data_byte(destoffset, *srcreg);
1872 } else { /* register to register */
1873 destreg = DECODE_RM_BYTE_REGISTER(rl);
1874 DECODE_PRINTF(",");
1875 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1876 DECODE_PRINTF("\n");
1877 TRACE_AND_STEP();
1878 *destreg = *srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08001879 }
1880 DECODE_CLEAR_SEGOVR();
1881 END_OF_INSTR();
1882}
1883
1884/****************************************************************************
1885REMARKS:
1886Handles opcode 0x89
1887****************************************************************************/
1888void x86emuOp_mov_word_RM_R(u8 X86EMU_UNUSED(op1))
1889{
1890 int mod, rl, rh;
1891 uint destoffset;
1892
1893 START_OF_INSTR();
1894 DECODE_PRINTF("MOV\t");
1895 FETCH_DECODE_MODRM(mod, rh, rl);
1896 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001897 destoffset = decode_rmXX_address(mod, rl);
1898 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1899 u32 *srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08001900
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001901 DECODE_PRINTF(",");
1902 srcreg = DECODE_RM_LONG_REGISTER(rh);
1903 DECODE_PRINTF("\n");
1904 TRACE_AND_STEP();
1905 store_data_long(destoffset, *srcreg);
1906 } else {
1907 u16 *srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08001908
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001909 DECODE_PRINTF(",");
1910 srcreg = DECODE_RM_WORD_REGISTER(rh);
1911 DECODE_PRINTF("\n");
1912 TRACE_AND_STEP();
1913 store_data_word(destoffset, *srcreg);
1914 }
1915 } else { /* register to register */
1916 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1917 u32 *destreg,*srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08001918
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001919 destreg = DECODE_RM_LONG_REGISTER(rl);
1920 DECODE_PRINTF(",");
1921 srcreg = DECODE_RM_LONG_REGISTER(rh);
1922 DECODE_PRINTF("\n");
1923 TRACE_AND_STEP();
1924 *destreg = *srcreg;
1925 } else {
1926 u16 *destreg,*srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08001927
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001928 destreg = DECODE_RM_WORD_REGISTER(rl);
1929 DECODE_PRINTF(",");
1930 srcreg = DECODE_RM_WORD_REGISTER(rh);
1931 DECODE_PRINTF("\n");
1932 TRACE_AND_STEP();
1933 *destreg = *srcreg;
1934 }
Jason Jinece92f82007-07-06 08:34:56 +08001935 }
1936 DECODE_CLEAR_SEGOVR();
1937 END_OF_INSTR();
1938}
1939
1940/****************************************************************************
1941REMARKS:
1942Handles opcode 0x8a
1943****************************************************************************/
1944void x86emuOp_mov_byte_R_RM(u8 X86EMU_UNUSED(op1))
1945{
1946 int mod, rl, rh;
1947 u8 *destreg, *srcreg;
1948 uint srcoffset;
1949 u8 srcval;
1950
1951 START_OF_INSTR();
1952 DECODE_PRINTF("MOV\t");
1953 FETCH_DECODE_MODRM(mod, rh, rl);
1954 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001955 destreg = DECODE_RM_BYTE_REGISTER(rh);
1956 DECODE_PRINTF(",");
1957 srcoffset = decode_rmXX_address(mod, rl);
1958 srcval = fetch_data_byte(srcoffset);
1959 DECODE_PRINTF("\n");
1960 TRACE_AND_STEP();
1961 *destreg = srcval;
1962 } else { /* register to register */
1963 destreg = DECODE_RM_BYTE_REGISTER(rh);
1964 DECODE_PRINTF(",");
1965 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1966 DECODE_PRINTF("\n");
1967 TRACE_AND_STEP();
1968 *destreg = *srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08001969 }
1970 DECODE_CLEAR_SEGOVR();
1971 END_OF_INSTR();
1972}
1973
1974/****************************************************************************
1975REMARKS:
1976Handles opcode 0x8b
1977****************************************************************************/
1978void x86emuOp_mov_word_R_RM(u8 X86EMU_UNUSED(op1))
1979{
1980 int mod, rl, rh;
1981 uint srcoffset;
1982
1983 START_OF_INSTR();
1984 DECODE_PRINTF("MOV\t");
1985 FETCH_DECODE_MODRM(mod, rh, rl);
1986 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001987 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1988 u32 *destreg;
1989 u32 srcval;
Jason Jinece92f82007-07-06 08:34:56 +08001990
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001991 destreg = DECODE_RM_LONG_REGISTER(rh);
1992 DECODE_PRINTF(",");
1993 srcoffset = decode_rmXX_address(mod, rl);
1994 srcval = fetch_data_long(srcoffset);
1995 DECODE_PRINTF("\n");
1996 TRACE_AND_STEP();
1997 *destreg = srcval;
1998 } else {
1999 u16 *destreg;
2000 u16 srcval;
Jason Jinece92f82007-07-06 08:34:56 +08002001
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002002 destreg = DECODE_RM_WORD_REGISTER(rh);
2003 DECODE_PRINTF(",");
2004 srcoffset = decode_rmXX_address(mod, rl);
2005 srcval = fetch_data_word(srcoffset);
2006 DECODE_PRINTF("\n");
2007 TRACE_AND_STEP();
2008 *destreg = srcval;
2009 }
2010 } else { /* register to register */
2011 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2012 u32 *destreg, *srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08002013
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002014 destreg = DECODE_RM_LONG_REGISTER(rh);
2015 DECODE_PRINTF(",");
2016 srcreg = DECODE_RM_LONG_REGISTER(rl);
2017 DECODE_PRINTF("\n");
2018 TRACE_AND_STEP();
2019 *destreg = *srcreg;
2020 } else {
2021 u16 *destreg, *srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08002022
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002023 destreg = DECODE_RM_WORD_REGISTER(rh);
2024 DECODE_PRINTF(",");
2025 srcreg = DECODE_RM_WORD_REGISTER(rl);
2026 DECODE_PRINTF("\n");
2027 TRACE_AND_STEP();
2028 *destreg = *srcreg;
2029 }
Jason Jinece92f82007-07-06 08:34:56 +08002030 }
2031 DECODE_CLEAR_SEGOVR();
2032 END_OF_INSTR();
2033}
2034
2035/****************************************************************************
2036REMARKS:
2037Handles opcode 0x8c
2038****************************************************************************/
2039void x86emuOp_mov_word_RM_SR(u8 X86EMU_UNUSED(op1))
2040{
2041 int mod, rl, rh;
2042 u16 *destreg, *srcreg;
2043 uint destoffset;
2044 u16 destval;
2045
2046 START_OF_INSTR();
2047 DECODE_PRINTF("MOV\t");
2048 FETCH_DECODE_MODRM(mod, rh, rl);
2049 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002050 destoffset = decode_rmXX_address(mod, rl);
2051 DECODE_PRINTF(",");
2052 srcreg = decode_rm_seg_register(rh);
2053 DECODE_PRINTF("\n");
2054 TRACE_AND_STEP();
2055 destval = *srcreg;
2056 store_data_word(destoffset, destval);
2057 } else { /* register to register */
2058 destreg = DECODE_RM_WORD_REGISTER(rl);
2059 DECODE_PRINTF(",");
2060 srcreg = decode_rm_seg_register(rh);
2061 DECODE_PRINTF("\n");
2062 TRACE_AND_STEP();
2063 *destreg = *srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08002064 }
2065 DECODE_CLEAR_SEGOVR();
2066 END_OF_INSTR();
2067}
2068
2069/****************************************************************************
2070REMARKS:
2071Handles opcode 0x8d
2072****************************************************************************/
2073void x86emuOp_lea_word_R_M(u8 X86EMU_UNUSED(op1))
2074{
2075 int mod, rl, rh;
2076 u16 *srcreg;
2077 uint destoffset;
2078
2079/*
2080 * TODO: Need to handle address size prefix!
2081 *
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002082 * lea eax,[eax+ebx*2] ??
Jason Jinece92f82007-07-06 08:34:56 +08002083 */
2084
2085 START_OF_INSTR();
2086 DECODE_PRINTF("LEA\t");
2087 FETCH_DECODE_MODRM(mod, rh, rl);
2088 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002089 srcreg = DECODE_RM_WORD_REGISTER(rh);
2090 DECODE_PRINTF(",");
2091 destoffset = decode_rmXX_address(mod, rl);
2092 DECODE_PRINTF("\n");
2093 TRACE_AND_STEP();
2094 *srcreg = (u16)destoffset;
2095 }
Jason Jinece92f82007-07-06 08:34:56 +08002096 /* } else { undefined. Do nothing. } */
2097 DECODE_CLEAR_SEGOVR();
2098 END_OF_INSTR();
2099}
2100
2101/****************************************************************************
2102REMARKS:
2103Handles opcode 0x8e
2104****************************************************************************/
2105void x86emuOp_mov_word_SR_RM(u8 X86EMU_UNUSED(op1))
2106{
2107 int mod, rl, rh;
2108 u16 *destreg, *srcreg;
2109 uint srcoffset;
2110 u16 srcval;
2111
2112 START_OF_INSTR();
2113 DECODE_PRINTF("MOV\t");
2114 FETCH_DECODE_MODRM(mod, rh, rl);
2115 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002116 destreg = decode_rm_seg_register(rh);
2117 DECODE_PRINTF(",");
2118 srcoffset = decode_rmXX_address(mod, rl);
2119 srcval = fetch_data_word(srcoffset);
2120 DECODE_PRINTF("\n");
2121 TRACE_AND_STEP();
2122 *destreg = srcval;
2123 } else { /* register to register */
2124 destreg = decode_rm_seg_register(rh);
2125 DECODE_PRINTF(",");
2126 srcreg = DECODE_RM_WORD_REGISTER(rl);
2127 DECODE_PRINTF("\n");
2128 TRACE_AND_STEP();
2129 *destreg = *srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08002130 }
2131 /*
2132 * Clean up, and reset all the R_xSP pointers to the correct
2133 * locations. This is about 3x too much overhead (doing all the
2134 * segreg ptrs when only one is needed, but this instruction
2135 * *cannot* be that common, and this isn't too much work anyway.
2136 */
2137 DECODE_CLEAR_SEGOVR();
2138 END_OF_INSTR();
2139}
2140
2141/****************************************************************************
2142REMARKS:
2143Handles opcode 0x8f
2144****************************************************************************/
2145void x86emuOp_pop_RM(u8 X86EMU_UNUSED(op1))
2146{
2147 int mod, rl, rh;
2148 uint destoffset;
2149
2150 START_OF_INSTR();
2151 DECODE_PRINTF("POP\t");
2152 FETCH_DECODE_MODRM(mod, rh, rl);
2153 if (rh != 0) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002154 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
2155 HALT_SYS();
Jason Jinece92f82007-07-06 08:34:56 +08002156 }
2157 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002158 destoffset = decode_rmXX_address(mod, rl);
2159 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2160 u32 destval;
Jason Jinece92f82007-07-06 08:34:56 +08002161
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002162 DECODE_PRINTF("\n");
2163 TRACE_AND_STEP();
2164 destval = pop_long();
2165 store_data_long(destoffset, destval);
2166 } else {
2167 u16 destval;
Jason Jinece92f82007-07-06 08:34:56 +08002168
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002169 DECODE_PRINTF("\n");
2170 TRACE_AND_STEP();
2171 destval = pop_word();
2172 store_data_word(destoffset, destval);
2173 }
2174 } else { /* register to register */
2175 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2176 u32 *destreg;
Jason Jinece92f82007-07-06 08:34:56 +08002177
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002178 destreg = DECODE_RM_LONG_REGISTER(rl);
2179 DECODE_PRINTF("\n");
2180 TRACE_AND_STEP();
2181 *destreg = pop_long();
2182 } else {
2183 u16 *destreg;
Jason Jinece92f82007-07-06 08:34:56 +08002184
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002185 destreg = DECODE_RM_WORD_REGISTER(rl);
2186 DECODE_PRINTF("\n");
2187 TRACE_AND_STEP();
2188 *destreg = pop_word();
2189 }
Jason Jinece92f82007-07-06 08:34:56 +08002190 }
2191 DECODE_CLEAR_SEGOVR();
2192 END_OF_INSTR();
2193}
2194
2195/****************************************************************************
2196REMARKS:
2197Handles opcode 0x90
2198****************************************************************************/
2199void x86emuOp_nop(u8 X86EMU_UNUSED(op1))
2200{
2201 START_OF_INSTR();
2202 DECODE_PRINTF("NOP\n");
2203 TRACE_AND_STEP();
2204 DECODE_CLEAR_SEGOVR();
2205 END_OF_INSTR();
2206}
2207
2208/****************************************************************************
2209REMARKS:
2210Handles opcode 0x91-0x97
2211****************************************************************************/
2212void x86emuOp_xchg_word_AX_register(u8 X86EMU_UNUSED(op1))
2213{
2214 u32 tmp;
2215
2216 op1 &= 0x7;
2217
2218 START_OF_INSTR();
2219
2220 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002221 u32 *reg32;
2222 DECODE_PRINTF("XCHG\tEAX,");
2223 reg32 = DECODE_RM_LONG_REGISTER(op1);
2224 DECODE_PRINTF("\n");
2225 TRACE_AND_STEP();
2226 tmp = M.x86.R_EAX;
2227 M.x86.R_EAX = *reg32;
2228 *reg32 = tmp;
Jason Jinece92f82007-07-06 08:34:56 +08002229 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002230 u16 *reg16;
2231 DECODE_PRINTF("XCHG\tAX,");
2232 reg16 = DECODE_RM_WORD_REGISTER(op1);
2233 DECODE_PRINTF("\n");
2234 TRACE_AND_STEP();
2235 tmp = M.x86.R_AX;
2236 M.x86.R_EAX = *reg16;
2237 *reg16 = (u16)tmp;
Jason Jinece92f82007-07-06 08:34:56 +08002238 }
2239 DECODE_CLEAR_SEGOVR();
2240 END_OF_INSTR();
2241}
2242
2243/****************************************************************************
2244REMARKS:
2245Handles opcode 0x98
2246****************************************************************************/
2247void x86emuOp_cbw(u8 X86EMU_UNUSED(op1))
2248{
2249 START_OF_INSTR();
2250 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002251 DECODE_PRINTF("CWDE\n");
Jason Jinece92f82007-07-06 08:34:56 +08002252 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002253 DECODE_PRINTF("CBW\n");
Jason Jinece92f82007-07-06 08:34:56 +08002254 }
2255 TRACE_AND_STEP();
2256 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002257 if (M.x86.R_AX & 0x8000) {
2258 M.x86.R_EAX |= 0xffff0000;
2259 } else {
2260 M.x86.R_EAX &= 0x0000ffff;
2261 }
Jason Jinece92f82007-07-06 08:34:56 +08002262 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002263 if (M.x86.R_AL & 0x80) {
2264 M.x86.R_AH = 0xff;
2265 } else {
2266 M.x86.R_AH = 0x0;
2267 }
Jason Jinece92f82007-07-06 08:34:56 +08002268 }
2269 DECODE_CLEAR_SEGOVR();
2270 END_OF_INSTR();
2271}
2272
2273/****************************************************************************
2274REMARKS:
2275Handles opcode 0x99
2276****************************************************************************/
2277void x86emuOp_cwd(u8 X86EMU_UNUSED(op1))
2278{
2279 START_OF_INSTR();
2280 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002281 DECODE_PRINTF("CDQ\n");
Jason Jinece92f82007-07-06 08:34:56 +08002282 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002283 DECODE_PRINTF("CWD\n");
Jason Jinece92f82007-07-06 08:34:56 +08002284 }
2285 DECODE_PRINTF("CWD\n");
2286 TRACE_AND_STEP();
2287 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002288 if (M.x86.R_EAX & 0x80000000) {
2289 M.x86.R_EDX = 0xffffffff;
2290 } else {
2291 M.x86.R_EDX = 0x0;
2292 }
Jason Jinece92f82007-07-06 08:34:56 +08002293 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002294 if (M.x86.R_AX & 0x8000) {
2295 M.x86.R_DX = 0xffff;
2296 } else {
2297 M.x86.R_DX = 0x0;
2298 }
Jason Jinece92f82007-07-06 08:34:56 +08002299 }
2300 DECODE_CLEAR_SEGOVR();
2301 END_OF_INSTR();
2302}
2303
2304/****************************************************************************
2305REMARKS:
2306Handles opcode 0x9a
2307****************************************************************************/
2308void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1))
2309{
2310 u16 farseg, faroff;
2311
2312 START_OF_INSTR();
2313 DECODE_PRINTF("CALL\t");
2314 faroff = fetch_word_imm();
2315 farseg = fetch_word_imm();
2316 DECODE_PRINTF2("%04x:", farseg);
2317 DECODE_PRINTF2("%04x\n", faroff);
2318 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, farseg, faroff, "FAR ");
2319
2320 /* XXX
2321 *
2322 * Hooked interrupt vectors calling into our "BIOS" will cause
2323 * problems unless all intersegment stuff is checked for BIOS
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002324 * access. Check needed here. For moment, let it alone.
Jason Jinece92f82007-07-06 08:34:56 +08002325 */
2326 TRACE_AND_STEP();
2327 push_word(M.x86.R_CS);
2328 M.x86.R_CS = farseg;
2329 push_word(M.x86.R_IP);
2330 M.x86.R_IP = faroff;
2331 DECODE_CLEAR_SEGOVR();
2332 END_OF_INSTR();
2333}
2334
2335/****************************************************************************
2336REMARKS:
2337Handles opcode 0x9b
2338****************************************************************************/
2339void x86emuOp_wait(u8 X86EMU_UNUSED(op1))
2340{
2341 START_OF_INSTR();
2342 DECODE_PRINTF("WAIT");
2343 TRACE_AND_STEP();
2344 /* NADA. */
2345 DECODE_CLEAR_SEGOVR();
2346 END_OF_INSTR();
2347}
2348
2349/****************************************************************************
2350REMARKS:
2351Handles opcode 0x9c
2352****************************************************************************/
2353void x86emuOp_pushf_word(u8 X86EMU_UNUSED(op1))
2354{
2355 u32 flags;
2356
2357 START_OF_INSTR();
2358 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002359 DECODE_PRINTF("PUSHFD\n");
Jason Jinece92f82007-07-06 08:34:56 +08002360 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002361 DECODE_PRINTF("PUSHF\n");
Jason Jinece92f82007-07-06 08:34:56 +08002362 }
2363 TRACE_AND_STEP();
2364
2365 /* clear out *all* bits not representing flags, and turn on real bits */
2366 flags = (M.x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
2367 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002368 push_long(flags);
Jason Jinece92f82007-07-06 08:34:56 +08002369 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002370 push_word((u16)flags);
Jason Jinece92f82007-07-06 08:34:56 +08002371 }
2372 DECODE_CLEAR_SEGOVR();
2373 END_OF_INSTR();
2374}
2375
2376/****************************************************************************
2377REMARKS:
2378Handles opcode 0x9d
2379****************************************************************************/
2380void x86emuOp_popf_word(u8 X86EMU_UNUSED(op1))
2381{
2382 START_OF_INSTR();
2383 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002384 DECODE_PRINTF("POPFD\n");
Jason Jinece92f82007-07-06 08:34:56 +08002385 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002386 DECODE_PRINTF("POPF\n");
Jason Jinece92f82007-07-06 08:34:56 +08002387 }
2388 TRACE_AND_STEP();
2389 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002390 M.x86.R_EFLG = pop_long();
Jason Jinece92f82007-07-06 08:34:56 +08002391 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002392 M.x86.R_FLG = pop_word();
Jason Jinece92f82007-07-06 08:34:56 +08002393 }
2394 DECODE_CLEAR_SEGOVR();
2395 END_OF_INSTR();
2396}
2397
2398/****************************************************************************
2399REMARKS:
2400Handles opcode 0x9e
2401****************************************************************************/
2402void x86emuOp_sahf(u8 X86EMU_UNUSED(op1))
2403{
2404 START_OF_INSTR();
2405 DECODE_PRINTF("SAHF\n");
2406 TRACE_AND_STEP();
2407 /* clear the lower bits of the flag register */
2408 M.x86.R_FLG &= 0xffffff00;
2409 /* or in the AH register into the flags register */
2410 M.x86.R_FLG |= M.x86.R_AH;
2411 DECODE_CLEAR_SEGOVR();
2412 END_OF_INSTR();
2413}
2414
2415/****************************************************************************
2416REMARKS:
2417Handles opcode 0x9f
2418****************************************************************************/
2419void x86emuOp_lahf(u8 X86EMU_UNUSED(op1))
2420{
2421 START_OF_INSTR();
2422 DECODE_PRINTF("LAHF\n");
2423 TRACE_AND_STEP();
2424 M.x86.R_AH = (u8)(M.x86.R_FLG & 0xff);
2425 /*undocumented TC++ behavior??? Nope. It's documented, but
2426 you have too look real hard to notice it. */
2427 M.x86.R_AH |= 0x2;
2428 DECODE_CLEAR_SEGOVR();
2429 END_OF_INSTR();
2430}
2431
2432/****************************************************************************
2433REMARKS:
2434Handles opcode 0xa0
2435****************************************************************************/
2436void x86emuOp_mov_AL_M_IMM(u8 X86EMU_UNUSED(op1))
2437{
2438 u16 offset;
2439
2440 START_OF_INSTR();
2441 DECODE_PRINTF("MOV\tAL,");
2442 offset = fetch_word_imm();
2443 DECODE_PRINTF2("[%04x]\n", offset);
2444 TRACE_AND_STEP();
2445 M.x86.R_AL = fetch_data_byte(offset);
2446 DECODE_CLEAR_SEGOVR();
2447 END_OF_INSTR();
2448}
2449
2450/****************************************************************************
2451REMARKS:
2452Handles opcode 0xa1
2453****************************************************************************/
2454void x86emuOp_mov_AX_M_IMM(u8 X86EMU_UNUSED(op1))
2455{
2456 u16 offset;
2457
2458 START_OF_INSTR();
2459 offset = fetch_word_imm();
2460 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002461 DECODE_PRINTF2("MOV\tEAX,[%04x]\n", offset);
Jason Jinece92f82007-07-06 08:34:56 +08002462 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002463 DECODE_PRINTF2("MOV\tAX,[%04x]\n", offset);
Jason Jinece92f82007-07-06 08:34:56 +08002464 }
2465 TRACE_AND_STEP();
2466 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002467 M.x86.R_EAX = fetch_data_long(offset);
Jason Jinece92f82007-07-06 08:34:56 +08002468 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002469 M.x86.R_AX = fetch_data_word(offset);
Jason Jinece92f82007-07-06 08:34:56 +08002470 }
2471 DECODE_CLEAR_SEGOVR();
2472 END_OF_INSTR();
2473}
2474
2475/****************************************************************************
2476REMARKS:
2477Handles opcode 0xa2
2478****************************************************************************/
2479void x86emuOp_mov_M_AL_IMM(u8 X86EMU_UNUSED(op1))
2480{
2481 u16 offset;
2482
2483 START_OF_INSTR();
2484 DECODE_PRINTF("MOV\t");
2485 offset = fetch_word_imm();
2486 DECODE_PRINTF2("[%04x],AL\n", offset);
2487 TRACE_AND_STEP();
2488 store_data_byte(offset, M.x86.R_AL);
2489 DECODE_CLEAR_SEGOVR();
2490 END_OF_INSTR();
2491}
2492
2493/****************************************************************************
2494REMARKS:
2495Handles opcode 0xa3
2496****************************************************************************/
2497void x86emuOp_mov_M_AX_IMM(u8 X86EMU_UNUSED(op1))
2498{
2499 u16 offset;
2500
2501 START_OF_INSTR();
2502 offset = fetch_word_imm();
2503 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002504 DECODE_PRINTF2("MOV\t[%04x],EAX\n", offset);
Jason Jinece92f82007-07-06 08:34:56 +08002505 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002506 DECODE_PRINTF2("MOV\t[%04x],AX\n", offset);
Jason Jinece92f82007-07-06 08:34:56 +08002507 }
2508 TRACE_AND_STEP();
2509 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002510 store_data_long(offset, M.x86.R_EAX);
Jason Jinece92f82007-07-06 08:34:56 +08002511 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002512 store_data_word(offset, M.x86.R_AX);
Jason Jinece92f82007-07-06 08:34:56 +08002513 }
2514 DECODE_CLEAR_SEGOVR();
2515 END_OF_INSTR();
2516}
2517
2518/****************************************************************************
2519REMARKS:
2520Handles opcode 0xa4
2521****************************************************************************/
2522void x86emuOp_movs_byte(u8 X86EMU_UNUSED(op1))
2523{
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002524 u8 val;
Jason Jinece92f82007-07-06 08:34:56 +08002525 u32 count;
2526 int inc;
2527
2528 START_OF_INSTR();
2529 DECODE_PRINTF("MOVS\tBYTE\n");
2530 if (ACCESS_FLAG(F_DF)) /* down */
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002531 inc = -1;
Jason Jinece92f82007-07-06 08:34:56 +08002532 else
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002533 inc = 1;
Jason Jinece92f82007-07-06 08:34:56 +08002534 TRACE_AND_STEP();
2535 count = 1;
2536 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002537 /* dont care whether REPE or REPNE */
2538 /* move them until CX is ZERO. */
2539 count = M.x86.R_CX;
2540 M.x86.R_CX = 0;
2541 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
Jason Jinece92f82007-07-06 08:34:56 +08002542 }
2543 while (count--) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002544 val = fetch_data_byte(M.x86.R_SI);
2545 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, val);
2546 M.x86.R_SI += inc;
2547 M.x86.R_DI += inc;
Jason Jinece92f82007-07-06 08:34:56 +08002548 }
2549 DECODE_CLEAR_SEGOVR();
2550 END_OF_INSTR();
2551}
2552
2553/****************************************************************************
2554REMARKS:
2555Handles opcode 0xa5
2556****************************************************************************/
2557void x86emuOp_movs_word(u8 X86EMU_UNUSED(op1))
2558{
2559 u32 val;
2560 int inc;
2561 u32 count;
2562
2563 START_OF_INSTR();
2564 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002565 DECODE_PRINTF("MOVS\tDWORD\n");
2566 if (ACCESS_FLAG(F_DF)) /* down */
2567 inc = -4;
2568 else
2569 inc = 4;
Jason Jinece92f82007-07-06 08:34:56 +08002570 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002571 DECODE_PRINTF("MOVS\tWORD\n");
2572 if (ACCESS_FLAG(F_DF)) /* down */
2573 inc = -2;
2574 else
2575 inc = 2;
Jason Jinece92f82007-07-06 08:34:56 +08002576 }
2577 TRACE_AND_STEP();
2578 count = 1;
2579 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002580 /* dont care whether REPE or REPNE */
2581 /* move them until CX is ZERO. */
2582 count = M.x86.R_CX;
2583 M.x86.R_CX = 0;
2584 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
Jason Jinece92f82007-07-06 08:34:56 +08002585 }
2586 while (count--) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002587 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2588 val = fetch_data_long(M.x86.R_SI);
2589 store_data_long_abs(M.x86.R_ES, M.x86.R_DI, val);
2590 } else {
2591 val = fetch_data_word(M.x86.R_SI);
2592 store_data_word_abs(M.x86.R_ES, M.x86.R_DI, (u16)val);
2593 }
2594 M.x86.R_SI += inc;
2595 M.x86.R_DI += inc;
Jason Jinece92f82007-07-06 08:34:56 +08002596 }
2597 DECODE_CLEAR_SEGOVR();
2598 END_OF_INSTR();
2599}
2600
2601/****************************************************************************
2602REMARKS:
2603Handles opcode 0xa6
2604****************************************************************************/
2605void x86emuOp_cmps_byte(u8 X86EMU_UNUSED(op1))
2606{
2607 s8 val1, val2;
2608 int inc;
2609
2610 START_OF_INSTR();
2611 DECODE_PRINTF("CMPS\tBYTE\n");
2612 TRACE_AND_STEP();
2613 if (ACCESS_FLAG(F_DF)) /* down */
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002614 inc = -1;
Jason Jinece92f82007-07-06 08:34:56 +08002615 else
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002616 inc = 1;
Jason Jinece92f82007-07-06 08:34:56 +08002617
2618 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002619 /* REPE */
2620 /* move them until CX is ZERO. */
2621 while (M.x86.R_CX != 0) {
2622 val1 = fetch_data_byte(M.x86.R_SI);
2623 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2624 cmp_byte(val1, val2);
2625 M.x86.R_CX -= 1;
2626 M.x86.R_SI += inc;
2627 M.x86.R_DI += inc;
2628 if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && (ACCESS_FLAG(F_ZF) == 0) ) break;
2629 if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2630 }
2631 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
Jason Jinece92f82007-07-06 08:34:56 +08002632 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002633 val1 = fetch_data_byte(M.x86.R_SI);
2634 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2635 cmp_byte(val1, val2);
2636 M.x86.R_SI += inc;
2637 M.x86.R_DI += inc;
Jason Jinece92f82007-07-06 08:34:56 +08002638 }
2639 DECODE_CLEAR_SEGOVR();
2640 END_OF_INSTR();
2641}
2642
2643/****************************************************************************
2644REMARKS:
2645Handles opcode 0xa7
2646****************************************************************************/
2647void x86emuOp_cmps_word(u8 X86EMU_UNUSED(op1))
2648{
2649 u32 val1,val2;
2650 int inc;
2651
2652 START_OF_INSTR();
2653 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002654 DECODE_PRINTF("CMPS\tDWORD\n");
2655 inc = 4;
Jason Jinece92f82007-07-06 08:34:56 +08002656 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002657 DECODE_PRINTF("CMPS\tWORD\n");
2658 inc = 2;
Jason Jinece92f82007-07-06 08:34:56 +08002659 }
2660 if (ACCESS_FLAG(F_DF)) /* down */
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002661 inc = -inc;
Jason Jinece92f82007-07-06 08:34:56 +08002662
2663 TRACE_AND_STEP();
2664 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002665 /* REPE */
2666 /* move them until CX is ZERO. */
2667 while (M.x86.R_CX != 0) {
2668 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2669 val1 = fetch_data_long(M.x86.R_SI);
2670 val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2671 cmp_long(val1, val2);
2672 } else {
2673 val1 = fetch_data_word(M.x86.R_SI);
2674 val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2675 cmp_word((u16)val1, (u16)val2);
2676 }
2677 M.x86.R_CX -= 1;
2678 M.x86.R_SI += inc;
2679 M.x86.R_DI += inc;
2680 if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && ACCESS_FLAG(F_ZF) == 0 ) break;
2681 if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2682 }
2683 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
Jason Jinece92f82007-07-06 08:34:56 +08002684 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002685 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2686 val1 = fetch_data_long(M.x86.R_SI);
2687 val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2688 cmp_long(val1, val2);
2689 } else {
2690 val1 = fetch_data_word(M.x86.R_SI);
2691 val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2692 cmp_word((u16)val1, (u16)val2);
2693 }
2694 M.x86.R_SI += inc;
2695 M.x86.R_DI += inc;
Jason Jinece92f82007-07-06 08:34:56 +08002696 }
2697 DECODE_CLEAR_SEGOVR();
2698 END_OF_INSTR();
2699}
2700
2701/****************************************************************************
2702REMARKS:
2703Handles opcode 0xa8
2704****************************************************************************/
2705void x86emuOp_test_AL_IMM(u8 X86EMU_UNUSED(op1))
2706{
2707 int imm;
2708
2709 START_OF_INSTR();
2710 DECODE_PRINTF("TEST\tAL,");
2711 imm = fetch_byte_imm();
2712 DECODE_PRINTF2("%04x\n", imm);
2713 TRACE_AND_STEP();
2714 test_byte(M.x86.R_AL, (u8)imm);
2715 DECODE_CLEAR_SEGOVR();
2716 END_OF_INSTR();
2717}
2718
2719/****************************************************************************
2720REMARKS:
2721Handles opcode 0xa9
2722****************************************************************************/
2723void x86emuOp_test_AX_IMM(u8 X86EMU_UNUSED(op1))
2724{
2725 u32 srcval;
2726
2727 START_OF_INSTR();
2728 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002729 DECODE_PRINTF("TEST\tEAX,");
2730 srcval = fetch_long_imm();
Jason Jinece92f82007-07-06 08:34:56 +08002731 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002732 DECODE_PRINTF("TEST\tAX,");
2733 srcval = fetch_word_imm();
Jason Jinece92f82007-07-06 08:34:56 +08002734 }
2735 DECODE_PRINTF2("%x\n", srcval);
2736 TRACE_AND_STEP();
2737 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002738 test_long(M.x86.R_EAX, srcval);
Jason Jinece92f82007-07-06 08:34:56 +08002739 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002740 test_word(M.x86.R_AX, (u16)srcval);
Jason Jinece92f82007-07-06 08:34:56 +08002741 }
2742 DECODE_CLEAR_SEGOVR();
2743 END_OF_INSTR();
2744}
2745
2746/****************************************************************************
2747REMARKS:
2748Handles opcode 0xaa
2749****************************************************************************/
2750void x86emuOp_stos_byte(u8 X86EMU_UNUSED(op1))
2751{
2752 int inc;
2753
2754 START_OF_INSTR();
2755 DECODE_PRINTF("STOS\tBYTE\n");
2756 if (ACCESS_FLAG(F_DF)) /* down */
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002757 inc = -1;
Jason Jinece92f82007-07-06 08:34:56 +08002758 else
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002759 inc = 1;
Jason Jinece92f82007-07-06 08:34:56 +08002760 TRACE_AND_STEP();
2761 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002762 /* dont care whether REPE or REPNE */
2763 /* move them until CX is ZERO. */
2764 while (M.x86.R_CX != 0) {
2765 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
2766 M.x86.R_CX -= 1;
2767 M.x86.R_DI += inc;
2768 }
2769 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
Jason Jinece92f82007-07-06 08:34:56 +08002770 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002771 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
2772 M.x86.R_DI += inc;
Jason Jinece92f82007-07-06 08:34:56 +08002773 }
2774 DECODE_CLEAR_SEGOVR();
2775 END_OF_INSTR();
2776}
2777
2778/****************************************************************************
2779REMARKS:
2780Handles opcode 0xab
2781****************************************************************************/
2782void x86emuOp_stos_word(u8 X86EMU_UNUSED(op1))
2783{
2784 int inc;
2785 u32 count;
2786
2787 START_OF_INSTR();
2788 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002789 DECODE_PRINTF("STOS\tDWORD\n");
2790 if (ACCESS_FLAG(F_DF)) /* down */
2791 inc = -4;
2792 else
2793 inc = 4;
Jason Jinece92f82007-07-06 08:34:56 +08002794 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002795 DECODE_PRINTF("STOS\tWORD\n");
2796 if (ACCESS_FLAG(F_DF)) /* down */
2797 inc = -2;
2798 else
2799 inc = 2;
Jason Jinece92f82007-07-06 08:34:56 +08002800 }
2801 TRACE_AND_STEP();
2802 count = 1;
2803 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002804 /* dont care whether REPE or REPNE */
2805 /* move them until CX is ZERO. */
2806 count = M.x86.R_CX;
2807 M.x86.R_CX = 0;
2808 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
Jason Jinece92f82007-07-06 08:34:56 +08002809 }
2810 while (count--) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002811 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2812 store_data_long_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_EAX);
2813 } else {
2814 store_data_word_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AX);
2815 }
2816 M.x86.R_DI += inc;
Jason Jinece92f82007-07-06 08:34:56 +08002817 }
2818 DECODE_CLEAR_SEGOVR();
2819 END_OF_INSTR();
2820}
2821
2822/****************************************************************************
2823REMARKS:
2824Handles opcode 0xac
2825****************************************************************************/
2826void x86emuOp_lods_byte(u8 X86EMU_UNUSED(op1))
2827{
2828 int inc;
2829
2830 START_OF_INSTR();
2831 DECODE_PRINTF("LODS\tBYTE\n");
2832 TRACE_AND_STEP();
2833 if (ACCESS_FLAG(F_DF)) /* down */
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002834 inc = -1;
Jason Jinece92f82007-07-06 08:34:56 +08002835 else
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002836 inc = 1;
Jason Jinece92f82007-07-06 08:34:56 +08002837 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002838 /* dont care whether REPE or REPNE */
2839 /* move them until CX is ZERO. */
2840 while (M.x86.R_CX != 0) {
2841 M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
2842 M.x86.R_CX -= 1;
2843 M.x86.R_SI += inc;
2844 }
2845 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
Jason Jinece92f82007-07-06 08:34:56 +08002846 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002847 M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
2848 M.x86.R_SI += inc;
Jason Jinece92f82007-07-06 08:34:56 +08002849 }
2850 DECODE_CLEAR_SEGOVR();
2851 END_OF_INSTR();
2852}
2853
2854/****************************************************************************
2855REMARKS:
2856Handles opcode 0xad
2857****************************************************************************/
2858void x86emuOp_lods_word(u8 X86EMU_UNUSED(op1))
2859{
2860 int inc;
2861 u32 count;
2862
2863 START_OF_INSTR();
2864 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002865 DECODE_PRINTF("LODS\tDWORD\n");
2866 if (ACCESS_FLAG(F_DF)) /* down */
2867 inc = -4;
2868 else
2869 inc = 4;
Jason Jinece92f82007-07-06 08:34:56 +08002870 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002871 DECODE_PRINTF("LODS\tWORD\n");
2872 if (ACCESS_FLAG(F_DF)) /* down */
2873 inc = -2;
2874 else
2875 inc = 2;
Jason Jinece92f82007-07-06 08:34:56 +08002876 }
2877 TRACE_AND_STEP();
2878 count = 1;
2879 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002880 /* dont care whether REPE or REPNE */
2881 /* move them until CX is ZERO. */
2882 count = M.x86.R_CX;
2883 M.x86.R_CX = 0;
2884 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
Jason Jinece92f82007-07-06 08:34:56 +08002885 }
2886 while (count--) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002887 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2888 M.x86.R_EAX = fetch_data_long(M.x86.R_SI);
2889 } else {
2890 M.x86.R_AX = fetch_data_word(M.x86.R_SI);
2891 }
2892 M.x86.R_SI += inc;
Jason Jinece92f82007-07-06 08:34:56 +08002893 }
2894 DECODE_CLEAR_SEGOVR();
2895 END_OF_INSTR();
2896}
2897
2898/****************************************************************************
2899REMARKS:
2900Handles opcode 0xae
2901****************************************************************************/
2902void x86emuOp_scas_byte(u8 X86EMU_UNUSED(op1))
2903{
2904 s8 val2;
2905 int inc;
2906
2907 START_OF_INSTR();
2908 DECODE_PRINTF("SCAS\tBYTE\n");
2909 TRACE_AND_STEP();
2910 if (ACCESS_FLAG(F_DF)) /* down */
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002911 inc = -1;
Jason Jinece92f82007-07-06 08:34:56 +08002912 else
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002913 inc = 1;
Jason Jinece92f82007-07-06 08:34:56 +08002914 if (M.x86.mode & SYSMODE_PREFIX_REPE) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002915 /* REPE */
2916 /* move them until CX is ZERO. */
2917 while (M.x86.R_CX != 0) {
2918 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2919 cmp_byte(M.x86.R_AL, val2);
2920 M.x86.R_CX -= 1;
2921 M.x86.R_DI += inc;
2922 if (ACCESS_FLAG(F_ZF) == 0)
2923 break;
2924 }
2925 M.x86.mode &= ~SYSMODE_PREFIX_REPE;
Jason Jinece92f82007-07-06 08:34:56 +08002926 } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002927 /* REPNE */
2928 /* move them until CX is ZERO. */
2929 while (M.x86.R_CX != 0) {
2930 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2931 cmp_byte(M.x86.R_AL, val2);
2932 M.x86.R_CX -= 1;
2933 M.x86.R_DI += inc;
2934 if (ACCESS_FLAG(F_ZF))
2935 break; /* zero flag set means equal */
2936 }
2937 M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
Jason Jinece92f82007-07-06 08:34:56 +08002938 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002939 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2940 cmp_byte(M.x86.R_AL, val2);
2941 M.x86.R_DI += inc;
Jason Jinece92f82007-07-06 08:34:56 +08002942 }
2943 DECODE_CLEAR_SEGOVR();
2944 END_OF_INSTR();
2945}
2946
2947/****************************************************************************
2948REMARKS:
2949Handles opcode 0xaf
2950****************************************************************************/
2951void x86emuOp_scas_word(u8 X86EMU_UNUSED(op1))
2952{
2953 int inc;
2954 u32 val;
2955
2956 START_OF_INSTR();
2957 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002958 DECODE_PRINTF("SCAS\tDWORD\n");
2959 if (ACCESS_FLAG(F_DF)) /* down */
2960 inc = -4;
2961 else
2962 inc = 4;
Jason Jinece92f82007-07-06 08:34:56 +08002963 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002964 DECODE_PRINTF("SCAS\tWORD\n");
2965 if (ACCESS_FLAG(F_DF)) /* down */
2966 inc = -2;
2967 else
2968 inc = 2;
Jason Jinece92f82007-07-06 08:34:56 +08002969 }
2970 TRACE_AND_STEP();
2971 if (M.x86.mode & SYSMODE_PREFIX_REPE) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002972 /* REPE */
2973 /* move them until CX is ZERO. */
2974 while (M.x86.R_CX != 0) {
2975 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2976 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2977 cmp_long(M.x86.R_EAX, val);
2978 } else {
2979 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2980 cmp_word(M.x86.R_AX, (u16)val);
2981 }
2982 M.x86.R_CX -= 1;
2983 M.x86.R_DI += inc;
2984 if (ACCESS_FLAG(F_ZF) == 0)
2985 break;
2986 }
2987 M.x86.mode &= ~SYSMODE_PREFIX_REPE;
Jason Jinece92f82007-07-06 08:34:56 +08002988 } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02002989 /* REPNE */
2990 /* move them until CX is ZERO. */
2991 while (M.x86.R_CX != 0) {
2992 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2993 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2994 cmp_long(M.x86.R_EAX, val);
2995 } else {
2996 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2997 cmp_word(M.x86.R_AX, (u16)val);
2998 }
2999 M.x86.R_CX -= 1;
3000 M.x86.R_DI += inc;
3001 if (ACCESS_FLAG(F_ZF))
3002 break; /* zero flag set means equal */
3003 }
3004 M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
Jason Jinece92f82007-07-06 08:34:56 +08003005 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003006 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3007 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
3008 cmp_long(M.x86.R_EAX, val);
3009 } else {
3010 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
3011 cmp_word(M.x86.R_AX, (u16)val);
3012 }
3013 M.x86.R_DI += inc;
Jason Jinece92f82007-07-06 08:34:56 +08003014 }
3015 DECODE_CLEAR_SEGOVR();
3016 END_OF_INSTR();
3017}
3018
3019/****************************************************************************
3020REMARKS:
3021Handles opcode 0xb0 - 0xb7
3022****************************************************************************/
3023void x86emuOp_mov_byte_register_IMM(u8 op1)
3024{
3025 u8 imm, *ptr;
3026
3027 START_OF_INSTR();
3028 DECODE_PRINTF("MOV\t");
3029 ptr = DECODE_RM_BYTE_REGISTER(op1 & 0x7);
3030 DECODE_PRINTF(",");
3031 imm = fetch_byte_imm();
3032 DECODE_PRINTF2("%x\n", imm);
3033 TRACE_AND_STEP();
3034 *ptr = imm;
3035 DECODE_CLEAR_SEGOVR();
3036 END_OF_INSTR();
3037}
3038
3039/****************************************************************************
3040REMARKS:
3041Handles opcode 0xb8 - 0xbf
3042****************************************************************************/
3043void x86emuOp_mov_word_register_IMM(u8 X86EMU_UNUSED(op1))
3044{
3045 u32 srcval;
3046
3047 op1 &= 0x7;
3048
3049 START_OF_INSTR();
3050 DECODE_PRINTF("MOV\t");
3051 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003052 u32 *reg32;
3053 reg32 = DECODE_RM_LONG_REGISTER(op1);
3054 srcval = fetch_long_imm();
3055 DECODE_PRINTF2(",%x\n", srcval);
3056 TRACE_AND_STEP();
3057 *reg32 = srcval;
Jason Jinece92f82007-07-06 08:34:56 +08003058 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003059 u16 *reg16;
3060 reg16 = DECODE_RM_WORD_REGISTER(op1);
3061 srcval = fetch_word_imm();
3062 DECODE_PRINTF2(",%x\n", srcval);
3063 TRACE_AND_STEP();
3064 *reg16 = (u16)srcval;
Jason Jinece92f82007-07-06 08:34:56 +08003065 }
3066 DECODE_CLEAR_SEGOVR();
3067 END_OF_INSTR();
3068}
3069
3070/****************************************************************************
3071REMARKS:
3072Handles opcode 0xc0
3073****************************************************************************/
3074void x86emuOp_opcC0_byte_RM_MEM(u8 X86EMU_UNUSED(op1))
3075{
3076 int mod, rl, rh;
3077 u8 *destreg;
3078 uint destoffset;
3079 u8 destval;
3080 u8 amt;
3081
3082 /*
3083 * Yet another weirdo special case instruction format. Part of
3084 * the opcode held below in "RH". Doubly nested case would
3085 * result, except that the decoded instruction
3086 */
3087 START_OF_INSTR();
3088 FETCH_DECODE_MODRM(mod, rh, rl);
3089#ifdef DEBUG
3090 if (DEBUG_DECODE()) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003091 /* XXX DECODE_PRINTF may be changed to something more
3092 general, so that it is important to leave the strings
3093 in the same format, even though the result is that the
3094 above test is done twice. */
Jason Jinece92f82007-07-06 08:34:56 +08003095
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003096 switch (rh) {
3097 case 0:
3098 DECODE_PRINTF("ROL\t");
3099 break;
3100 case 1:
3101 DECODE_PRINTF("ROR\t");
3102 break;
3103 case 2:
3104 DECODE_PRINTF("RCL\t");
3105 break;
3106 case 3:
3107 DECODE_PRINTF("RCR\t");
3108 break;
3109 case 4:
3110 DECODE_PRINTF("SHL\t");
3111 break;
3112 case 5:
3113 DECODE_PRINTF("SHR\t");
3114 break;
3115 case 6:
3116 DECODE_PRINTF("SAL\t");
3117 break;
3118 case 7:
3119 DECODE_PRINTF("SAR\t");
3120 break;
3121 }
Jason Jinece92f82007-07-06 08:34:56 +08003122 }
3123#endif
3124 /* know operation, decode the mod byte to find the addressing
3125 mode. */
3126 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003127 DECODE_PRINTF("BYTE PTR ");
3128 destoffset = decode_rmXX_address(mod, rl);
3129 amt = fetch_byte_imm();
3130 DECODE_PRINTF2(",%x\n", amt);
3131 destval = fetch_data_byte(destoffset);
3132 TRACE_AND_STEP();
3133 destval = (*opcD0_byte_operation[rh]) (destval, amt);
3134 store_data_byte(destoffset, destval);
3135 } else { /* register to register */
3136 destreg = DECODE_RM_BYTE_REGISTER(rl);
3137 amt = fetch_byte_imm();
3138 DECODE_PRINTF2(",%x\n", amt);
3139 TRACE_AND_STEP();
3140 destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3141 *destreg = destval;
Jason Jinece92f82007-07-06 08:34:56 +08003142 }
3143 DECODE_CLEAR_SEGOVR();
3144 END_OF_INSTR();
3145}
3146
3147/****************************************************************************
3148REMARKS:
3149Handles opcode 0xc1
3150****************************************************************************/
3151void x86emuOp_opcC1_word_RM_MEM(u8 X86EMU_UNUSED(op1))
3152{
3153 int mod, rl, rh;
3154 uint destoffset;
3155 u8 amt;
3156
3157 /*
3158 * Yet another weirdo special case instruction format. Part of
3159 * the opcode held below in "RH". Doubly nested case would
3160 * result, except that the decoded instruction
3161 */
3162 START_OF_INSTR();
3163 FETCH_DECODE_MODRM(mod, rh, rl);
3164#ifdef DEBUG
3165 if (DEBUG_DECODE()) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003166 /* XXX DECODE_PRINTF may be changed to something more
3167 general, so that it is important to leave the strings
3168 in the same format, even though the result is that the
3169 above test is done twice. */
Jason Jinece92f82007-07-06 08:34:56 +08003170
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003171 switch (rh) {
3172 case 0:
3173 DECODE_PRINTF("ROL\t");
3174 break;
3175 case 1:
3176 DECODE_PRINTF("ROR\t");
3177 break;
3178 case 2:
3179 DECODE_PRINTF("RCL\t");
3180 break;
3181 case 3:
3182 DECODE_PRINTF("RCR\t");
3183 break;
3184 case 4:
3185 DECODE_PRINTF("SHL\t");
3186 break;
3187 case 5:
3188 DECODE_PRINTF("SHR\t");
3189 break;
3190 case 6:
3191 DECODE_PRINTF("SAL\t");
3192 break;
3193 case 7:
3194 DECODE_PRINTF("SAR\t");
3195 break;
3196 }
Jason Jinece92f82007-07-06 08:34:56 +08003197 }
3198#endif
3199 /* know operation, decode the mod byte to find the addressing
3200 mode. */
3201 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003202 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3203 u32 destval;
Jason Jinece92f82007-07-06 08:34:56 +08003204
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003205 DECODE_PRINTF("DWORD PTR ");
3206 destoffset = decode_rmXX_address(mod, rl);
3207 amt = fetch_byte_imm();
3208 DECODE_PRINTF2(",%x\n", amt);
3209 destval = fetch_data_long(destoffset);
3210 TRACE_AND_STEP();
3211 destval = (*opcD1_long_operation[rh]) (destval, amt);
3212 store_data_long(destoffset, destval);
3213 } else {
3214 u16 destval;
Jason Jinece92f82007-07-06 08:34:56 +08003215
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003216 DECODE_PRINTF("WORD PTR ");
3217 destoffset = decode_rmXX_address(mod, rl);
3218 amt = fetch_byte_imm();
3219 DECODE_PRINTF2(",%x\n", amt);
3220 destval = fetch_data_word(destoffset);
3221 TRACE_AND_STEP();
3222 destval = (*opcD1_word_operation[rh]) (destval, amt);
3223 store_data_word(destoffset, destval);
3224 }
3225 } else { /* register to register */
3226 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3227 u32 *destreg;
Jason Jinece92f82007-07-06 08:34:56 +08003228
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003229 destreg = DECODE_RM_LONG_REGISTER(rl);
3230 amt = fetch_byte_imm();
3231 DECODE_PRINTF2(",%x\n", amt);
3232 TRACE_AND_STEP();
3233 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3234 } else {
3235 u16 *destreg;
Jason Jinece92f82007-07-06 08:34:56 +08003236
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003237 destreg = DECODE_RM_WORD_REGISTER(rl);
3238 amt = fetch_byte_imm();
3239 DECODE_PRINTF2(",%x\n", amt);
3240 TRACE_AND_STEP();
3241 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
3242 }
Jason Jinece92f82007-07-06 08:34:56 +08003243 }
3244 DECODE_CLEAR_SEGOVR();
3245 END_OF_INSTR();
3246}
3247
3248/****************************************************************************
3249REMARKS:
3250Handles opcode 0xc2
3251****************************************************************************/
3252void x86emuOp_ret_near_IMM(u8 X86EMU_UNUSED(op1))
3253{
3254 u16 imm;
3255
3256 START_OF_INSTR();
3257 DECODE_PRINTF("RET\t");
3258 imm = fetch_word_imm();
3259 DECODE_PRINTF2("%x\n", imm);
3260 RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
3261 TRACE_AND_STEP();
3262 M.x86.R_IP = pop_word();
3263 M.x86.R_SP += imm;
3264 DECODE_CLEAR_SEGOVR();
3265 END_OF_INSTR();
3266}
3267
3268/****************************************************************************
3269REMARKS:
3270Handles opcode 0xc3
3271****************************************************************************/
3272void x86emuOp_ret_near(u8 X86EMU_UNUSED(op1))
3273{
3274 START_OF_INSTR();
3275 DECODE_PRINTF("RET\n");
3276 RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
3277 TRACE_AND_STEP();
3278 M.x86.R_IP = pop_word();
3279 DECODE_CLEAR_SEGOVR();
3280 END_OF_INSTR();
3281}
3282
3283/****************************************************************************
3284REMARKS:
3285Handles opcode 0xc4
3286****************************************************************************/
3287void x86emuOp_les_R_IMM(u8 X86EMU_UNUSED(op1))
3288{
3289 int mod, rh, rl;
3290 u16 *dstreg;
3291 uint srcoffset;
3292
3293 START_OF_INSTR();
3294 DECODE_PRINTF("LES\t");
3295 FETCH_DECODE_MODRM(mod, rh, rl);
3296 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003297 dstreg = DECODE_RM_WORD_REGISTER(rh);
3298 DECODE_PRINTF(",");
3299 srcoffset = decode_rmXX_address(mod, rl);
3300 DECODE_PRINTF("\n");
3301 TRACE_AND_STEP();
3302 *dstreg = fetch_data_word(srcoffset);
3303 M.x86.R_ES = fetch_data_word(srcoffset + 2);
Jason Jinece92f82007-07-06 08:34:56 +08003304 }
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003305 /* else UNDEFINED! register to register */
Jason Jinece92f82007-07-06 08:34:56 +08003306
3307 DECODE_CLEAR_SEGOVR();
3308 END_OF_INSTR();
3309}
3310
3311/****************************************************************************
3312REMARKS:
3313Handles opcode 0xc5
3314****************************************************************************/
3315void x86emuOp_lds_R_IMM(u8 X86EMU_UNUSED(op1))
3316{
3317 int mod, rh, rl;
3318 u16 *dstreg;
3319 uint srcoffset;
3320
3321 START_OF_INSTR();
3322 DECODE_PRINTF("LDS\t");
3323 FETCH_DECODE_MODRM(mod, rh, rl);
3324 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003325 dstreg = DECODE_RM_WORD_REGISTER(rh);
3326 DECODE_PRINTF(",");
3327 srcoffset = decode_rmXX_address(mod, rl);
3328 DECODE_PRINTF("\n");
3329 TRACE_AND_STEP();
3330 *dstreg = fetch_data_word(srcoffset);
3331 M.x86.R_DS = fetch_data_word(srcoffset + 2);
Jason Jinece92f82007-07-06 08:34:56 +08003332 }
3333 /* else UNDEFINED! */
3334 DECODE_CLEAR_SEGOVR();
3335 END_OF_INSTR();
3336}
3337
3338/****************************************************************************
3339REMARKS:
3340Handles opcode 0xc6
3341****************************************************************************/
3342void x86emuOp_mov_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
3343{
3344 int mod, rl, rh;
3345 u8 *destreg;
3346 uint destoffset;
3347 u8 imm;
3348
3349 START_OF_INSTR();
3350 DECODE_PRINTF("MOV\t");
3351 FETCH_DECODE_MODRM(mod, rh, rl);
3352 if (rh != 0) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003353 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE c6\n");
3354 HALT_SYS();
Jason Jinece92f82007-07-06 08:34:56 +08003355 }
3356 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003357 DECODE_PRINTF("BYTE PTR ");
3358 destoffset = decode_rmXX_address(mod, rl);
3359 imm = fetch_byte_imm();
3360 DECODE_PRINTF2(",%2x\n", imm);
3361 TRACE_AND_STEP();
3362 store_data_byte(destoffset, imm);
3363 } else { /* register to register */
3364 destreg = DECODE_RM_BYTE_REGISTER(rl);
3365 imm = fetch_byte_imm();
3366 DECODE_PRINTF2(",%2x\n", imm);
3367 TRACE_AND_STEP();
3368 *destreg = imm;
Jason Jinece92f82007-07-06 08:34:56 +08003369 }
3370 DECODE_CLEAR_SEGOVR();
3371 END_OF_INSTR();
3372}
3373
3374/****************************************************************************
3375REMARKS:
3376Handles opcode 0xc7
3377****************************************************************************/
3378void x86emuOp_mov_word_RM_IMM(u8 X86EMU_UNUSED(op1))
3379{
3380 int mod, rl, rh;
3381 uint destoffset;
3382
3383 START_OF_INSTR();
3384 DECODE_PRINTF("MOV\t");
3385 FETCH_DECODE_MODRM(mod, rh, rl);
3386 if (rh != 0) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003387 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
3388 HALT_SYS();
Jason Jinece92f82007-07-06 08:34:56 +08003389 }
3390 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003391 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3392 u32 imm;
Jason Jinece92f82007-07-06 08:34:56 +08003393
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003394 DECODE_PRINTF("DWORD PTR ");
3395 destoffset = decode_rmXX_address(mod, rl);
3396 imm = fetch_long_imm();
3397 DECODE_PRINTF2(",%x\n", imm);
3398 TRACE_AND_STEP();
3399 store_data_long(destoffset, imm);
3400 } else {
3401 u16 imm;
Jason Jinece92f82007-07-06 08:34:56 +08003402
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003403 DECODE_PRINTF("WORD PTR ");
3404 destoffset = decode_rmXX_address(mod, rl);
3405 imm = fetch_word_imm();
3406 DECODE_PRINTF2(",%x\n", imm);
3407 TRACE_AND_STEP();
3408 store_data_word(destoffset, imm);
3409 }
3410 } else { /* register to register */
3411 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Jason Jinece92f82007-07-06 08:34:56 +08003412 u32 *destreg;
3413 u32 imm;
3414
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003415 destreg = DECODE_RM_LONG_REGISTER(rl);
3416 imm = fetch_long_imm();
3417 DECODE_PRINTF2(",%x\n", imm);
3418 TRACE_AND_STEP();
3419 *destreg = imm;
3420 } else {
Jason Jinece92f82007-07-06 08:34:56 +08003421 u16 *destreg;
3422 u16 imm;
3423
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003424 destreg = DECODE_RM_WORD_REGISTER(rl);
3425 imm = fetch_word_imm();
3426 DECODE_PRINTF2(",%x\n", imm);
3427 TRACE_AND_STEP();
3428 *destreg = imm;
3429 }
Jason Jinece92f82007-07-06 08:34:56 +08003430 }
3431 DECODE_CLEAR_SEGOVR();
3432 END_OF_INSTR();
3433}
3434
3435/****************************************************************************
3436REMARKS:
3437Handles opcode 0xc8
3438****************************************************************************/
3439void x86emuOp_enter(u8 X86EMU_UNUSED(op1))
3440{
3441 u16 local,frame_pointer;
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003442 u8 nesting;
Jason Jinece92f82007-07-06 08:34:56 +08003443 int i;
3444
3445 START_OF_INSTR();
3446 local = fetch_word_imm();
3447 nesting = fetch_byte_imm();
3448 DECODE_PRINTF2("ENTER %x\n", local);
3449 DECODE_PRINTF2(",%x\n", nesting);
3450 TRACE_AND_STEP();
3451 push_word(M.x86.R_BP);
3452 frame_pointer = M.x86.R_SP;
3453 if (nesting > 0) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003454 for (i = 1; i < nesting; i++) {
3455 M.x86.R_BP -= 2;
3456 push_word(fetch_data_word_abs(M.x86.R_SS, M.x86.R_BP));
3457 }
3458 push_word(frame_pointer);
3459 }
Jason Jinece92f82007-07-06 08:34:56 +08003460 M.x86.R_BP = frame_pointer;
3461 M.x86.R_SP = (u16)(M.x86.R_SP - local);
3462 DECODE_CLEAR_SEGOVR();
3463 END_OF_INSTR();
3464}
3465
3466/****************************************************************************
3467REMARKS:
3468Handles opcode 0xc9
3469****************************************************************************/
3470void x86emuOp_leave(u8 X86EMU_UNUSED(op1))
3471{
3472 START_OF_INSTR();
3473 DECODE_PRINTF("LEAVE\n");
3474 TRACE_AND_STEP();
3475 M.x86.R_SP = M.x86.R_BP;
3476 M.x86.R_BP = pop_word();
3477 DECODE_CLEAR_SEGOVR();
3478 END_OF_INSTR();
3479}
3480
3481/****************************************************************************
3482REMARKS:
3483Handles opcode 0xca
3484****************************************************************************/
3485void x86emuOp_ret_far_IMM(u8 X86EMU_UNUSED(op1))
3486{
3487 u16 imm;
3488
3489 START_OF_INSTR();
3490 DECODE_PRINTF("RETF\t");
3491 imm = fetch_word_imm();
3492 DECODE_PRINTF2("%x\n", imm);
3493 RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
3494 TRACE_AND_STEP();
3495 M.x86.R_IP = pop_word();
3496 M.x86.R_CS = pop_word();
3497 M.x86.R_SP += imm;
3498 DECODE_CLEAR_SEGOVR();
3499 END_OF_INSTR();
3500}
3501
3502/****************************************************************************
3503REMARKS:
3504Handles opcode 0xcb
3505****************************************************************************/
3506void x86emuOp_ret_far(u8 X86EMU_UNUSED(op1))
3507{
3508 START_OF_INSTR();
3509 DECODE_PRINTF("RETF\n");
3510 RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
3511 TRACE_AND_STEP();
3512 M.x86.R_IP = pop_word();
3513 M.x86.R_CS = pop_word();
3514 DECODE_CLEAR_SEGOVR();
3515 END_OF_INSTR();
3516}
3517
3518/****************************************************************************
3519REMARKS:
3520Handles opcode 0xcc
3521****************************************************************************/
3522void x86emuOp_int3(u8 X86EMU_UNUSED(op1))
3523{
3524 u16 tmp;
3525
3526 START_OF_INSTR();
3527 DECODE_PRINTF("INT 3\n");
3528 tmp = (u16) mem_access_word(3 * 4 + 2);
3529 /* access the segment register */
3530 TRACE_AND_STEP();
3531 if (_X86EMU_intrTab[3]) {
3532 (*_X86EMU_intrTab[3])(3);
3533 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003534 push_word((u16)M.x86.R_FLG);
3535 CLEAR_FLAG(F_IF);
3536 CLEAR_FLAG(F_TF);
3537 push_word(M.x86.R_CS);
3538 M.x86.R_CS = mem_access_word(3 * 4 + 2);
3539 push_word(M.x86.R_IP);
3540 M.x86.R_IP = mem_access_word(3 * 4);
Jason Jinece92f82007-07-06 08:34:56 +08003541 }
3542 DECODE_CLEAR_SEGOVR();
3543 END_OF_INSTR();
3544}
3545
3546/****************************************************************************
3547REMARKS:
3548Handles opcode 0xcd
3549****************************************************************************/
3550void x86emuOp_int_IMM(u8 X86EMU_UNUSED(op1))
3551{
3552 u16 tmp;
3553 u8 intnum;
3554
3555 START_OF_INSTR();
3556 DECODE_PRINTF("INT\t");
3557 intnum = fetch_byte_imm();
3558 DECODE_PRINTF2("%x\n", intnum);
3559 tmp = mem_access_word(intnum * 4 + 2);
3560 TRACE_AND_STEP();
3561 if (_X86EMU_intrTab[intnum]) {
3562 (*_X86EMU_intrTab[intnum])(intnum);
3563 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003564 push_word((u16)M.x86.R_FLG);
3565 CLEAR_FLAG(F_IF);
3566 CLEAR_FLAG(F_TF);
3567 push_word(M.x86.R_CS);
3568 M.x86.R_CS = mem_access_word(intnum * 4 + 2);
3569 push_word(M.x86.R_IP);
3570 M.x86.R_IP = mem_access_word(intnum * 4);
Jason Jinece92f82007-07-06 08:34:56 +08003571 }
3572 DECODE_CLEAR_SEGOVR();
3573 END_OF_INSTR();
3574}
3575
3576/****************************************************************************
3577REMARKS:
3578Handles opcode 0xce
3579****************************************************************************/
3580void x86emuOp_into(u8 X86EMU_UNUSED(op1))
3581{
3582 u16 tmp;
3583
3584 START_OF_INSTR();
3585 DECODE_PRINTF("INTO\n");
3586 TRACE_AND_STEP();
3587 if (ACCESS_FLAG(F_OF)) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003588 tmp = mem_access_word(4 * 4 + 2);
Jason Jinece92f82007-07-06 08:34:56 +08003589 if (_X86EMU_intrTab[4]) {
3590 (*_X86EMU_intrTab[4])(4);
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003591 } else {
3592 push_word((u16)M.x86.R_FLG);
3593 CLEAR_FLAG(F_IF);
3594 CLEAR_FLAG(F_TF);
3595 push_word(M.x86.R_CS);
3596 M.x86.R_CS = mem_access_word(4 * 4 + 2);
3597 push_word(M.x86.R_IP);
3598 M.x86.R_IP = mem_access_word(4 * 4);
3599 }
Jason Jinece92f82007-07-06 08:34:56 +08003600 }
3601 DECODE_CLEAR_SEGOVR();
3602 END_OF_INSTR();
3603}
3604
3605/****************************************************************************
3606REMARKS:
3607Handles opcode 0xcf
3608****************************************************************************/
3609void x86emuOp_iret(u8 X86EMU_UNUSED(op1))
3610{
3611 START_OF_INSTR();
3612 DECODE_PRINTF("IRET\n");
3613
3614 TRACE_AND_STEP();
3615
3616 M.x86.R_IP = pop_word();
3617 M.x86.R_CS = pop_word();
3618 M.x86.R_FLG = pop_word();
3619 DECODE_CLEAR_SEGOVR();
3620 END_OF_INSTR();
3621}
3622
3623/****************************************************************************
3624REMARKS:
3625Handles opcode 0xd0
3626****************************************************************************/
3627void x86emuOp_opcD0_byte_RM_1(u8 X86EMU_UNUSED(op1))
3628{
3629 int mod, rl, rh;
3630 u8 *destreg;
3631 uint destoffset;
3632 u8 destval;
3633
3634 /*
3635 * Yet another weirdo special case instruction format. Part of
3636 * the opcode held below in "RH". Doubly nested case would
3637 * result, except that the decoded instruction
3638 */
3639 START_OF_INSTR();
3640 FETCH_DECODE_MODRM(mod, rh, rl);
3641#ifdef DEBUG
3642 if (DEBUG_DECODE()) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003643 /* XXX DECODE_PRINTF may be changed to something more
3644 general, so that it is important to leave the strings
3645 in the same format, even though the result is that the
3646 above test is done twice. */
3647 switch (rh) {
3648 case 0:
3649 DECODE_PRINTF("ROL\t");
3650 break;
3651 case 1:
3652 DECODE_PRINTF("ROR\t");
3653 break;
3654 case 2:
3655 DECODE_PRINTF("RCL\t");
3656 break;
3657 case 3:
3658 DECODE_PRINTF("RCR\t");
3659 break;
3660 case 4:
3661 DECODE_PRINTF("SHL\t");
3662 break;
3663 case 5:
3664 DECODE_PRINTF("SHR\t");
3665 break;
3666 case 6:
3667 DECODE_PRINTF("SAL\t");
3668 break;
3669 case 7:
3670 DECODE_PRINTF("SAR\t");
3671 break;
3672 }
Jason Jinece92f82007-07-06 08:34:56 +08003673 }
3674#endif
3675 /* know operation, decode the mod byte to find the addressing
3676 mode. */
3677 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003678 DECODE_PRINTF("BYTE PTR ");
3679 destoffset = decode_rmXX_address(mod, rl);
3680 DECODE_PRINTF(",1\n");
3681 destval = fetch_data_byte(destoffset);
3682 TRACE_AND_STEP();
3683 destval = (*opcD0_byte_operation[rh]) (destval, 1);
3684 store_data_byte(destoffset, destval);
3685 } else { /* register to register */
3686 destreg = DECODE_RM_BYTE_REGISTER(rl);
3687 DECODE_PRINTF(",1\n");
3688 TRACE_AND_STEP();
3689 destval = (*opcD0_byte_operation[rh]) (*destreg, 1);
3690 *destreg = destval;
Jason Jinece92f82007-07-06 08:34:56 +08003691 }
3692 DECODE_CLEAR_SEGOVR();
3693 END_OF_INSTR();
3694}
3695
3696/****************************************************************************
3697REMARKS:
3698Handles opcode 0xd1
3699****************************************************************************/
3700void x86emuOp_opcD1_word_RM_1(u8 X86EMU_UNUSED(op1))
3701{
3702 int mod, rl, rh;
3703 uint destoffset;
3704
3705 /*
3706 * Yet another weirdo special case instruction format. Part of
3707 * the opcode held below in "RH". Doubly nested case would
3708 * result, except that the decoded instruction
3709 */
3710 START_OF_INSTR();
3711 FETCH_DECODE_MODRM(mod, rh, rl);
3712#ifdef DEBUG
3713 if (DEBUG_DECODE()) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003714 /* XXX DECODE_PRINTF may be changed to something more
3715 general, so that it is important to leave the strings
3716 in the same format, even though the result is that the
3717 above test is done twice. */
3718 switch (rh) {
3719 case 0:
3720 DECODE_PRINTF("ROL\t");
3721 break;
3722 case 1:
3723 DECODE_PRINTF("ROR\t");
3724 break;
3725 case 2:
3726 DECODE_PRINTF("RCL\t");
3727 break;
3728 case 3:
3729 DECODE_PRINTF("RCR\t");
3730 break;
3731 case 4:
3732 DECODE_PRINTF("SHL\t");
3733 break;
3734 case 5:
3735 DECODE_PRINTF("SHR\t");
3736 break;
3737 case 6:
3738 DECODE_PRINTF("SAL\t");
3739 break;
3740 case 7:
3741 DECODE_PRINTF("SAR\t");
3742 break;
3743 }
Jason Jinece92f82007-07-06 08:34:56 +08003744 }
3745#endif
3746 /* know operation, decode the mod byte to find the addressing
3747 mode. */
3748 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003749 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3750 u32 destval;
Jason Jinece92f82007-07-06 08:34:56 +08003751
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003752 DECODE_PRINTF("DWORD PTR ");
3753 destoffset = decode_rmXX_address(mod, rl);
3754 DECODE_PRINTF(",1\n");
3755 destval = fetch_data_long(destoffset);
3756 TRACE_AND_STEP();
3757 destval = (*opcD1_long_operation[rh]) (destval, 1);
3758 store_data_long(destoffset, destval);
3759 } else {
3760 u16 destval;
Jason Jinece92f82007-07-06 08:34:56 +08003761
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003762 DECODE_PRINTF("WORD PTR ");
3763 destoffset = decode_rmXX_address(mod, rl);
3764 DECODE_PRINTF(",1\n");
3765 destval = fetch_data_word(destoffset);
3766 TRACE_AND_STEP();
3767 destval = (*opcD1_word_operation[rh]) (destval, 1);
3768 store_data_word(destoffset, destval);
3769 }
3770 } else { /* register to register */
3771 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Jason Jinece92f82007-07-06 08:34:56 +08003772 u32 destval;
3773 u32 *destreg;
3774
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003775 destreg = DECODE_RM_LONG_REGISTER(rl);
3776 DECODE_PRINTF(",1\n");
3777 TRACE_AND_STEP();
3778 destval = (*opcD1_long_operation[rh]) (*destreg, 1);
3779 *destreg = destval;
3780 } else {
Jason Jinece92f82007-07-06 08:34:56 +08003781 u16 destval;
3782 u16 *destreg;
3783
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003784 destreg = DECODE_RM_WORD_REGISTER(rl);
3785 DECODE_PRINTF(",1\n");
3786 TRACE_AND_STEP();
3787 destval = (*opcD1_word_operation[rh]) (*destreg, 1);
3788 *destreg = destval;
3789 }
Jason Jinece92f82007-07-06 08:34:56 +08003790 }
3791 DECODE_CLEAR_SEGOVR();
3792 END_OF_INSTR();
3793}
3794
3795/****************************************************************************
3796REMARKS:
3797Handles opcode 0xd2
3798****************************************************************************/
3799void x86emuOp_opcD2_byte_RM_CL(u8 X86EMU_UNUSED(op1))
3800{
3801 int mod, rl, rh;
3802 u8 *destreg;
3803 uint destoffset;
3804 u8 destval;
3805 u8 amt;
3806
3807 /*
3808 * Yet another weirdo special case instruction format. Part of
3809 * the opcode held below in "RH". Doubly nested case would
3810 * result, except that the decoded instruction
3811 */
3812 START_OF_INSTR();
3813 FETCH_DECODE_MODRM(mod, rh, rl);
3814#ifdef DEBUG
3815 if (DEBUG_DECODE()) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003816 /* XXX DECODE_PRINTF may be changed to something more
3817 general, so that it is important to leave the strings
3818 in the same format, even though the result is that the
3819 above test is done twice. */
3820 switch (rh) {
3821 case 0:
3822 DECODE_PRINTF("ROL\t");
3823 break;
3824 case 1:
3825 DECODE_PRINTF("ROR\t");
3826 break;
3827 case 2:
3828 DECODE_PRINTF("RCL\t");
3829 break;
3830 case 3:
3831 DECODE_PRINTF("RCR\t");
3832 break;
3833 case 4:
3834 DECODE_PRINTF("SHL\t");
3835 break;
3836 case 5:
3837 DECODE_PRINTF("SHR\t");
3838 break;
3839 case 6:
3840 DECODE_PRINTF("SAL\t");
3841 break;
3842 case 7:
3843 DECODE_PRINTF("SAR\t");
3844 break;
3845 }
Jason Jinece92f82007-07-06 08:34:56 +08003846 }
3847#endif
3848 /* know operation, decode the mod byte to find the addressing
3849 mode. */
3850 amt = M.x86.R_CL;
3851 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003852 DECODE_PRINTF("BYTE PTR ");
3853 destoffset = decode_rmXX_address(mod, rl);
3854 DECODE_PRINTF(",CL\n");
3855 destval = fetch_data_byte(destoffset);
3856 TRACE_AND_STEP();
3857 destval = (*opcD0_byte_operation[rh]) (destval, amt);
3858 store_data_byte(destoffset, destval);
3859 } else { /* register to register */
3860 destreg = DECODE_RM_BYTE_REGISTER(rl);
3861 DECODE_PRINTF(",CL\n");
3862 TRACE_AND_STEP();
3863 destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3864 *destreg = destval;
Jason Jinece92f82007-07-06 08:34:56 +08003865 }
3866 DECODE_CLEAR_SEGOVR();
3867 END_OF_INSTR();
3868}
3869
3870/****************************************************************************
3871REMARKS:
3872Handles opcode 0xd3
3873****************************************************************************/
3874void x86emuOp_opcD3_word_RM_CL(u8 X86EMU_UNUSED(op1))
3875{
3876 int mod, rl, rh;
3877 uint destoffset;
3878 u8 amt;
3879
3880 /*
3881 * Yet another weirdo special case instruction format. Part of
3882 * the opcode held below in "RH". Doubly nested case would
3883 * result, except that the decoded instruction
3884 */
3885 START_OF_INSTR();
3886 FETCH_DECODE_MODRM(mod, rh, rl);
3887#ifdef DEBUG
3888 if (DEBUG_DECODE()) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003889 /* XXX DECODE_PRINTF may be changed to something more
3890 general, so that it is important to leave the strings
3891 in the same format, even though the result is that the
3892 above test is done twice. */
3893 switch (rh) {
3894 case 0:
3895 DECODE_PRINTF("ROL\t");
3896 break;
3897 case 1:
3898 DECODE_PRINTF("ROR\t");
3899 break;
3900 case 2:
3901 DECODE_PRINTF("RCL\t");
3902 break;
3903 case 3:
3904 DECODE_PRINTF("RCR\t");
3905 break;
3906 case 4:
3907 DECODE_PRINTF("SHL\t");
3908 break;
3909 case 5:
3910 DECODE_PRINTF("SHR\t");
3911 break;
3912 case 6:
3913 DECODE_PRINTF("SAL\t");
3914 break;
3915 case 7:
3916 DECODE_PRINTF("SAR\t");
3917 break;
3918 }
Jason Jinece92f82007-07-06 08:34:56 +08003919 }
3920#endif
3921 /* know operation, decode the mod byte to find the addressing
3922 mode. */
3923 amt = M.x86.R_CL;
3924 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003925 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3926 u32 destval;
Jason Jinece92f82007-07-06 08:34:56 +08003927
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003928 DECODE_PRINTF("DWORD PTR ");
3929 destoffset = decode_rmXX_address(mod, rl);
3930 DECODE_PRINTF(",CL\n");
3931 destval = fetch_data_long(destoffset);
3932 TRACE_AND_STEP();
3933 destval = (*opcD1_long_operation[rh]) (destval, amt);
3934 store_data_long(destoffset, destval);
3935 } else {
3936 u16 destval;
Jason Jinece92f82007-07-06 08:34:56 +08003937
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003938 DECODE_PRINTF("WORD PTR ");
3939 destoffset = decode_rmXX_address(mod, rl);
3940 DECODE_PRINTF(",CL\n");
3941 destval = fetch_data_word(destoffset);
3942 TRACE_AND_STEP();
3943 destval = (*opcD1_word_operation[rh]) (destval, amt);
3944 store_data_word(destoffset, destval);
3945 }
3946 } else { /* register to register */
3947 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3948 u32 *destreg;
Jason Jinece92f82007-07-06 08:34:56 +08003949
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003950 destreg = DECODE_RM_LONG_REGISTER(rl);
3951 DECODE_PRINTF(",CL\n");
3952 TRACE_AND_STEP();
3953 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3954 } else {
3955 u16 *destreg;
Jason Jinece92f82007-07-06 08:34:56 +08003956
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003957 destreg = DECODE_RM_WORD_REGISTER(rl);
3958 DECODE_PRINTF(",CL\n");
3959 TRACE_AND_STEP();
3960 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
3961 }
Jason Jinece92f82007-07-06 08:34:56 +08003962 }
3963 DECODE_CLEAR_SEGOVR();
3964 END_OF_INSTR();
3965}
3966
3967/****************************************************************************
3968REMARKS:
3969Handles opcode 0xd4
3970****************************************************************************/
3971void x86emuOp_aam(u8 X86EMU_UNUSED(op1))
3972{
3973 u8 a;
3974
3975 START_OF_INSTR();
3976 DECODE_PRINTF("AAM\n");
3977 a = fetch_byte_imm(); /* this is a stupid encoding. */
3978 if (a != 10) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003979 DECODE_PRINTF("ERROR DECODING AAM\n");
3980 TRACE_REGS();
3981 HALT_SYS();
Jason Jinece92f82007-07-06 08:34:56 +08003982 }
3983 TRACE_AND_STEP();
3984 /* note the type change here --- returning AL and AH in AX. */
3985 M.x86.R_AX = aam_word(M.x86.R_AL);
3986 DECODE_CLEAR_SEGOVR();
3987 END_OF_INSTR();
3988}
3989
3990/****************************************************************************
3991REMARKS:
3992Handles opcode 0xd5
3993****************************************************************************/
3994void x86emuOp_aad(u8 X86EMU_UNUSED(op1))
3995{
3996 u8 a;
3997
3998 START_OF_INSTR();
3999 DECODE_PRINTF("AAD\n");
4000 a = fetch_byte_imm();
4001 TRACE_AND_STEP();
4002 M.x86.R_AX = aad_word(M.x86.R_AX);
4003 DECODE_CLEAR_SEGOVR();
4004 END_OF_INSTR();
4005}
4006
4007/* opcode 0xd6 ILLEGAL OPCODE */
4008
4009/****************************************************************************
4010REMARKS:
4011Handles opcode 0xd7
4012****************************************************************************/
4013void x86emuOp_xlat(u8 X86EMU_UNUSED(op1))
4014{
4015 u16 addr;
4016
4017 START_OF_INSTR();
4018 DECODE_PRINTF("XLAT\n");
4019 TRACE_AND_STEP();
4020 addr = (u16)(M.x86.R_BX + (u8)M.x86.R_AL);
4021 M.x86.R_AL = fetch_data_byte(addr);
4022 DECODE_CLEAR_SEGOVR();
4023 END_OF_INSTR();
4024}
4025
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004026/* instuctions D8 .. DF are in i87_ops.c */
Jason Jinece92f82007-07-06 08:34:56 +08004027
4028/****************************************************************************
4029REMARKS:
4030Handles opcode 0xe0
4031****************************************************************************/
4032void x86emuOp_loopne(u8 X86EMU_UNUSED(op1))
4033{
4034 s16 ip;
4035
4036 START_OF_INSTR();
4037 DECODE_PRINTF("LOOPNE\t");
4038 ip = (s8) fetch_byte_imm();
4039 ip += (s16) M.x86.R_IP;
4040 DECODE_PRINTF2("%04x\n", ip);
4041 TRACE_AND_STEP();
4042 M.x86.R_CX -= 1;
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004043 if (M.x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */
4044 M.x86.R_IP = ip;
Jason Jinece92f82007-07-06 08:34:56 +08004045 DECODE_CLEAR_SEGOVR();
4046 END_OF_INSTR();
4047}
4048
4049/****************************************************************************
4050REMARKS:
4051Handles opcode 0xe1
4052****************************************************************************/
4053void x86emuOp_loope(u8 X86EMU_UNUSED(op1))
4054{
4055 s16 ip;
4056
4057 START_OF_INSTR();
4058 DECODE_PRINTF("LOOPE\t");
4059 ip = (s8) fetch_byte_imm();
4060 ip += (s16) M.x86.R_IP;
4061 DECODE_PRINTF2("%04x\n", ip);
4062 TRACE_AND_STEP();
4063 M.x86.R_CX -= 1;
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004064 if (M.x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */
4065 M.x86.R_IP = ip;
Jason Jinece92f82007-07-06 08:34:56 +08004066 DECODE_CLEAR_SEGOVR();
4067 END_OF_INSTR();
4068}
4069
4070/****************************************************************************
4071REMARKS:
4072Handles opcode 0xe2
4073****************************************************************************/
4074void x86emuOp_loop(u8 X86EMU_UNUSED(op1))
4075{
4076 s16 ip;
4077
4078 START_OF_INSTR();
4079 DECODE_PRINTF("LOOP\t");
4080 ip = (s8) fetch_byte_imm();
4081 ip += (s16) M.x86.R_IP;
4082 DECODE_PRINTF2("%04x\n", ip);
4083 TRACE_AND_STEP();
4084 M.x86.R_CX -= 1;
4085 if (M.x86.R_CX != 0)
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004086 M.x86.R_IP = ip;
Jason Jinece92f82007-07-06 08:34:56 +08004087 DECODE_CLEAR_SEGOVR();
4088 END_OF_INSTR();
4089}
4090
4091/****************************************************************************
4092REMARKS:
4093Handles opcode 0xe3
4094****************************************************************************/
4095void x86emuOp_jcxz(u8 X86EMU_UNUSED(op1))
4096{
4097 u16 target;
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004098 s8 offset;
Jason Jinece92f82007-07-06 08:34:56 +08004099
4100 /* jump to byte offset if overflow flag is set */
4101 START_OF_INSTR();
4102 DECODE_PRINTF("JCXZ\t");
4103 offset = (s8)fetch_byte_imm();
4104 target = (u16)(M.x86.R_IP + offset);
4105 DECODE_PRINTF2("%x\n", target);
4106 TRACE_AND_STEP();
4107 if (M.x86.R_CX == 0)
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004108 M.x86.R_IP = target;
Jason Jinece92f82007-07-06 08:34:56 +08004109 DECODE_CLEAR_SEGOVR();
4110 END_OF_INSTR();
4111}
4112
4113/****************************************************************************
4114REMARKS:
4115Handles opcode 0xe4
4116****************************************************************************/
4117void x86emuOp_in_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
4118{
4119 u8 port;
4120
4121 START_OF_INSTR();
4122 DECODE_PRINTF("IN\t");
4123 port = (u8) fetch_byte_imm();
4124 DECODE_PRINTF2("%x,AL\n", port);
4125 TRACE_AND_STEP();
4126 M.x86.R_AL = (*sys_inb)(port);
4127 DECODE_CLEAR_SEGOVR();
4128 END_OF_INSTR();
4129}
4130
4131/****************************************************************************
4132REMARKS:
4133Handles opcode 0xe5
4134****************************************************************************/
4135void x86emuOp_in_word_AX_IMM(u8 X86EMU_UNUSED(op1))
4136{
4137 u8 port;
4138
4139 START_OF_INSTR();
4140 DECODE_PRINTF("IN\t");
4141 port = (u8) fetch_byte_imm();
4142 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004143 DECODE_PRINTF2("EAX,%x\n", port);
Jason Jinece92f82007-07-06 08:34:56 +08004144 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004145 DECODE_PRINTF2("AX,%x\n", port);
Jason Jinece92f82007-07-06 08:34:56 +08004146 }
4147 TRACE_AND_STEP();
4148 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004149 M.x86.R_EAX = (*sys_inl)(port);
Jason Jinece92f82007-07-06 08:34:56 +08004150 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004151 M.x86.R_AX = (*sys_inw)(port);
Jason Jinece92f82007-07-06 08:34:56 +08004152 }
4153 DECODE_CLEAR_SEGOVR();
4154 END_OF_INSTR();
4155}
4156
4157/****************************************************************************
4158REMARKS:
4159Handles opcode 0xe6
4160****************************************************************************/
4161void x86emuOp_out_byte_IMM_AL(u8 X86EMU_UNUSED(op1))
4162{
4163 u8 port;
4164
4165 START_OF_INSTR();
4166 DECODE_PRINTF("OUT\t");
4167 port = (u8) fetch_byte_imm();
4168 DECODE_PRINTF2("%x,AL\n", port);
4169 TRACE_AND_STEP();
4170 (*sys_outb)(port, M.x86.R_AL);
4171 DECODE_CLEAR_SEGOVR();
4172 END_OF_INSTR();
4173}
4174
4175/****************************************************************************
4176REMARKS:
4177Handles opcode 0xe7
4178****************************************************************************/
4179void x86emuOp_out_word_IMM_AX(u8 X86EMU_UNUSED(op1))
4180{
4181 u8 port;
4182
4183 START_OF_INSTR();
4184 DECODE_PRINTF("OUT\t");
4185 port = (u8) fetch_byte_imm();
4186 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004187 DECODE_PRINTF2("%x,EAX\n", port);
Jason Jinece92f82007-07-06 08:34:56 +08004188 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004189 DECODE_PRINTF2("%x,AX\n", port);
Jason Jinece92f82007-07-06 08:34:56 +08004190 }
4191 TRACE_AND_STEP();
4192 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004193 (*sys_outl)(port, M.x86.R_EAX);
Jason Jinece92f82007-07-06 08:34:56 +08004194 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004195 (*sys_outw)(port, M.x86.R_AX);
Jason Jinece92f82007-07-06 08:34:56 +08004196 }
4197 DECODE_CLEAR_SEGOVR();
4198 END_OF_INSTR();
4199}
4200
4201/****************************************************************************
4202REMARKS:
4203Handles opcode 0xe8
4204****************************************************************************/
4205void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1))
4206{
4207 s16 ip;
4208
4209 START_OF_INSTR();
4210 DECODE_PRINTF("CALL\t");
4211 ip = (s16) fetch_word_imm();
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004212 ip += (s16) M.x86.R_IP; /* CHECK SIGN */
Jason Jinece92f82007-07-06 08:34:56 +08004213 DECODE_PRINTF2("%04x\n", ip);
4214 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, "");
4215 TRACE_AND_STEP();
4216 push_word(M.x86.R_IP);
4217 M.x86.R_IP = ip;
4218 DECODE_CLEAR_SEGOVR();
4219 END_OF_INSTR();
4220}
4221
4222/****************************************************************************
4223REMARKS:
4224Handles opcode 0xe9
4225****************************************************************************/
4226void x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1))
4227{
4228 int ip;
4229
4230 START_OF_INSTR();
4231 DECODE_PRINTF("JMP\t");
4232 ip = (s16)fetch_word_imm();
4233 ip += (s16)M.x86.R_IP;
4234 DECODE_PRINTF2("%04x\n", ip);
4235 TRACE_AND_STEP();
4236 M.x86.R_IP = (u16)ip;
4237 DECODE_CLEAR_SEGOVR();
4238 END_OF_INSTR();
4239}
4240
4241/****************************************************************************
4242REMARKS:
4243Handles opcode 0xea
4244****************************************************************************/
4245void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1))
4246{
4247 u16 cs, ip;
4248
4249 START_OF_INSTR();
4250 DECODE_PRINTF("JMP\tFAR ");
4251 ip = fetch_word_imm();
4252 cs = fetch_word_imm();
4253 DECODE_PRINTF2("%04x:", cs);
4254 DECODE_PRINTF2("%04x\n", ip);
4255 TRACE_AND_STEP();
4256 M.x86.R_IP = ip;
4257 M.x86.R_CS = cs;
4258 DECODE_CLEAR_SEGOVR();
4259 END_OF_INSTR();
4260}
4261
4262/****************************************************************************
4263REMARKS:
4264Handles opcode 0xeb
4265****************************************************************************/
4266void x86emuOp_jump_byte_IMM(u8 X86EMU_UNUSED(op1))
4267{
4268 u16 target;
4269 s8 offset;
4270
4271 START_OF_INSTR();
4272 DECODE_PRINTF("JMP\t");
4273 offset = (s8)fetch_byte_imm();
4274 target = (u16)(M.x86.R_IP + offset);
4275 DECODE_PRINTF2("%x\n", target);
4276 TRACE_AND_STEP();
4277 M.x86.R_IP = target;
4278 DECODE_CLEAR_SEGOVR();
4279 END_OF_INSTR();
4280}
4281
4282/****************************************************************************
4283REMARKS:
4284Handles opcode 0xec
4285****************************************************************************/
4286void x86emuOp_in_byte_AL_DX(u8 X86EMU_UNUSED(op1))
4287{
4288 START_OF_INSTR();
4289 DECODE_PRINTF("IN\tAL,DX\n");
4290 TRACE_AND_STEP();
4291 M.x86.R_AL = (*sys_inb)(M.x86.R_DX);
4292 DECODE_CLEAR_SEGOVR();
4293 END_OF_INSTR();
4294}
4295
4296/****************************************************************************
4297REMARKS:
4298Handles opcode 0xed
4299****************************************************************************/
4300void x86emuOp_in_word_AX_DX(u8 X86EMU_UNUSED(op1))
4301{
4302 START_OF_INSTR();
4303 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004304 DECODE_PRINTF("IN\tEAX,DX\n");
Jason Jinece92f82007-07-06 08:34:56 +08004305 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004306 DECODE_PRINTF("IN\tAX,DX\n");
Jason Jinece92f82007-07-06 08:34:56 +08004307 }
4308 TRACE_AND_STEP();
4309 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004310 M.x86.R_EAX = (*sys_inl)(M.x86.R_DX);
Jason Jinece92f82007-07-06 08:34:56 +08004311 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004312 M.x86.R_AX = (*sys_inw)(M.x86.R_DX);
Jason Jinece92f82007-07-06 08:34:56 +08004313 }
4314 DECODE_CLEAR_SEGOVR();
4315 END_OF_INSTR();
4316}
4317
4318/****************************************************************************
4319REMARKS:
4320Handles opcode 0xee
4321****************************************************************************/
4322void x86emuOp_out_byte_DX_AL(u8 X86EMU_UNUSED(op1))
4323{
4324 START_OF_INSTR();
4325 DECODE_PRINTF("OUT\tDX,AL\n");
4326 TRACE_AND_STEP();
4327 (*sys_outb)(M.x86.R_DX, M.x86.R_AL);
4328 DECODE_CLEAR_SEGOVR();
4329 END_OF_INSTR();
4330}
4331
4332/****************************************************************************
4333REMARKS:
4334Handles opcode 0xef
4335****************************************************************************/
4336void x86emuOp_out_word_DX_AX(u8 X86EMU_UNUSED(op1))
4337{
4338 START_OF_INSTR();
4339 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004340 DECODE_PRINTF("OUT\tDX,EAX\n");
Jason Jinece92f82007-07-06 08:34:56 +08004341 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004342 DECODE_PRINTF("OUT\tDX,AX\n");
Jason Jinece92f82007-07-06 08:34:56 +08004343 }
4344 TRACE_AND_STEP();
4345 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004346 (*sys_outl)(M.x86.R_DX, M.x86.R_EAX);
Jason Jinece92f82007-07-06 08:34:56 +08004347 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004348 (*sys_outw)(M.x86.R_DX, M.x86.R_AX);
Jason Jinece92f82007-07-06 08:34:56 +08004349 }
4350 DECODE_CLEAR_SEGOVR();
4351 END_OF_INSTR();
4352}
4353
4354/****************************************************************************
4355REMARKS:
4356Handles opcode 0xf0
4357****************************************************************************/
4358void x86emuOp_lock(u8 X86EMU_UNUSED(op1))
4359{
4360 START_OF_INSTR();
4361 DECODE_PRINTF("LOCK:\n");
4362 TRACE_AND_STEP();
4363 DECODE_CLEAR_SEGOVR();
4364 END_OF_INSTR();
4365}
4366
4367/*opcode 0xf1 ILLEGAL OPERATION */
4368
4369/****************************************************************************
4370REMARKS:
4371Handles opcode 0xf2
4372****************************************************************************/
4373void x86emuOp_repne(u8 X86EMU_UNUSED(op1))
4374{
4375 START_OF_INSTR();
4376 DECODE_PRINTF("REPNE\n");
4377 TRACE_AND_STEP();
4378 M.x86.mode |= SYSMODE_PREFIX_REPNE;
4379 DECODE_CLEAR_SEGOVR();
4380 END_OF_INSTR();
4381}
4382
4383/****************************************************************************
4384REMARKS:
4385Handles opcode 0xf3
4386****************************************************************************/
4387void x86emuOp_repe(u8 X86EMU_UNUSED(op1))
4388{
4389 START_OF_INSTR();
4390 DECODE_PRINTF("REPE\n");
4391 TRACE_AND_STEP();
4392 M.x86.mode |= SYSMODE_PREFIX_REPE;
4393 DECODE_CLEAR_SEGOVR();
4394 END_OF_INSTR();
4395}
4396
4397/****************************************************************************
4398REMARKS:
4399Handles opcode 0xf4
4400****************************************************************************/
4401void x86emuOp_halt(u8 X86EMU_UNUSED(op1))
4402{
4403 START_OF_INSTR();
4404 DECODE_PRINTF("HALT\n");
4405 TRACE_AND_STEP();
4406 HALT_SYS();
4407 DECODE_CLEAR_SEGOVR();
4408 END_OF_INSTR();
4409}
4410
4411/****************************************************************************
4412REMARKS:
4413Handles opcode 0xf5
4414****************************************************************************/
4415void x86emuOp_cmc(u8 X86EMU_UNUSED(op1))
4416{
4417 /* complement the carry flag. */
4418 START_OF_INSTR();
4419 DECODE_PRINTF("CMC\n");
4420 TRACE_AND_STEP();
4421 TOGGLE_FLAG(F_CF);
4422 DECODE_CLEAR_SEGOVR();
4423 END_OF_INSTR();
4424}
4425
4426/****************************************************************************
4427REMARKS:
4428Handles opcode 0xf6
4429****************************************************************************/
4430void x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1))
4431{
4432 int mod, rl, rh;
4433 u8 *destreg;
4434 uint destoffset;
4435 u8 destval, srcval;
4436
4437 /* long, drawn out code follows. Double switch for a total
4438 of 32 cases. */
4439 START_OF_INSTR();
4440 FETCH_DECODE_MODRM(mod, rh, rl);
4441 DECODE_PRINTF(opF6_names[rh]);
4442 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004443 DECODE_PRINTF("BYTE PTR ");
4444 destoffset = decode_rmXX_address(mod, rl);
4445 destval = fetch_data_byte(destoffset);
Jason Jinece92f82007-07-06 08:34:56 +08004446
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004447 switch (rh) {
4448 case 0: /* test byte imm */
4449 DECODE_PRINTF(",");
4450 srcval = fetch_byte_imm();
4451 DECODE_PRINTF2("%02x\n", srcval);
4452 TRACE_AND_STEP();
4453 test_byte(destval, srcval);
4454 break;
4455 case 1:
4456 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4457 HALT_SYS();
4458 break;
4459 case 2:
4460 DECODE_PRINTF("\n");
4461 TRACE_AND_STEP();
4462 destval = not_byte(destval);
4463 store_data_byte(destoffset, destval);
4464 break;
4465 case 3:
4466 DECODE_PRINTF("\n");
4467 TRACE_AND_STEP();
4468 destval = neg_byte(destval);
4469 store_data_byte(destoffset, destval);
4470 break;
4471 case 4:
4472 DECODE_PRINTF("\n");
4473 TRACE_AND_STEP();
4474 mul_byte(destval);
4475 break;
4476 case 5:
4477 DECODE_PRINTF("\n");
4478 TRACE_AND_STEP();
4479 imul_byte(destval);
4480 break;
4481 case 6:
4482 DECODE_PRINTF("\n");
4483 TRACE_AND_STEP();
4484 div_byte(destval);
4485 break;
4486 default:
4487 DECODE_PRINTF("\n");
4488 TRACE_AND_STEP();
4489 idiv_byte(destval);
4490 break;
4491 }
4492 } else { /* mod=11 */
4493 destreg = DECODE_RM_BYTE_REGISTER(rl);
4494 switch (rh) {
4495 case 0: /* test byte imm */
4496 DECODE_PRINTF(",");
4497 srcval = fetch_byte_imm();
4498 DECODE_PRINTF2("%02x\n", srcval);
4499 TRACE_AND_STEP();
4500 test_byte(*destreg, srcval);
4501 break;
4502 case 1:
4503 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4504 HALT_SYS();
4505 break;
4506 case 2:
4507 DECODE_PRINTF("\n");
4508 TRACE_AND_STEP();
4509 *destreg = not_byte(*destreg);
4510 break;
4511 case 3:
4512 DECODE_PRINTF("\n");
4513 TRACE_AND_STEP();
4514 *destreg = neg_byte(*destreg);
4515 break;
4516 case 4:
4517 DECODE_PRINTF("\n");
4518 TRACE_AND_STEP();
4519 mul_byte(*destreg); /*!!! */
4520 break;
4521 case 5:
4522 DECODE_PRINTF("\n");
4523 TRACE_AND_STEP();
4524 imul_byte(*destreg);
4525 break;
4526 case 6:
4527 DECODE_PRINTF("\n");
4528 TRACE_AND_STEP();
4529 div_byte(*destreg);
4530 break;
4531 default:
4532 DECODE_PRINTF("\n");
4533 TRACE_AND_STEP();
4534 idiv_byte(*destreg);
4535 break;
4536 }
Jason Jinece92f82007-07-06 08:34:56 +08004537 }
4538 DECODE_CLEAR_SEGOVR();
4539 END_OF_INSTR();
4540}
4541
4542/****************************************************************************
4543REMARKS:
4544Handles opcode 0xf7
4545****************************************************************************/
4546void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1))
4547{
4548 int mod, rl, rh;
4549 uint destoffset;
4550
4551 START_OF_INSTR();
4552 FETCH_DECODE_MODRM(mod, rh, rl);
4553 DECODE_PRINTF(opF6_names[rh]);
4554 if (mod < 3) {
4555
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004556 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4557 u32 destval, srcval;
Jason Jinece92f82007-07-06 08:34:56 +08004558
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004559 DECODE_PRINTF("DWORD PTR ");
4560 destoffset = decode_rmXX_address(mod, rl);
4561 destval = fetch_data_long(destoffset);
Jason Jinece92f82007-07-06 08:34:56 +08004562
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004563 switch (rh) {
4564 case 0:
4565 DECODE_PRINTF(",");
4566 srcval = fetch_long_imm();
4567 DECODE_PRINTF2("%x\n", srcval);
4568 TRACE_AND_STEP();
4569 test_long(destval, srcval);
4570 break;
4571 case 1:
4572 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4573 HALT_SYS();
4574 break;
4575 case 2:
4576 DECODE_PRINTF("\n");
4577 TRACE_AND_STEP();
4578 destval = not_long(destval);
4579 store_data_long(destoffset, destval);
4580 break;
4581 case 3:
4582 DECODE_PRINTF("\n");
4583 TRACE_AND_STEP();
4584 destval = neg_long(destval);
4585 store_data_long(destoffset, destval);
4586 break;
4587 case 4:
4588 DECODE_PRINTF("\n");
4589 TRACE_AND_STEP();
4590 mul_long(destval);
4591 break;
4592 case 5:
4593 DECODE_PRINTF("\n");
4594 TRACE_AND_STEP();
4595 imul_long(destval);
4596 break;
4597 case 6:
4598 DECODE_PRINTF("\n");
4599 TRACE_AND_STEP();
4600 div_long(destval);
4601 break;
4602 case 7:
4603 DECODE_PRINTF("\n");
4604 TRACE_AND_STEP();
4605 idiv_long(destval);
4606 break;
4607 }
4608 } else {
4609 u16 destval, srcval;
Jason Jinece92f82007-07-06 08:34:56 +08004610
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004611 DECODE_PRINTF("WORD PTR ");
4612 destoffset = decode_rmXX_address(mod, rl);
4613 destval = fetch_data_word(destoffset);
Jason Jinece92f82007-07-06 08:34:56 +08004614
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004615 switch (rh) {
4616 case 0: /* test word imm */
4617 DECODE_PRINTF(",");
4618 srcval = fetch_word_imm();
4619 DECODE_PRINTF2("%x\n", srcval);
4620 TRACE_AND_STEP();
4621 test_word(destval, srcval);
4622 break;
4623 case 1:
4624 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4625 HALT_SYS();
4626 break;
4627 case 2:
4628 DECODE_PRINTF("\n");
4629 TRACE_AND_STEP();
4630 destval = not_word(destval);
4631 store_data_word(destoffset, destval);
4632 break;
4633 case 3:
4634 DECODE_PRINTF("\n");
4635 TRACE_AND_STEP();
4636 destval = neg_word(destval);
4637 store_data_word(destoffset, destval);
4638 break;
4639 case 4:
4640 DECODE_PRINTF("\n");
4641 TRACE_AND_STEP();
4642 mul_word(destval);
4643 break;
4644 case 5:
4645 DECODE_PRINTF("\n");
4646 TRACE_AND_STEP();
4647 imul_word(destval);
4648 break;
4649 case 6:
4650 DECODE_PRINTF("\n");
4651 TRACE_AND_STEP();
4652 div_word(destval);
4653 break;
4654 case 7:
4655 DECODE_PRINTF("\n");
4656 TRACE_AND_STEP();
4657 idiv_word(destval);
4658 break;
4659 }
4660 }
Jason Jinece92f82007-07-06 08:34:56 +08004661
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004662 } else { /* mod=11 */
Jason Jinece92f82007-07-06 08:34:56 +08004663
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004664 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4665 u32 *destreg;
4666 u32 srcval;
Jason Jinece92f82007-07-06 08:34:56 +08004667
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004668 destreg = DECODE_RM_LONG_REGISTER(rl);
Jason Jinece92f82007-07-06 08:34:56 +08004669
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004670 switch (rh) {
4671 case 0: /* test word imm */
4672 DECODE_PRINTF(",");
4673 srcval = fetch_long_imm();
4674 DECODE_PRINTF2("%x\n", srcval);
4675 TRACE_AND_STEP();
4676 test_long(*destreg, srcval);
4677 break;
4678 case 1:
4679 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4680 HALT_SYS();
4681 break;
4682 case 2:
4683 DECODE_PRINTF("\n");
4684 TRACE_AND_STEP();
4685 *destreg = not_long(*destreg);
4686 break;
4687 case 3:
4688 DECODE_PRINTF("\n");
4689 TRACE_AND_STEP();
4690 *destreg = neg_long(*destreg);
4691 break;
4692 case 4:
4693 DECODE_PRINTF("\n");
4694 TRACE_AND_STEP();
4695 mul_long(*destreg); /*!!! */
4696 break;
4697 case 5:
4698 DECODE_PRINTF("\n");
4699 TRACE_AND_STEP();
4700 imul_long(*destreg);
4701 break;
4702 case 6:
4703 DECODE_PRINTF("\n");
4704 TRACE_AND_STEP();
4705 div_long(*destreg);
4706 break;
4707 case 7:
4708 DECODE_PRINTF("\n");
4709 TRACE_AND_STEP();
4710 idiv_long(*destreg);
4711 break;
4712 }
4713 } else {
4714 u16 *destreg;
4715 u16 srcval;
Jason Jinece92f82007-07-06 08:34:56 +08004716
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004717 destreg = DECODE_RM_WORD_REGISTER(rl);
Jason Jinece92f82007-07-06 08:34:56 +08004718
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004719 switch (rh) {
4720 case 0: /* test word imm */
4721 DECODE_PRINTF(",");
4722 srcval = fetch_word_imm();
4723 DECODE_PRINTF2("%x\n", srcval);
4724 TRACE_AND_STEP();
4725 test_word(*destreg, srcval);
4726 break;
4727 case 1:
4728 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4729 HALT_SYS();
4730 break;
4731 case 2:
4732 DECODE_PRINTF("\n");
4733 TRACE_AND_STEP();
4734 *destreg = not_word(*destreg);
4735 break;
4736 case 3:
4737 DECODE_PRINTF("\n");
4738 TRACE_AND_STEP();
4739 *destreg = neg_word(*destreg);
4740 break;
4741 case 4:
4742 DECODE_PRINTF("\n");
4743 TRACE_AND_STEP();
4744 mul_word(*destreg); /*!!! */
4745 break;
4746 case 5:
4747 DECODE_PRINTF("\n");
4748 TRACE_AND_STEP();
4749 imul_word(*destreg);
4750 break;
4751 case 6:
4752 DECODE_PRINTF("\n");
4753 TRACE_AND_STEP();
4754 div_word(*destreg);
4755 break;
4756 case 7:
4757 DECODE_PRINTF("\n");
4758 TRACE_AND_STEP();
4759 idiv_word(*destreg);
4760 break;
4761 }
4762 }
Jason Jinece92f82007-07-06 08:34:56 +08004763 }
4764 DECODE_CLEAR_SEGOVR();
4765 END_OF_INSTR();
4766}
4767
4768/****************************************************************************
4769REMARKS:
4770Handles opcode 0xf8
4771****************************************************************************/
4772void x86emuOp_clc(u8 X86EMU_UNUSED(op1))
4773{
4774 /* clear the carry flag. */
4775 START_OF_INSTR();
4776 DECODE_PRINTF("CLC\n");
4777 TRACE_AND_STEP();
4778 CLEAR_FLAG(F_CF);
4779 DECODE_CLEAR_SEGOVR();
4780 END_OF_INSTR();
4781}
4782
4783/****************************************************************************
4784REMARKS:
4785Handles opcode 0xf9
4786****************************************************************************/
4787void x86emuOp_stc(u8 X86EMU_UNUSED(op1))
4788{
4789 /* set the carry flag. */
4790 START_OF_INSTR();
4791 DECODE_PRINTF("STC\n");
4792 TRACE_AND_STEP();
4793 SET_FLAG(F_CF);
4794 DECODE_CLEAR_SEGOVR();
4795 END_OF_INSTR();
4796}
4797
4798/****************************************************************************
4799REMARKS:
4800Handles opcode 0xfa
4801****************************************************************************/
4802void x86emuOp_cli(u8 X86EMU_UNUSED(op1))
4803{
4804 /* clear interrupts. */
4805 START_OF_INSTR();
4806 DECODE_PRINTF("CLI\n");
4807 TRACE_AND_STEP();
4808 CLEAR_FLAG(F_IF);
4809 DECODE_CLEAR_SEGOVR();
4810 END_OF_INSTR();
4811}
4812
4813/****************************************************************************
4814REMARKS:
4815Handles opcode 0xfb
4816****************************************************************************/
4817void x86emuOp_sti(u8 X86EMU_UNUSED(op1))
4818{
4819 /* enable interrupts. */
4820 START_OF_INSTR();
4821 DECODE_PRINTF("STI\n");
4822 TRACE_AND_STEP();
4823 SET_FLAG(F_IF);
4824 DECODE_CLEAR_SEGOVR();
4825 END_OF_INSTR();
4826}
4827
4828/****************************************************************************
4829REMARKS:
4830Handles opcode 0xfc
4831****************************************************************************/
4832void x86emuOp_cld(u8 X86EMU_UNUSED(op1))
4833{
4834 /* clear interrupts. */
4835 START_OF_INSTR();
4836 DECODE_PRINTF("CLD\n");
4837 TRACE_AND_STEP();
4838 CLEAR_FLAG(F_DF);
4839 DECODE_CLEAR_SEGOVR();
4840 END_OF_INSTR();
4841}
4842
4843/****************************************************************************
4844REMARKS:
4845Handles opcode 0xfd
4846****************************************************************************/
4847void x86emuOp_std(u8 X86EMU_UNUSED(op1))
4848{
4849 /* clear interrupts. */
4850 START_OF_INSTR();
4851 DECODE_PRINTF("STD\n");
4852 TRACE_AND_STEP();
4853 SET_FLAG(F_DF);
4854 DECODE_CLEAR_SEGOVR();
4855 END_OF_INSTR();
4856}
4857
4858/****************************************************************************
4859REMARKS:
4860Handles opcode 0xfe
4861****************************************************************************/
4862void x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1))
4863{
4864 int mod, rh, rl;
4865 u8 destval;
4866 uint destoffset;
4867 u8 *destreg;
4868
4869 /* Yet another special case instruction. */
4870 START_OF_INSTR();
4871 FETCH_DECODE_MODRM(mod, rh, rl);
4872#ifdef DEBUG
4873 if (DEBUG_DECODE()) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004874 /* XXX DECODE_PRINTF may be changed to something more
4875 general, so that it is important to leave the strings
4876 in the same format, even though the result is that the
4877 above test is done twice. */
Jason Jinece92f82007-07-06 08:34:56 +08004878
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004879 switch (rh) {
4880 case 0:
4881 DECODE_PRINTF("INC\t");
4882 break;
4883 case 1:
4884 DECODE_PRINTF("DEC\t");
4885 break;
4886 case 2:
4887 case 3:
4888 case 4:
4889 case 5:
4890 case 6:
4891 case 7:
4892 DECODE_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x \n", mod);
4893 HALT_SYS();
4894 break;
4895 }
Jason Jinece92f82007-07-06 08:34:56 +08004896 }
4897#endif
4898 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004899 DECODE_PRINTF("BYTE PTR ");
4900 destoffset = decode_rmXX_address(mod, rl);
4901 DECODE_PRINTF("\n");
4902 destval = fetch_data_byte(destoffset);
4903 TRACE_AND_STEP();
4904 if (rh == 0)
4905 destval = inc_byte(destval);
4906 else
4907 destval = dec_byte(destval);
4908 store_data_byte(destoffset, destval);
Jason Jinece92f82007-07-06 08:34:56 +08004909 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004910 destreg = DECODE_RM_BYTE_REGISTER(rl);
4911 DECODE_PRINTF("\n");
4912 TRACE_AND_STEP();
4913 if (rh == 0)
4914 *destreg = inc_byte(*destreg);
4915 else
4916 *destreg = dec_byte(*destreg);
Jason Jinece92f82007-07-06 08:34:56 +08004917 }
4918 DECODE_CLEAR_SEGOVR();
4919 END_OF_INSTR();
4920}
4921
4922/****************************************************************************
4923REMARKS:
4924Handles opcode 0xff
4925****************************************************************************/
4926void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1))
4927{
4928 int mod, rh, rl;
4929 uint destoffset = 0;
4930 u16 *destreg;
4931 u16 destval,destval2;
4932
4933 /* Yet another special case instruction. */
4934 START_OF_INSTR();
4935 FETCH_DECODE_MODRM(mod, rh, rl);
4936#ifdef DEBUG
4937 if (DEBUG_DECODE()) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004938 /* XXX DECODE_PRINTF may be changed to something more
4939 general, so that it is important to leave the strings
4940 in the same format, even though the result is that the
4941 above test is done twice. */
Jason Jinece92f82007-07-06 08:34:56 +08004942
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004943 switch (rh) {
4944 case 0:
4945 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4946 DECODE_PRINTF("INC\tDWORD PTR ");
4947 } else {
4948 DECODE_PRINTF("INC\tWORD PTR ");
4949 }
4950 break;
4951 case 1:
4952 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4953 DECODE_PRINTF("DEC\tDWORD PTR ");
4954 } else {
4955 DECODE_PRINTF("DEC\tWORD PTR ");
4956 }
4957 break;
4958 case 2:
4959 DECODE_PRINTF("CALL\t ");
4960 break;
4961 case 3:
4962 DECODE_PRINTF("CALL\tFAR ");
4963 break;
4964 case 4:
4965 DECODE_PRINTF("JMP\t");
4966 break;
4967 case 5:
4968 DECODE_PRINTF("JMP\tFAR ");
4969 break;
4970 case 6:
4971 DECODE_PRINTF("PUSH\t");
4972 break;
4973 case 7:
4974 DECODE_PRINTF("ILLEGAL DECODING OF OPCODE FF\t");
4975 HALT_SYS();
4976 break;
4977 }
Jason Jinece92f82007-07-06 08:34:56 +08004978 }
4979#endif
4980 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004981 destoffset = decode_rmXX_address(mod, rl);
4982 DECODE_PRINTF("\n");
4983 switch (rh) {
4984 case 0: /* inc word ptr ... */
4985 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4986 u32 destval;
Jason Jinece92f82007-07-06 08:34:56 +08004987
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004988 destval = fetch_data_long(destoffset);
4989 TRACE_AND_STEP();
4990 destval = inc_long(destval);
4991 store_data_long(destoffset, destval);
4992 } else {
4993 u16 destval;
Jason Jinece92f82007-07-06 08:34:56 +08004994
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02004995 destval = fetch_data_word(destoffset);
4996 TRACE_AND_STEP();
4997 destval = inc_word(destval);
4998 store_data_word(destoffset, destval);
4999 }
5000 break;
5001 case 1: /* dec word ptr ... */
5002 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5003 u32 destval;
Jason Jinece92f82007-07-06 08:34:56 +08005004
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02005005 destval = fetch_data_long(destoffset);
5006 TRACE_AND_STEP();
5007 destval = dec_long(destval);
5008 store_data_long(destoffset, destval);
5009 } else {
5010 u16 destval;
Jason Jinece92f82007-07-06 08:34:56 +08005011
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02005012 destval = fetch_data_word(destoffset);
5013 TRACE_AND_STEP();
5014 destval = dec_word(destval);
5015 store_data_word(destoffset, destval);
5016 }
5017 break;
5018 case 2: /* call word ptr ... */
5019 destval = fetch_data_word(destoffset);
5020 TRACE_AND_STEP();
5021 push_word(M.x86.R_IP);
5022 M.x86.R_IP = destval;
5023 break;
5024 case 3: /* call far ptr ... */
5025 destval = fetch_data_word(destoffset);
5026 destval2 = fetch_data_word(destoffset + 2);
5027 TRACE_AND_STEP();
5028 push_word(M.x86.R_CS);
5029 M.x86.R_CS = destval2;
5030 push_word(M.x86.R_IP);
5031 M.x86.R_IP = destval;
5032 break;
5033 case 4: /* jmp word ptr ... */
5034 destval = fetch_data_word(destoffset);
5035 TRACE_AND_STEP();
5036 M.x86.R_IP = destval;
5037 break;
5038 case 5: /* jmp far ptr ... */
5039 destval = fetch_data_word(destoffset);
5040 destval2 = fetch_data_word(destoffset + 2);
5041 TRACE_AND_STEP();
5042 M.x86.R_IP = destval;
5043 M.x86.R_CS = destval2;
5044 break;
5045 case 6: /* push word ptr ... */
5046 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5047 u32 destval;
Jason Jinece92f82007-07-06 08:34:56 +08005048
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02005049 destval = fetch_data_long(destoffset);
5050 TRACE_AND_STEP();
5051 push_long(destval);
5052 } else {
5053 u16 destval;
Jason Jinece92f82007-07-06 08:34:56 +08005054
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02005055 destval = fetch_data_word(destoffset);
5056 TRACE_AND_STEP();
5057 push_word(destval);
5058 }
5059 break;
5060 }
Jason Jinece92f82007-07-06 08:34:56 +08005061 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02005062 switch (rh) {
5063 case 0:
5064 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5065 u32 *destreg;
Jason Jinece92f82007-07-06 08:34:56 +08005066
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02005067 destreg = DECODE_RM_LONG_REGISTER(rl);
5068 DECODE_PRINTF("\n");
5069 TRACE_AND_STEP();
5070 *destreg = inc_long(*destreg);
5071 } else {
5072 u16 *destreg;
Jason Jinece92f82007-07-06 08:34:56 +08005073
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02005074 destreg = DECODE_RM_WORD_REGISTER(rl);
5075 DECODE_PRINTF("\n");
5076 TRACE_AND_STEP();
5077 *destreg = inc_word(*destreg);
5078 }
5079 break;
5080 case 1:
5081 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5082 u32 *destreg;
Jason Jinece92f82007-07-06 08:34:56 +08005083
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02005084 destreg = DECODE_RM_LONG_REGISTER(rl);
5085 DECODE_PRINTF("\n");
5086 TRACE_AND_STEP();
5087 *destreg = dec_long(*destreg);
5088 } else {
5089 u16 *destreg;
Jason Jinece92f82007-07-06 08:34:56 +08005090
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02005091 destreg = DECODE_RM_WORD_REGISTER(rl);
5092 DECODE_PRINTF("\n");
5093 TRACE_AND_STEP();
5094 *destreg = dec_word(*destreg);
5095 }
5096 break;
5097 case 2: /* call word ptr ... */
5098 destreg = DECODE_RM_WORD_REGISTER(rl);
5099 DECODE_PRINTF("\n");
5100 TRACE_AND_STEP();
5101 push_word(M.x86.R_IP);
5102 M.x86.R_IP = *destreg;
5103 break;
5104 case 3: /* jmp far ptr ... */
5105 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5106 TRACE_AND_STEP();
5107 HALT_SYS();
5108 break;
Jason Jinece92f82007-07-06 08:34:56 +08005109
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02005110 case 4: /* jmp ... */
5111 destreg = DECODE_RM_WORD_REGISTER(rl);
5112 DECODE_PRINTF("\n");
5113 TRACE_AND_STEP();
5114 M.x86.R_IP = (u16) (*destreg);
5115 break;
5116 case 5: /* jmp far ptr ... */
5117 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5118 TRACE_AND_STEP();
5119 HALT_SYS();
5120 break;
5121 case 6:
5122 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5123 u32 *destreg;
Jason Jinece92f82007-07-06 08:34:56 +08005124
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02005125 destreg = DECODE_RM_LONG_REGISTER(rl);
5126 DECODE_PRINTF("\n");
5127 TRACE_AND_STEP();
5128 push_long(*destreg);
5129 } else {
5130 u16 *destreg;
Jason Jinece92f82007-07-06 08:34:56 +08005131
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02005132 destreg = DECODE_RM_WORD_REGISTER(rl);
5133 DECODE_PRINTF("\n");
5134 TRACE_AND_STEP();
5135 push_word(*destreg);
5136 }
5137 break;
5138 }
Jason Jinece92f82007-07-06 08:34:56 +08005139 }
5140 DECODE_CLEAR_SEGOVR();
5141 END_OF_INSTR();
5142}
5143
5144/***************************************************************************
5145 * Single byte operation code table:
5146 **************************************************************************/
Anatolij Gustschin30c6a242008-02-15 20:09:01 +01005147void (*x86emu_optab[256])(u8) __attribute__ ((section(GOT2_TYPE))) =
Jason Jinece92f82007-07-06 08:34:56 +08005148{
5149/* 0x00 */ x86emuOp_genop_byte_RM_R,
5150/* 0x01 */ x86emuOp_genop_word_RM_R,
5151/* 0x02 */ x86emuOp_genop_byte_R_RM,
5152/* 0x03 */ x86emuOp_genop_word_R_RM,
5153/* 0x04 */ x86emuOp_genop_byte_AL_IMM,
5154/* 0x05 */ x86emuOp_genop_word_AX_IMM,
5155/* 0x06 */ x86emuOp_push_ES,
5156/* 0x07 */ x86emuOp_pop_ES,
5157
5158/* 0x08 */ x86emuOp_genop_byte_RM_R,
5159/* 0x09 */ x86emuOp_genop_word_RM_R,
5160/* 0x0a */ x86emuOp_genop_byte_R_RM,
5161/* 0x0b */ x86emuOp_genop_word_R_RM,
5162/* 0x0c */ x86emuOp_genop_byte_AL_IMM,
5163/* 0x0d */ x86emuOp_genop_word_AX_IMM,
5164/* 0x0e */ x86emuOp_push_CS,
5165/* 0x0f */ x86emuOp_two_byte,
5166
5167/* 0x10 */ x86emuOp_genop_byte_RM_R,
5168/* 0x11 */ x86emuOp_genop_word_RM_R,
5169/* 0x12 */ x86emuOp_genop_byte_R_RM,
5170/* 0x13 */ x86emuOp_genop_word_R_RM,
5171/* 0x14 */ x86emuOp_genop_byte_AL_IMM,
5172/* 0x15 */ x86emuOp_genop_word_AX_IMM,
5173/* 0x16 */ x86emuOp_push_SS,
5174/* 0x17 */ x86emuOp_pop_SS,
5175
5176/* 0x18 */ x86emuOp_genop_byte_RM_R,
5177/* 0x19 */ x86emuOp_genop_word_RM_R,
5178/* 0x1a */ x86emuOp_genop_byte_R_RM,
5179/* 0x1b */ x86emuOp_genop_word_R_RM,
5180/* 0x1c */ x86emuOp_genop_byte_AL_IMM,
5181/* 0x1d */ x86emuOp_genop_word_AX_IMM,
5182/* 0x1e */ x86emuOp_push_DS,
5183/* 0x1f */ x86emuOp_pop_DS,
5184
5185/* 0x20 */ x86emuOp_genop_byte_RM_R,
5186/* 0x21 */ x86emuOp_genop_word_RM_R,
5187/* 0x22 */ x86emuOp_genop_byte_R_RM,
5188/* 0x23 */ x86emuOp_genop_word_R_RM,
5189/* 0x24 */ x86emuOp_genop_byte_AL_IMM,
5190/* 0x25 */ x86emuOp_genop_word_AX_IMM,
5191/* 0x26 */ x86emuOp_segovr_ES,
5192/* 0x27 */ x86emuOp_daa,
5193
5194/* 0x28 */ x86emuOp_genop_byte_RM_R,
5195/* 0x29 */ x86emuOp_genop_word_RM_R,
5196/* 0x2a */ x86emuOp_genop_byte_R_RM,
5197/* 0x2b */ x86emuOp_genop_word_R_RM,
5198/* 0x2c */ x86emuOp_genop_byte_AL_IMM,
5199/* 0x2d */ x86emuOp_genop_word_AX_IMM,
5200/* 0x2e */ x86emuOp_segovr_CS,
5201/* 0x2f */ x86emuOp_das,
5202
5203/* 0x30 */ x86emuOp_genop_byte_RM_R,
5204/* 0x31 */ x86emuOp_genop_word_RM_R,
5205/* 0x32 */ x86emuOp_genop_byte_R_RM,
5206/* 0x33 */ x86emuOp_genop_word_R_RM,
5207/* 0x34 */ x86emuOp_genop_byte_AL_IMM,
5208/* 0x35 */ x86emuOp_genop_word_AX_IMM,
5209/* 0x36 */ x86emuOp_segovr_SS,
5210/* 0x37 */ x86emuOp_aaa,
5211
5212/* 0x38 */ x86emuOp_genop_byte_RM_R,
5213/* 0x39 */ x86emuOp_genop_word_RM_R,
5214/* 0x3a */ x86emuOp_genop_byte_R_RM,
5215/* 0x3b */ x86emuOp_genop_word_R_RM,
5216/* 0x3c */ x86emuOp_genop_byte_AL_IMM,
5217/* 0x3d */ x86emuOp_genop_word_AX_IMM,
5218/* 0x3e */ x86emuOp_segovr_DS,
5219/* 0x3f */ x86emuOp_aas,
5220
5221/* 0x40 */ x86emuOp_inc_register,
5222/* 0x41 */ x86emuOp_inc_register,
5223/* 0x42 */ x86emuOp_inc_register,
5224/* 0x43 */ x86emuOp_inc_register,
5225/* 0x44 */ x86emuOp_inc_register,
5226/* 0x45 */ x86emuOp_inc_register,
5227/* 0x46 */ x86emuOp_inc_register,
5228/* 0x47 */ x86emuOp_inc_register,
5229
5230/* 0x48 */ x86emuOp_dec_register,
5231/* 0x49 */ x86emuOp_dec_register,
5232/* 0x4a */ x86emuOp_dec_register,
5233/* 0x4b */ x86emuOp_dec_register,
5234/* 0x4c */ x86emuOp_dec_register,
5235/* 0x4d */ x86emuOp_dec_register,
5236/* 0x4e */ x86emuOp_dec_register,
5237/* 0x4f */ x86emuOp_dec_register,
5238
5239/* 0x50 */ x86emuOp_push_register,
5240/* 0x51 */ x86emuOp_push_register,
5241/* 0x52 */ x86emuOp_push_register,
5242/* 0x53 */ x86emuOp_push_register,
5243/* 0x54 */ x86emuOp_push_register,
5244/* 0x55 */ x86emuOp_push_register,
5245/* 0x56 */ x86emuOp_push_register,
5246/* 0x57 */ x86emuOp_push_register,
5247
5248/* 0x58 */ x86emuOp_pop_register,
5249/* 0x59 */ x86emuOp_pop_register,
5250/* 0x5a */ x86emuOp_pop_register,
5251/* 0x5b */ x86emuOp_pop_register,
5252/* 0x5c */ x86emuOp_pop_register,
5253/* 0x5d */ x86emuOp_pop_register,
5254/* 0x5e */ x86emuOp_pop_register,
5255/* 0x5f */ x86emuOp_pop_register,
5256
5257/* 0x60 */ x86emuOp_push_all,
5258/* 0x61 */ x86emuOp_pop_all,
5259/* 0x62 */ x86emuOp_illegal_op, /* bound */
5260/* 0x63 */ x86emuOp_illegal_op, /* arpl */
5261/* 0x64 */ x86emuOp_segovr_FS,
5262/* 0x65 */ x86emuOp_segovr_GS,
5263/* 0x66 */ x86emuOp_prefix_data,
5264/* 0x67 */ x86emuOp_prefix_addr,
5265
5266/* 0x68 */ x86emuOp_push_word_IMM,
5267/* 0x69 */ x86emuOp_imul_word_IMM,
5268/* 0x6a */ x86emuOp_push_byte_IMM,
5269/* 0x6b */ x86emuOp_imul_byte_IMM,
5270/* 0x6c */ x86emuOp_ins_byte,
5271/* 0x6d */ x86emuOp_ins_word,
5272/* 0x6e */ x86emuOp_outs_byte,
5273/* 0x6f */ x86emuOp_outs_word,
5274
5275/* 0x70 */ x86emuOp_jump_near_cond,
5276/* 0x71 */ x86emuOp_jump_near_cond,
5277/* 0x72 */ x86emuOp_jump_near_cond,
5278/* 0x73 */ x86emuOp_jump_near_cond,
5279/* 0x74 */ x86emuOp_jump_near_cond,
5280/* 0x75 */ x86emuOp_jump_near_cond,
5281/* 0x76 */ x86emuOp_jump_near_cond,
5282/* 0x77 */ x86emuOp_jump_near_cond,
5283
5284/* 0x78 */ x86emuOp_jump_near_cond,
5285/* 0x79 */ x86emuOp_jump_near_cond,
5286/* 0x7a */ x86emuOp_jump_near_cond,
5287/* 0x7b */ x86emuOp_jump_near_cond,
5288/* 0x7c */ x86emuOp_jump_near_cond,
5289/* 0x7d */ x86emuOp_jump_near_cond,
5290/* 0x7e */ x86emuOp_jump_near_cond,
5291/* 0x7f */ x86emuOp_jump_near_cond,
5292
5293/* 0x80 */ x86emuOp_opc80_byte_RM_IMM,
5294/* 0x81 */ x86emuOp_opc81_word_RM_IMM,
5295/* 0x82 */ x86emuOp_opc82_byte_RM_IMM,
5296/* 0x83 */ x86emuOp_opc83_word_RM_IMM,
5297/* 0x84 */ x86emuOp_test_byte_RM_R,
5298/* 0x85 */ x86emuOp_test_word_RM_R,
5299/* 0x86 */ x86emuOp_xchg_byte_RM_R,
5300/* 0x87 */ x86emuOp_xchg_word_RM_R,
5301
5302/* 0x88 */ x86emuOp_mov_byte_RM_R,
5303/* 0x89 */ x86emuOp_mov_word_RM_R,
5304/* 0x8a */ x86emuOp_mov_byte_R_RM,
5305/* 0x8b */ x86emuOp_mov_word_R_RM,
5306/* 0x8c */ x86emuOp_mov_word_RM_SR,
5307/* 0x8d */ x86emuOp_lea_word_R_M,
5308/* 0x8e */ x86emuOp_mov_word_SR_RM,
5309/* 0x8f */ x86emuOp_pop_RM,
5310
5311/* 0x90 */ x86emuOp_nop,
5312/* 0x91 */ x86emuOp_xchg_word_AX_register,
5313/* 0x92 */ x86emuOp_xchg_word_AX_register,
5314/* 0x93 */ x86emuOp_xchg_word_AX_register,
5315/* 0x94 */ x86emuOp_xchg_word_AX_register,
5316/* 0x95 */ x86emuOp_xchg_word_AX_register,
5317/* 0x96 */ x86emuOp_xchg_word_AX_register,
5318/* 0x97 */ x86emuOp_xchg_word_AX_register,
5319
5320/* 0x98 */ x86emuOp_cbw,
5321/* 0x99 */ x86emuOp_cwd,
5322/* 0x9a */ x86emuOp_call_far_IMM,
5323/* 0x9b */ x86emuOp_wait,
5324/* 0x9c */ x86emuOp_pushf_word,
5325/* 0x9d */ x86emuOp_popf_word,
5326/* 0x9e */ x86emuOp_sahf,
5327/* 0x9f */ x86emuOp_lahf,
5328
5329/* 0xa0 */ x86emuOp_mov_AL_M_IMM,
5330/* 0xa1 */ x86emuOp_mov_AX_M_IMM,
5331/* 0xa2 */ x86emuOp_mov_M_AL_IMM,
5332/* 0xa3 */ x86emuOp_mov_M_AX_IMM,
5333/* 0xa4 */ x86emuOp_movs_byte,
5334/* 0xa5 */ x86emuOp_movs_word,
5335/* 0xa6 */ x86emuOp_cmps_byte,
5336/* 0xa7 */ x86emuOp_cmps_word,
5337/* 0xa8 */ x86emuOp_test_AL_IMM,
5338/* 0xa9 */ x86emuOp_test_AX_IMM,
5339/* 0xaa */ x86emuOp_stos_byte,
5340/* 0xab */ x86emuOp_stos_word,
5341/* 0xac */ x86emuOp_lods_byte,
5342/* 0xad */ x86emuOp_lods_word,
5343/* 0xac */ x86emuOp_scas_byte,
5344/* 0xad */ x86emuOp_scas_word,
5345
5346/* 0xb0 */ x86emuOp_mov_byte_register_IMM,
5347/* 0xb1 */ x86emuOp_mov_byte_register_IMM,
5348/* 0xb2 */ x86emuOp_mov_byte_register_IMM,
5349/* 0xb3 */ x86emuOp_mov_byte_register_IMM,
5350/* 0xb4 */ x86emuOp_mov_byte_register_IMM,
5351/* 0xb5 */ x86emuOp_mov_byte_register_IMM,
5352/* 0xb6 */ x86emuOp_mov_byte_register_IMM,
5353/* 0xb7 */ x86emuOp_mov_byte_register_IMM,
5354
5355/* 0xb8 */ x86emuOp_mov_word_register_IMM,
5356/* 0xb9 */ x86emuOp_mov_word_register_IMM,
5357/* 0xba */ x86emuOp_mov_word_register_IMM,
5358/* 0xbb */ x86emuOp_mov_word_register_IMM,
5359/* 0xbc */ x86emuOp_mov_word_register_IMM,
5360/* 0xbd */ x86emuOp_mov_word_register_IMM,
5361/* 0xbe */ x86emuOp_mov_word_register_IMM,
5362/* 0xbf */ x86emuOp_mov_word_register_IMM,
5363
5364/* 0xc0 */ x86emuOp_opcC0_byte_RM_MEM,
5365/* 0xc1 */ x86emuOp_opcC1_word_RM_MEM,
5366/* 0xc2 */ x86emuOp_ret_near_IMM,
5367/* 0xc3 */ x86emuOp_ret_near,
5368/* 0xc4 */ x86emuOp_les_R_IMM,
5369/* 0xc5 */ x86emuOp_lds_R_IMM,
5370/* 0xc6 */ x86emuOp_mov_byte_RM_IMM,
5371/* 0xc7 */ x86emuOp_mov_word_RM_IMM,
5372/* 0xc8 */ x86emuOp_enter,
5373/* 0xc9 */ x86emuOp_leave,
5374/* 0xca */ x86emuOp_ret_far_IMM,
5375/* 0xcb */ x86emuOp_ret_far,
5376/* 0xcc */ x86emuOp_int3,
5377/* 0xcd */ x86emuOp_int_IMM,
5378/* 0xce */ x86emuOp_into,
5379/* 0xcf */ x86emuOp_iret,
5380
5381/* 0xd0 */ x86emuOp_opcD0_byte_RM_1,
5382/* 0xd1 */ x86emuOp_opcD1_word_RM_1,
5383/* 0xd2 */ x86emuOp_opcD2_byte_RM_CL,
5384/* 0xd3 */ x86emuOp_opcD3_word_RM_CL,
5385/* 0xd4 */ x86emuOp_aam,
5386/* 0xd5 */ x86emuOp_aad,
5387/* 0xd6 */ x86emuOp_illegal_op, /* Undocumented SETALC instruction */
5388/* 0xd7 */ x86emuOp_xlat,
5389/* 0xd8 */ NULL, /*x86emuOp_esc_coprocess_d8,*/
5390/* 0xd9 */ NULL, /*x86emuOp_esc_coprocess_d9,*/
5391/* 0xda */ NULL, /*x86emuOp_esc_coprocess_da,*/
5392/* 0xdb */ NULL, /*x86emuOp_esc_coprocess_db,*/
5393/* 0xdc */ NULL, /*x86emuOp_esc_coprocess_dc,*/
5394/* 0xdd */ NULL, /*x86emuOp_esc_coprocess_dd,*/
5395/* 0xde */ NULL, /*x86emuOp_esc_coprocess_de,*/
5396/* 0xdf */ NULL, /*x86emuOp_esc_coprocess_df,*/
5397
5398/* 0xe0 */ x86emuOp_loopne,
5399/* 0xe1 */ x86emuOp_loope,
5400/* 0xe2 */ x86emuOp_loop,
5401/* 0xe3 */ x86emuOp_jcxz,
5402/* 0xe4 */ x86emuOp_in_byte_AL_IMM,
5403/* 0xe5 */ x86emuOp_in_word_AX_IMM,
5404/* 0xe6 */ x86emuOp_out_byte_IMM_AL,
5405/* 0xe7 */ x86emuOp_out_word_IMM_AX,
5406
5407/* 0xe8 */ x86emuOp_call_near_IMM,
5408/* 0xe9 */ x86emuOp_jump_near_IMM,
5409/* 0xea */ x86emuOp_jump_far_IMM,
5410/* 0xeb */ x86emuOp_jump_byte_IMM,
5411/* 0xec */ x86emuOp_in_byte_AL_DX,
5412/* 0xed */ x86emuOp_in_word_AX_DX,
5413/* 0xee */ x86emuOp_out_byte_DX_AL,
5414/* 0xef */ x86emuOp_out_word_DX_AX,
5415
5416/* 0xf0 */ x86emuOp_lock,
5417/* 0xf1 */ x86emuOp_illegal_op,
5418/* 0xf2 */ x86emuOp_repne,
5419/* 0xf3 */ x86emuOp_repe,
5420/* 0xf4 */ x86emuOp_halt,
5421/* 0xf5 */ x86emuOp_cmc,
5422/* 0xf6 */ x86emuOp_opcF6_byte_RM,
5423/* 0xf7 */ x86emuOp_opcF7_word_RM,
5424
5425/* 0xf8 */ x86emuOp_clc,
5426/* 0xf9 */ x86emuOp_stc,
5427/* 0xfa */ x86emuOp_cli,
5428/* 0xfb */ x86emuOp_sti,
5429/* 0xfc */ x86emuOp_cld,
5430/* 0xfd */ x86emuOp_std,
5431/* 0xfe */ x86emuOp_opcFE_byte_RM,
5432/* 0xff */ x86emuOp_opcFF_word_RM,
5433};