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