blob: d1380ceec0099526d1552a5bc8a968a17f1ae79a [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"
79/*----------------------------- Implementation ----------------------------*/
80
81/* constant arrays to do several instructions in just one function */
82
83#ifdef DEBUG
84static char *x86emu_GenOpName[8] = {
85 "ADD", "OR", "ADC", "SBB", "AND", "SUB", "XOR", "CMP"};
86#endif
87
88/* used by several opcodes */
89static u8 (*genop_byte_operation[])(u8 d, u8 s) __attribute__ ((section(".got2"))) =
90{
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020091 add_byte, /* 00 */
92 or_byte, /* 01 */
93 adc_byte, /* 02 */
94 sbb_byte, /* 03 */
95 and_byte, /* 04 */
96 sub_byte, /* 05 */
97 xor_byte, /* 06 */
98 cmp_byte, /* 07 */
Jason Jina63ce952007-07-06 08:34:56 +080099};
100
101static u16 (*genop_word_operation[])(u16 d, u16 s) __attribute__ ((section(".got2"))) =
102{
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200103 add_word, /*00 */
104 or_word, /*01 */
105 adc_word, /*02 */
106 sbb_word, /*03 */
107 and_word, /*04 */
108 sub_word, /*05 */
109 xor_word, /*06 */
110 cmp_word, /*07 */
Jason Jina63ce952007-07-06 08:34:56 +0800111};
112
113static u32 (*genop_long_operation[])(u32 d, u32 s) __attribute__ ((section(".got2"))) =
114{
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200115 add_long, /*00 */
116 or_long, /*01 */
117 adc_long, /*02 */
118 sbb_long, /*03 */
119 and_long, /*04 */
120 sub_long, /*05 */
121 xor_long, /*06 */
122 cmp_long, /*07 */
Jason Jina63ce952007-07-06 08:34:56 +0800123};
124
125/* used by opcodes 80, c0, d0, and d2. */
126static u8(*opcD0_byte_operation[])(u8 d, u8 s) __attribute__ ((section(".got2"))) =
127{
128 rol_byte,
129 ror_byte,
130 rcl_byte,
131 rcr_byte,
132 shl_byte,
133 shr_byte,
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200134 shl_byte, /* sal_byte === shl_byte by definition */
Jason Jina63ce952007-07-06 08:34:56 +0800135 sar_byte,
136};
137
138/* used by opcodes c1, d1, and d3. */
139static u16(*opcD1_word_operation[])(u16 s, u8 d) __attribute__ ((section(".got2"))) =
140{
141 rol_word,
142 ror_word,
143 rcl_word,
144 rcr_word,
145 shl_word,
146 shr_word,
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200147 shl_word, /* sal_byte === shl_byte by definition */
Jason Jina63ce952007-07-06 08:34:56 +0800148 sar_word,
149};
150
151/* used by opcodes c1, d1, and d3. */
152static u32 (*opcD1_long_operation[])(u32 s, u8 d) __attribute__ ((section(".got2"))) =
153{
154 rol_long,
155 ror_long,
156 rcl_long,
157 rcr_long,
158 shl_long,
159 shr_long,
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200160 shl_long, /* sal_byte === shl_byte by definition */
Jason Jina63ce952007-07-06 08:34:56 +0800161 sar_long,
162};
163
164#ifdef DEBUG
165
166static char *opF6_names[8] =
167 { "TEST\t", "", "NOT\t", "NEG\t", "MUL\t", "IMUL\t", "DIV\t", "IDIV\t" };
168
169#endif
170
171/****************************************************************************
172PARAMETERS:
173op1 - Instruction op code
174
175REMARKS:
176Handles illegal opcodes.
177****************************************************************************/
178void x86emuOp_illegal_op(
179 u8 op1)
180{
181 START_OF_INSTR();
182 if (M.x86.R_SP != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200183 DECODE_PRINTF("ILLEGAL X86 OPCODE\n");
184 TRACE_REGS();
185 DB( printk("%04x:%04x: %02X ILLEGAL X86 OPCODE!\n",
186 M.x86.R_CS, M.x86.R_IP-1,op1));
187 HALT_SYS();
188 }
Jason Jina63ce952007-07-06 08:34:56 +0800189 else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200190 /* If we get here, it means the stack pointer is back to zero
191 * so we are just returning from an emulator service call
192 * so therte is no need to display an error message. We trap
193 * the emulator with an 0xF1 opcode to finish the service
194 * call.
195 */
196 X86EMU_halt_sys();
197 }
Jason Jina63ce952007-07-06 08:34:56 +0800198 END_OF_INSTR();
199}
200
201/****************************************************************************
202REMARKS:
203Handles opcodes 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38
204****************************************************************************/
205void x86emuOp_genop_byte_RM_R(u8 op1)
206{
207 int mod, rl, rh;
208 uint destoffset;
209 u8 *destreg, *srcreg;
210 u8 destval;
211
212 op1 = (op1 >> 3) & 0x7;
213
214 START_OF_INSTR();
215 DECODE_PRINTF(x86emu_GenOpName[op1]);
216 DECODE_PRINTF("\t");
217 FETCH_DECODE_MODRM(mod, rh, rl);
218 if(mod<3)
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200219 { destoffset = decode_rmXX_address(mod,rl);
220 DECODE_PRINTF(",");
221 destval = fetch_data_byte(destoffset);
222 srcreg = DECODE_RM_BYTE_REGISTER(rh);
223 DECODE_PRINTF("\n");
224 TRACE_AND_STEP();
225 destval = genop_byte_operation[op1](destval, *srcreg);
226 store_data_byte(destoffset, destval);
227 }
Jason Jina63ce952007-07-06 08:34:56 +0800228 else
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200229 { /* register to register */
230 destreg = DECODE_RM_BYTE_REGISTER(rl);
231 DECODE_PRINTF(",");
232 srcreg = DECODE_RM_BYTE_REGISTER(rh);
233 DECODE_PRINTF("\n");
234 TRACE_AND_STEP();
235 *destreg = genop_byte_operation[op1](*destreg, *srcreg);
236 }
Jason Jina63ce952007-07-06 08:34:56 +0800237 DECODE_CLEAR_SEGOVR();
238 END_OF_INSTR();
239}
240
241/****************************************************************************
242REMARKS:
243Handles opcodes 0x01, 0x09, 0x11, 0x19, 0x21, 0x29, 0x31, 0x39
244****************************************************************************/
245void x86emuOp_genop_word_RM_R(u8 op1)
246{
247 int mod, rl, rh;
248 uint destoffset;
249
250 op1 = (op1 >> 3) & 0x7;
251
252 START_OF_INSTR();
253 DECODE_PRINTF(x86emu_GenOpName[op1]);
254 DECODE_PRINTF("\t");
255 FETCH_DECODE_MODRM(mod, rh, rl);
256
257 if(mod<3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200258 destoffset = decode_rmXX_address(mod,rl);
259 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
260 u32 destval;
261 u32 *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +0800262
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200263 DECODE_PRINTF(",");
264 destval = fetch_data_long(destoffset);
265 srcreg = DECODE_RM_LONG_REGISTER(rh);
266 DECODE_PRINTF("\n");
267 TRACE_AND_STEP();
268 destval = genop_long_operation[op1](destval, *srcreg);
269 store_data_long(destoffset, destval);
270 } else {
271 u16 destval;
272 u16 *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +0800273
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200274 DECODE_PRINTF(",");
275 destval = fetch_data_word(destoffset);
276 srcreg = DECODE_RM_WORD_REGISTER(rh);
277 DECODE_PRINTF("\n");
278 TRACE_AND_STEP();
279 destval = genop_word_operation[op1](destval, *srcreg);
280 store_data_word(destoffset, destval);
281 }
282 } else { /* register to register */
283 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
284 u32 *destreg,*srcreg;
Jason Jina63ce952007-07-06 08:34:56 +0800285
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200286 destreg = DECODE_RM_LONG_REGISTER(rl);
287 DECODE_PRINTF(",");
288 srcreg = DECODE_RM_LONG_REGISTER(rh);
289 DECODE_PRINTF("\n");
290 TRACE_AND_STEP();
291 *destreg = genop_long_operation[op1](*destreg, *srcreg);
292 } else {
293 u16 *destreg,*srcreg;
Jason Jina63ce952007-07-06 08:34:56 +0800294
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200295 destreg = DECODE_RM_WORD_REGISTER(rl);
296 DECODE_PRINTF(",");
297 srcreg = DECODE_RM_WORD_REGISTER(rh);
298 DECODE_PRINTF("\n");
299 TRACE_AND_STEP();
300 *destreg = genop_word_operation[op1](*destreg, *srcreg);
301 }
Jason Jina63ce952007-07-06 08:34:56 +0800302 }
303 DECODE_CLEAR_SEGOVR();
304 END_OF_INSTR();
305}
306
307/****************************************************************************
308REMARKS:
309Handles opcodes 0x02, 0x0a, 0x12, 0x1a, 0x22, 0x2a, 0x32, 0x3a
310****************************************************************************/
311void x86emuOp_genop_byte_R_RM(u8 op1)
312{
313 int mod, rl, rh;
314 u8 *destreg, *srcreg;
315 uint srcoffset;
316 u8 srcval;
317
318 op1 = (op1 >> 3) & 0x7;
319
320 START_OF_INSTR();
321 DECODE_PRINTF(x86emu_GenOpName[op1]);
322 DECODE_PRINTF("\t");
323 FETCH_DECODE_MODRM(mod, rh, rl);
324 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200325 destreg = DECODE_RM_BYTE_REGISTER(rh);
326 DECODE_PRINTF(",");
327 srcoffset = decode_rmXX_address(mod,rl);
328 srcval = fetch_data_byte(srcoffset);
329 } else { /* register to register */
330 destreg = DECODE_RM_BYTE_REGISTER(rh);
331 DECODE_PRINTF(",");
332 srcreg = DECODE_RM_BYTE_REGISTER(rl);
333 srcval = *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +0800334 }
335 DECODE_PRINTF("\n");
336 TRACE_AND_STEP();
337 *destreg = genop_byte_operation[op1](*destreg, srcval);
338
339 DECODE_CLEAR_SEGOVR();
340 END_OF_INSTR();
341}
342
343/****************************************************************************
344REMARKS:
345Handles opcodes 0x03, 0x0b, 0x13, 0x1b, 0x23, 0x2b, 0x33, 0x3b
346****************************************************************************/
347void x86emuOp_genop_word_R_RM(u8 op1)
348{
349 int mod, rl, rh;
350 uint srcoffset;
351 u32 *destreg32, srcval;
352 u16 *destreg;
353
354 op1 = (op1 >> 3) & 0x7;
355
356 START_OF_INSTR();
357 DECODE_PRINTF(x86emu_GenOpName[op1]);
358 DECODE_PRINTF("\t");
359 FETCH_DECODE_MODRM(mod, rh, rl);
360 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200361 srcoffset = decode_rmXX_address(mod,rl);
362 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
363 destreg32 = DECODE_RM_LONG_REGISTER(rh);
364 DECODE_PRINTF(",");
365 srcval = fetch_data_long(srcoffset);
366 DECODE_PRINTF("\n");
367 TRACE_AND_STEP();
368 *destreg32 = genop_long_operation[op1](*destreg32, srcval);
369 } else {
370 destreg = DECODE_RM_WORD_REGISTER(rh);
371 DECODE_PRINTF(",");
372 srcval = fetch_data_word(srcoffset);
373 DECODE_PRINTF("\n");
374 TRACE_AND_STEP();
375 *destreg = genop_word_operation[op1](*destreg, srcval);
376 }
377 } else { /* register to register */
378 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
379 u32 *srcreg;
380 destreg32 = DECODE_RM_LONG_REGISTER(rh);
381 DECODE_PRINTF(",");
382 srcreg = DECODE_RM_LONG_REGISTER(rl);
383 DECODE_PRINTF("\n");
384 TRACE_AND_STEP();
385 *destreg32 = genop_long_operation[op1](*destreg32, *srcreg);
386 } else {
387 u16 *srcreg;
388 destreg = DECODE_RM_WORD_REGISTER(rh);
389 DECODE_PRINTF(",");
390 srcreg = DECODE_RM_WORD_REGISTER(rl);
391 DECODE_PRINTF("\n");
392 TRACE_AND_STEP();
393 *destreg = genop_word_operation[op1](*destreg, *srcreg);
394 }
Jason Jina63ce952007-07-06 08:34:56 +0800395 }
396 DECODE_CLEAR_SEGOVR();
397 END_OF_INSTR();
398}
399
400/****************************************************************************
401REMARKS:
402Handles opcodes 0x04, 0x0c, 0x14, 0x1c, 0x24, 0x2c, 0x34, 0x3c
403****************************************************************************/
404void x86emuOp_genop_byte_AL_IMM(u8 op1)
405{
406 u8 srcval;
407
408 op1 = (op1 >> 3) & 0x7;
409
410 START_OF_INSTR();
411 DECODE_PRINTF(x86emu_GenOpName[op1]);
412 DECODE_PRINTF("\tAL,");
413 srcval = fetch_byte_imm();
414 DECODE_PRINTF2("%x\n", srcval);
415 TRACE_AND_STEP();
416 M.x86.R_AL = genop_byte_operation[op1](M.x86.R_AL, srcval);
417 DECODE_CLEAR_SEGOVR();
418 END_OF_INSTR();
419}
420
421/****************************************************************************
422REMARKS:
423Handles opcodes 0x05, 0x0d, 0x15, 0x1d, 0x25, 0x2d, 0x35, 0x3d
424****************************************************************************/
425void x86emuOp_genop_word_AX_IMM(u8 op1)
426{
427 u32 srcval;
428
429 op1 = (op1 >> 3) & 0x7;
430
431 START_OF_INSTR();
432 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200433 DECODE_PRINTF(x86emu_GenOpName[op1]);
434 DECODE_PRINTF("\tEAX,");
435 srcval = fetch_long_imm();
Jason Jina63ce952007-07-06 08:34:56 +0800436 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200437 DECODE_PRINTF(x86emu_GenOpName[op1]);
438 DECODE_PRINTF("\tAX,");
439 srcval = fetch_word_imm();
Jason Jina63ce952007-07-06 08:34:56 +0800440 }
441 DECODE_PRINTF2("%x\n", srcval);
442 TRACE_AND_STEP();
443 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200444 M.x86.R_EAX = genop_long_operation[op1](M.x86.R_EAX, srcval);
Jason Jina63ce952007-07-06 08:34:56 +0800445 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200446 M.x86.R_AX = genop_word_operation[op1](M.x86.R_AX, (u16)srcval);
Jason Jina63ce952007-07-06 08:34:56 +0800447 }
448 DECODE_CLEAR_SEGOVR();
449 END_OF_INSTR();
450}
451
452/****************************************************************************
453REMARKS:
454Handles opcode 0x06
455****************************************************************************/
456void x86emuOp_push_ES(u8 X86EMU_UNUSED(op1))
457{
458 START_OF_INSTR();
459 DECODE_PRINTF("PUSH\tES\n");
460 TRACE_AND_STEP();
461 push_word(M.x86.R_ES);
462 DECODE_CLEAR_SEGOVR();
463 END_OF_INSTR();
464}
465
466/****************************************************************************
467REMARKS:
468Handles opcode 0x07
469****************************************************************************/
470void x86emuOp_pop_ES(u8 X86EMU_UNUSED(op1))
471{
472 START_OF_INSTR();
473 DECODE_PRINTF("POP\tES\n");
474 TRACE_AND_STEP();
475 M.x86.R_ES = pop_word();
476 DECODE_CLEAR_SEGOVR();
477 END_OF_INSTR();
478}
479
480/****************************************************************************
481REMARKS:
482Handles opcode 0x0e
483****************************************************************************/
484void x86emuOp_push_CS(u8 X86EMU_UNUSED(op1))
485{
486 START_OF_INSTR();
487 DECODE_PRINTF("PUSH\tCS\n");
488 TRACE_AND_STEP();
489 push_word(M.x86.R_CS);
490 DECODE_CLEAR_SEGOVR();
491 END_OF_INSTR();
492}
493
494/****************************************************************************
495REMARKS:
496Handles opcode 0x0f. Escape for two-byte opcode (286 or better)
497****************************************************************************/
498void x86emuOp_two_byte(u8 X86EMU_UNUSED(op1))
499{
500 u8 op2 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
501 INC_DECODED_INST_LEN(1);
502 (*x86emu_optab2[op2])(op2);
503}
504
505/****************************************************************************
506REMARKS:
507Handles opcode 0x16
508****************************************************************************/
509void x86emuOp_push_SS(u8 X86EMU_UNUSED(op1))
510{
511 START_OF_INSTR();
512 DECODE_PRINTF("PUSH\tSS\n");
513 TRACE_AND_STEP();
514 push_word(M.x86.R_SS);
515 DECODE_CLEAR_SEGOVR();
516 END_OF_INSTR();
517}
518
519/****************************************************************************
520REMARKS:
521Handles opcode 0x17
522****************************************************************************/
523void x86emuOp_pop_SS(u8 X86EMU_UNUSED(op1))
524{
525 START_OF_INSTR();
526 DECODE_PRINTF("POP\tSS\n");
527 TRACE_AND_STEP();
528 M.x86.R_SS = pop_word();
529 DECODE_CLEAR_SEGOVR();
530 END_OF_INSTR();
531}
532
533/****************************************************************************
534REMARKS:
535Handles opcode 0x1e
536****************************************************************************/
537void x86emuOp_push_DS(u8 X86EMU_UNUSED(op1))
538{
539 START_OF_INSTR();
540 DECODE_PRINTF("PUSH\tDS\n");
541 TRACE_AND_STEP();
542 push_word(M.x86.R_DS);
543 DECODE_CLEAR_SEGOVR();
544 END_OF_INSTR();
545}
546
547/****************************************************************************
548REMARKS:
549Handles opcode 0x1f
550****************************************************************************/
551void x86emuOp_pop_DS(u8 X86EMU_UNUSED(op1))
552{
553 START_OF_INSTR();
554 DECODE_PRINTF("POP\tDS\n");
555 TRACE_AND_STEP();
556 M.x86.R_DS = pop_word();
557 DECODE_CLEAR_SEGOVR();
558 END_OF_INSTR();
559}
560
561/****************************************************************************
562REMARKS:
563Handles opcode 0x26
564****************************************************************************/
565void x86emuOp_segovr_ES(u8 X86EMU_UNUSED(op1))
566{
567 START_OF_INSTR();
568 DECODE_PRINTF("ES:\n");
569 TRACE_AND_STEP();
570 M.x86.mode |= SYSMODE_SEGOVR_ES;
571 /*
572 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
573 * opcode subroutines we do not want to do this.
574 */
575 END_OF_INSTR();
576}
577
578/****************************************************************************
579REMARKS:
580Handles opcode 0x27
581****************************************************************************/
582void x86emuOp_daa(u8 X86EMU_UNUSED(op1))
583{
584 START_OF_INSTR();
585 DECODE_PRINTF("DAA\n");
586 TRACE_AND_STEP();
587 M.x86.R_AL = daa_byte(M.x86.R_AL);
588 DECODE_CLEAR_SEGOVR();
589 END_OF_INSTR();
590}
591
592/****************************************************************************
593REMARKS:
594Handles opcode 0x2e
595****************************************************************************/
596void x86emuOp_segovr_CS(u8 X86EMU_UNUSED(op1))
597{
598 START_OF_INSTR();
599 DECODE_PRINTF("CS:\n");
600 TRACE_AND_STEP();
601 M.x86.mode |= SYSMODE_SEGOVR_CS;
602 /* note no DECODE_CLEAR_SEGOVR here. */
603 END_OF_INSTR();
604}
605
606/****************************************************************************
607REMARKS:
608Handles opcode 0x2f
609****************************************************************************/
610void x86emuOp_das(u8 X86EMU_UNUSED(op1))
611{
612 START_OF_INSTR();
613 DECODE_PRINTF("DAS\n");
614 TRACE_AND_STEP();
615 M.x86.R_AL = das_byte(M.x86.R_AL);
616 DECODE_CLEAR_SEGOVR();
617 END_OF_INSTR();
618}
619
620/****************************************************************************
621REMARKS:
622Handles opcode 0x36
623****************************************************************************/
624void x86emuOp_segovr_SS(u8 X86EMU_UNUSED(op1))
625{
626 START_OF_INSTR();
627 DECODE_PRINTF("SS:\n");
628 TRACE_AND_STEP();
629 M.x86.mode |= SYSMODE_SEGOVR_SS;
630 /* no DECODE_CLEAR_SEGOVR ! */
631 END_OF_INSTR();
632}
633
634/****************************************************************************
635REMARKS:
636Handles opcode 0x37
637****************************************************************************/
638void x86emuOp_aaa(u8 X86EMU_UNUSED(op1))
639{
640 START_OF_INSTR();
641 DECODE_PRINTF("AAA\n");
642 TRACE_AND_STEP();
643 M.x86.R_AX = aaa_word(M.x86.R_AX);
644 DECODE_CLEAR_SEGOVR();
645 END_OF_INSTR();
646}
647
648/****************************************************************************
649REMARKS:
650Handles opcode 0x3e
651****************************************************************************/
652void x86emuOp_segovr_DS(u8 X86EMU_UNUSED(op1))
653{
654 START_OF_INSTR();
655 DECODE_PRINTF("DS:\n");
656 TRACE_AND_STEP();
657 M.x86.mode |= SYSMODE_SEGOVR_DS;
658 /* NO DECODE_CLEAR_SEGOVR! */
659 END_OF_INSTR();
660}
661
662/****************************************************************************
663REMARKS:
664Handles opcode 0x3f
665****************************************************************************/
666void x86emuOp_aas(u8 X86EMU_UNUSED(op1))
667{
668 START_OF_INSTR();
669 DECODE_PRINTF("AAS\n");
670 TRACE_AND_STEP();
671 M.x86.R_AX = aas_word(M.x86.R_AX);
672 DECODE_CLEAR_SEGOVR();
673 END_OF_INSTR();
674}
675
676/****************************************************************************
677REMARKS:
678Handles opcode 0x40 - 0x47
679****************************************************************************/
680void x86emuOp_inc_register(u8 op1)
681{
682 START_OF_INSTR();
683 op1 &= 0x7;
684 DECODE_PRINTF("INC\t");
685 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200686 u32 *reg;
687 reg = DECODE_RM_LONG_REGISTER(op1);
688 DECODE_PRINTF("\n");
689 TRACE_AND_STEP();
690 *reg = inc_long(*reg);
Jason Jina63ce952007-07-06 08:34:56 +0800691 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200692 u16 *reg;
693 reg = DECODE_RM_WORD_REGISTER(op1);
694 DECODE_PRINTF("\n");
695 TRACE_AND_STEP();
696 *reg = inc_word(*reg);
Jason Jina63ce952007-07-06 08:34:56 +0800697 }
698 DECODE_CLEAR_SEGOVR();
699 END_OF_INSTR();
700}
701
702/****************************************************************************
703REMARKS:
704Handles opcode 0x48 - 0x4F
705****************************************************************************/
706void x86emuOp_dec_register(u8 op1)
707{
708 START_OF_INSTR();
709 op1 &= 0x7;
710 DECODE_PRINTF("DEC\t");
711 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200712 u32 *reg;
713 reg = DECODE_RM_LONG_REGISTER(op1);
714 DECODE_PRINTF("\n");
715 TRACE_AND_STEP();
716 *reg = dec_long(*reg);
Jason Jina63ce952007-07-06 08:34:56 +0800717 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200718 u16 *reg;
719 reg = DECODE_RM_WORD_REGISTER(op1);
720 DECODE_PRINTF("\n");
721 TRACE_AND_STEP();
722 *reg = dec_word(*reg);
Jason Jina63ce952007-07-06 08:34:56 +0800723 }
724 DECODE_CLEAR_SEGOVR();
725 END_OF_INSTR();
726}
727
728/****************************************************************************
729REMARKS:
730Handles opcode 0x50 - 0x57
731****************************************************************************/
732void x86emuOp_push_register(u8 op1)
733{
734 START_OF_INSTR();
735 op1 &= 0x7;
736 DECODE_PRINTF("PUSH\t");
737 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200738 u32 *reg;
739 reg = DECODE_RM_LONG_REGISTER(op1);
740 DECODE_PRINTF("\n");
741 TRACE_AND_STEP();
742 push_long(*reg);
Jason Jina63ce952007-07-06 08:34:56 +0800743 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200744 u16 *reg;
745 reg = DECODE_RM_WORD_REGISTER(op1);
746 DECODE_PRINTF("\n");
747 TRACE_AND_STEP();
748 push_word(*reg);
Jason Jina63ce952007-07-06 08:34:56 +0800749 }
750 DECODE_CLEAR_SEGOVR();
751 END_OF_INSTR();
752}
753
754/****************************************************************************
755REMARKS:
756Handles opcode 0x58 - 0x5F
757****************************************************************************/
758void x86emuOp_pop_register(u8 op1)
759{
760 START_OF_INSTR();
761 op1 &= 0x7;
762 DECODE_PRINTF("POP\t");
763 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200764 u32 *reg;
765 reg = DECODE_RM_LONG_REGISTER(op1);
766 DECODE_PRINTF("\n");
767 TRACE_AND_STEP();
768 *reg = pop_long();
Jason Jina63ce952007-07-06 08:34:56 +0800769 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200770 u16 *reg;
771 reg = DECODE_RM_WORD_REGISTER(op1);
772 DECODE_PRINTF("\n");
773 TRACE_AND_STEP();
774 *reg = pop_word();
Jason Jina63ce952007-07-06 08:34:56 +0800775 }
776 DECODE_CLEAR_SEGOVR();
777 END_OF_INSTR();
778}
779
780/****************************************************************************
781REMARKS:
782Handles opcode 0x60
783****************************************************************************/
784void x86emuOp_push_all(u8 X86EMU_UNUSED(op1))
785{
786 START_OF_INSTR();
787 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200788 DECODE_PRINTF("PUSHAD\n");
Jason Jina63ce952007-07-06 08:34:56 +0800789 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200790 DECODE_PRINTF("PUSHA\n");
Jason Jina63ce952007-07-06 08:34:56 +0800791 }
792 TRACE_AND_STEP();
793 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200794 u32 old_sp = M.x86.R_ESP;
Jason Jina63ce952007-07-06 08:34:56 +0800795
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200796 push_long(M.x86.R_EAX);
797 push_long(M.x86.R_ECX);
798 push_long(M.x86.R_EDX);
799 push_long(M.x86.R_EBX);
800 push_long(old_sp);
801 push_long(M.x86.R_EBP);
802 push_long(M.x86.R_ESI);
803 push_long(M.x86.R_EDI);
Jason Jina63ce952007-07-06 08:34:56 +0800804 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200805 u16 old_sp = M.x86.R_SP;
Jason Jina63ce952007-07-06 08:34:56 +0800806
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200807 push_word(M.x86.R_AX);
808 push_word(M.x86.R_CX);
809 push_word(M.x86.R_DX);
810 push_word(M.x86.R_BX);
811 push_word(old_sp);
812 push_word(M.x86.R_BP);
813 push_word(M.x86.R_SI);
814 push_word(M.x86.R_DI);
Jason Jina63ce952007-07-06 08:34:56 +0800815 }
816 DECODE_CLEAR_SEGOVR();
817 END_OF_INSTR();
818}
819
820/****************************************************************************
821REMARKS:
822Handles opcode 0x61
823****************************************************************************/
824void x86emuOp_pop_all(u8 X86EMU_UNUSED(op1))
825{
826 START_OF_INSTR();
827 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200828 DECODE_PRINTF("POPAD\n");
Jason Jina63ce952007-07-06 08:34:56 +0800829 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200830 DECODE_PRINTF("POPA\n");
Jason Jina63ce952007-07-06 08:34:56 +0800831 }
832 TRACE_AND_STEP();
833 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200834 M.x86.R_EDI = pop_long();
835 M.x86.R_ESI = pop_long();
836 M.x86.R_EBP = pop_long();
837 M.x86.R_ESP += 4; /* skip ESP */
838 M.x86.R_EBX = pop_long();
839 M.x86.R_EDX = pop_long();
840 M.x86.R_ECX = pop_long();
841 M.x86.R_EAX = pop_long();
Jason Jina63ce952007-07-06 08:34:56 +0800842 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200843 M.x86.R_DI = pop_word();
844 M.x86.R_SI = pop_word();
845 M.x86.R_BP = pop_word();
846 M.x86.R_SP += 2; /* skip SP */
847 M.x86.R_BX = pop_word();
848 M.x86.R_DX = pop_word();
849 M.x86.R_CX = pop_word();
850 M.x86.R_AX = pop_word();
Jason Jina63ce952007-07-06 08:34:56 +0800851 }
852 DECODE_CLEAR_SEGOVR();
853 END_OF_INSTR();
854}
855
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200856/*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */
857/*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */
Jason Jina63ce952007-07-06 08:34:56 +0800858
859/****************************************************************************
860REMARKS:
861Handles opcode 0x64
862****************************************************************************/
863void x86emuOp_segovr_FS(u8 X86EMU_UNUSED(op1))
864{
865 START_OF_INSTR();
866 DECODE_PRINTF("FS:\n");
867 TRACE_AND_STEP();
868 M.x86.mode |= SYSMODE_SEGOVR_FS;
869 /*
870 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
871 * opcode subroutines we do not want to do this.
872 */
873 END_OF_INSTR();
874}
875
876/****************************************************************************
877REMARKS:
878Handles opcode 0x65
879****************************************************************************/
880void x86emuOp_segovr_GS(u8 X86EMU_UNUSED(op1))
881{
882 START_OF_INSTR();
883 DECODE_PRINTF("GS:\n");
884 TRACE_AND_STEP();
885 M.x86.mode |= SYSMODE_SEGOVR_GS;
886 /*
887 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
888 * opcode subroutines we do not want to do this.
889 */
890 END_OF_INSTR();
891}
892
893/****************************************************************************
894REMARKS:
895Handles opcode 0x66 - prefix for 32-bit register
896****************************************************************************/
897void x86emuOp_prefix_data(u8 X86EMU_UNUSED(op1))
898{
899 START_OF_INSTR();
900 DECODE_PRINTF("DATA:\n");
901 TRACE_AND_STEP();
902 M.x86.mode |= SYSMODE_PREFIX_DATA;
903 /* note no DECODE_CLEAR_SEGOVR here. */
904 END_OF_INSTR();
905}
906
907/****************************************************************************
908REMARKS:
909Handles opcode 0x67 - prefix for 32-bit address
910****************************************************************************/
911void x86emuOp_prefix_addr(u8 X86EMU_UNUSED(op1))
912{
913 START_OF_INSTR();
914 DECODE_PRINTF("ADDR:\n");
915 TRACE_AND_STEP();
916 M.x86.mode |= SYSMODE_PREFIX_ADDR;
917 /* note no DECODE_CLEAR_SEGOVR here. */
918 END_OF_INSTR();
919}
920
921/****************************************************************************
922REMARKS:
923Handles opcode 0x68
924****************************************************************************/
925void x86emuOp_push_word_IMM(u8 X86EMU_UNUSED(op1))
926{
927 u32 imm;
928
929 START_OF_INSTR();
930 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200931 imm = fetch_long_imm();
Jason Jina63ce952007-07-06 08:34:56 +0800932 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200933 imm = fetch_word_imm();
Jason Jina63ce952007-07-06 08:34:56 +0800934 }
935 DECODE_PRINTF2("PUSH\t%x\n", imm);
936 TRACE_AND_STEP();
937 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200938 push_long(imm);
Jason Jina63ce952007-07-06 08:34:56 +0800939 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200940 push_word((u16)imm);
Jason Jina63ce952007-07-06 08:34:56 +0800941 }
942 DECODE_CLEAR_SEGOVR();
943 END_OF_INSTR();
944}
945
946/****************************************************************************
947REMARKS:
948Handles opcode 0x69
949****************************************************************************/
950void x86emuOp_imul_word_IMM(u8 X86EMU_UNUSED(op1))
951{
952 int mod, rl, rh;
953 uint srcoffset;
954
955 START_OF_INSTR();
956 DECODE_PRINTF("IMUL\t");
957 FETCH_DECODE_MODRM(mod, rh, rl);
958 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200959 srcoffset = decode_rmXX_address(mod, rl);
960 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
961 u32 *destreg;
962 u32 srcval;
963 u32 res_lo,res_hi;
964 s32 imm;
Jason Jina63ce952007-07-06 08:34:56 +0800965
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200966 destreg = DECODE_RM_LONG_REGISTER(rh);
967 DECODE_PRINTF(",");
968 srcval = fetch_data_long(srcoffset);
969 imm = fetch_long_imm();
970 DECODE_PRINTF2(",%d\n", (s32)imm);
971 TRACE_AND_STEP();
972 imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
973 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
974 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
975 CLEAR_FLAG(F_CF);
976 CLEAR_FLAG(F_OF);
977 } else {
978 SET_FLAG(F_CF);
979 SET_FLAG(F_OF);
980 }
981 *destreg = (u32)res_lo;
982 } else {
983 u16 *destreg;
984 u16 srcval;
985 u32 res;
986 s16 imm;
Jason Jina63ce952007-07-06 08:34:56 +0800987
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200988 destreg = DECODE_RM_WORD_REGISTER(rh);
989 DECODE_PRINTF(",");
990 srcval = fetch_data_word(srcoffset);
991 imm = fetch_word_imm();
992 DECODE_PRINTF2(",%d\n", (s32)imm);
993 TRACE_AND_STEP();
994 res = (s16)srcval * (s16)imm;
995 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
996 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
997 CLEAR_FLAG(F_CF);
998 CLEAR_FLAG(F_OF);
999 } else {
1000 SET_FLAG(F_CF);
1001 SET_FLAG(F_OF);
1002 }
1003 *destreg = (u16)res;
1004 }
1005 } else { /* register to register */
1006 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1007 u32 *destreg,*srcreg;
1008 u32 res_lo,res_hi;
1009 s32 imm;
Jason Jina63ce952007-07-06 08:34:56 +08001010
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001011 destreg = DECODE_RM_LONG_REGISTER(rh);
1012 DECODE_PRINTF(",");
1013 srcreg = DECODE_RM_LONG_REGISTER(rl);
1014 imm = fetch_long_imm();
1015 DECODE_PRINTF2(",%d\n", (s32)imm);
1016 TRACE_AND_STEP();
1017 imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
1018 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1019 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1020 CLEAR_FLAG(F_CF);
1021 CLEAR_FLAG(F_OF);
1022 } else {
1023 SET_FLAG(F_CF);
1024 SET_FLAG(F_OF);
1025 }
1026 *destreg = (u32)res_lo;
1027 } else {
1028 u16 *destreg,*srcreg;
1029 u32 res;
1030 s16 imm;
Jason Jina63ce952007-07-06 08:34:56 +08001031
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001032 destreg = DECODE_RM_WORD_REGISTER(rh);
1033 DECODE_PRINTF(",");
1034 srcreg = DECODE_RM_WORD_REGISTER(rl);
1035 imm = fetch_word_imm();
1036 DECODE_PRINTF2(",%d\n", (s32)imm);
1037 res = (s16)*srcreg * (s16)imm;
1038 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1039 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1040 CLEAR_FLAG(F_CF);
1041 CLEAR_FLAG(F_OF);
1042 } else {
1043 SET_FLAG(F_CF);
1044 SET_FLAG(F_OF);
1045 }
1046 *destreg = (u16)res;
1047 }
Jason Jina63ce952007-07-06 08:34:56 +08001048 }
1049 DECODE_CLEAR_SEGOVR();
1050 END_OF_INSTR();
1051}
1052
1053/****************************************************************************
1054REMARKS:
1055Handles opcode 0x6a
1056****************************************************************************/
1057void x86emuOp_push_byte_IMM(u8 X86EMU_UNUSED(op1))
1058{
1059 s16 imm;
1060
1061 START_OF_INSTR();
1062 imm = (s8)fetch_byte_imm();
1063 DECODE_PRINTF2("PUSH\t%d\n", imm);
1064 TRACE_AND_STEP();
1065 push_word(imm);
1066 DECODE_CLEAR_SEGOVR();
1067 END_OF_INSTR();
1068}
1069
1070/****************************************************************************
1071REMARKS:
1072Handles opcode 0x6b
1073****************************************************************************/
1074void x86emuOp_imul_byte_IMM(u8 X86EMU_UNUSED(op1))
1075{
1076 int mod, rl, rh;
1077 uint srcoffset;
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001078 s8 imm;
Jason Jina63ce952007-07-06 08:34:56 +08001079
1080 START_OF_INSTR();
1081 DECODE_PRINTF("IMUL\t");
1082 FETCH_DECODE_MODRM(mod, rh, rl);
1083 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001084 srcoffset = decode_rmXX_address(mod, rl);
1085 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1086 u32 *destreg;
1087 u32 srcval;
1088 u32 res_lo,res_hi;
Jason Jina63ce952007-07-06 08:34:56 +08001089
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001090 destreg = DECODE_RM_LONG_REGISTER(rh);
1091 DECODE_PRINTF(",");
1092 srcval = fetch_data_long(srcoffset);
1093 imm = fetch_byte_imm();
1094 DECODE_PRINTF2(",%d\n", (s32)imm);
1095 TRACE_AND_STEP();
1096 imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
1097 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1098 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1099 CLEAR_FLAG(F_CF);
1100 CLEAR_FLAG(F_OF);
1101 } else {
1102 SET_FLAG(F_CF);
1103 SET_FLAG(F_OF);
1104 }
1105 *destreg = (u32)res_lo;
1106 } else {
1107 u16 *destreg;
1108 u16 srcval;
1109 u32 res;
Jason Jina63ce952007-07-06 08:34:56 +08001110
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001111 destreg = DECODE_RM_WORD_REGISTER(rh);
1112 DECODE_PRINTF(",");
1113 srcval = fetch_data_word(srcoffset);
1114 imm = fetch_byte_imm();
1115 DECODE_PRINTF2(",%d\n", (s32)imm);
1116 TRACE_AND_STEP();
1117 res = (s16)srcval * (s16)imm;
1118 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1119 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1120 CLEAR_FLAG(F_CF);
1121 CLEAR_FLAG(F_OF);
1122 } else {
1123 SET_FLAG(F_CF);
1124 SET_FLAG(F_OF);
1125 }
1126 *destreg = (u16)res;
1127 }
1128 } else { /* register to register */
1129 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1130 u32 *destreg,*srcreg;
1131 u32 res_lo,res_hi;
Jason Jina63ce952007-07-06 08:34:56 +08001132
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001133 destreg = DECODE_RM_LONG_REGISTER(rh);
1134 DECODE_PRINTF(",");
1135 srcreg = DECODE_RM_LONG_REGISTER(rl);
1136 imm = fetch_byte_imm();
1137 DECODE_PRINTF2(",%d\n", (s32)imm);
1138 TRACE_AND_STEP();
1139 imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
1140 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1141 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1142 CLEAR_FLAG(F_CF);
1143 CLEAR_FLAG(F_OF);
1144 } else {
1145 SET_FLAG(F_CF);
1146 SET_FLAG(F_OF);
1147 }
1148 *destreg = (u32)res_lo;
1149 } else {
1150 u16 *destreg,*srcreg;
1151 u32 res;
Jason Jina63ce952007-07-06 08:34:56 +08001152
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001153 destreg = DECODE_RM_WORD_REGISTER(rh);
1154 DECODE_PRINTF(",");
1155 srcreg = DECODE_RM_WORD_REGISTER(rl);
1156 imm = fetch_byte_imm();
1157 DECODE_PRINTF2(",%d\n", (s32)imm);
1158 TRACE_AND_STEP();
1159 res = (s16)*srcreg * (s16)imm;
1160 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1161 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1162 CLEAR_FLAG(F_CF);
1163 CLEAR_FLAG(F_OF);
1164 } else {
1165 SET_FLAG(F_CF);
1166 SET_FLAG(F_OF);
1167 }
1168 *destreg = (u16)res;
1169 }
Jason Jina63ce952007-07-06 08:34:56 +08001170 }
1171 DECODE_CLEAR_SEGOVR();
1172 END_OF_INSTR();
1173}
1174
1175/****************************************************************************
1176REMARKS:
1177Handles opcode 0x6c
1178****************************************************************************/
1179void x86emuOp_ins_byte(u8 X86EMU_UNUSED(op1))
1180{
1181 START_OF_INSTR();
1182 DECODE_PRINTF("INSB\n");
1183 ins(1);
1184 TRACE_AND_STEP();
1185 DECODE_CLEAR_SEGOVR();
1186 END_OF_INSTR();
1187}
1188
1189/****************************************************************************
1190REMARKS:
1191Handles opcode 0x6d
1192****************************************************************************/
1193void x86emuOp_ins_word(u8 X86EMU_UNUSED(op1))
1194{
1195 START_OF_INSTR();
1196 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001197 DECODE_PRINTF("INSD\n");
1198 ins(4);
Jason Jina63ce952007-07-06 08:34:56 +08001199 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001200 DECODE_PRINTF("INSW\n");
1201 ins(2);
Jason Jina63ce952007-07-06 08:34:56 +08001202 }
1203 TRACE_AND_STEP();
1204 DECODE_CLEAR_SEGOVR();
1205 END_OF_INSTR();
1206}
1207
1208/****************************************************************************
1209REMARKS:
1210Handles opcode 0x6e
1211****************************************************************************/
1212void x86emuOp_outs_byte(u8 X86EMU_UNUSED(op1))
1213{
1214 START_OF_INSTR();
1215 DECODE_PRINTF("OUTSB\n");
1216 outs(1);
1217 TRACE_AND_STEP();
1218 DECODE_CLEAR_SEGOVR();
1219 END_OF_INSTR();
1220}
1221
1222/****************************************************************************
1223REMARKS:
1224Handles opcode 0x6f
1225****************************************************************************/
1226void x86emuOp_outs_word(u8 X86EMU_UNUSED(op1))
1227{
1228 START_OF_INSTR();
1229 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001230 DECODE_PRINTF("OUTSD\n");
1231 outs(4);
Jason Jina63ce952007-07-06 08:34:56 +08001232 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001233 DECODE_PRINTF("OUTSW\n");
1234 outs(2);
Jason Jina63ce952007-07-06 08:34:56 +08001235 }
1236 TRACE_AND_STEP();
1237 DECODE_CLEAR_SEGOVR();
1238 END_OF_INSTR();
1239}
1240
1241/****************************************************************************
1242REMARKS:
1243Handles opcode 0x70 - 0x7F
1244****************************************************************************/
1245int x86emu_check_jump_condition(u8 op);
1246
1247void x86emuOp_jump_near_cond(u8 op1)
1248{
1249 s8 offset;
1250 u16 target;
1251 int cond;
1252
1253 /* jump to byte offset if overflow flag is set */
1254 START_OF_INSTR();
1255 cond = x86emu_check_jump_condition(op1 & 0xF);
1256 offset = (s8)fetch_byte_imm();
1257 target = (u16)(M.x86.R_IP + (s16)offset);
1258 DECODE_PRINTF2("%x\n", target);
1259 TRACE_AND_STEP();
1260 if (cond)
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001261 M.x86.R_IP = target;
Jason Jina63ce952007-07-06 08:34:56 +08001262 DECODE_CLEAR_SEGOVR();
1263 END_OF_INSTR();
1264}
1265
1266/****************************************************************************
1267REMARKS:
1268Handles opcode 0x80
1269****************************************************************************/
1270void x86emuOp_opc80_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
1271{
1272 int mod, rl, rh;
1273 u8 *destreg;
1274 uint destoffset;
1275 u8 imm;
1276 u8 destval;
1277
1278 /*
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001279 * Weirdo special case instruction format. Part of the opcode
Jason Jina63ce952007-07-06 08:34:56 +08001280 * held below in "RH". Doubly nested case would result, except
1281 * that the decoded instruction
1282 */
1283 START_OF_INSTR();
1284 FETCH_DECODE_MODRM(mod, rh, rl);
1285#ifdef DEBUG
1286 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001287 /* XXX DECODE_PRINTF may be changed to something more
1288 general, so that it is important to leave the strings
1289 in the same format, even though the result is that the
1290 above test is done twice. */
Jason Jina63ce952007-07-06 08:34:56 +08001291
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001292 switch (rh) {
1293 case 0:
1294 DECODE_PRINTF("ADD\t");
1295 break;
1296 case 1:
1297 DECODE_PRINTF("OR\t");
1298 break;
1299 case 2:
1300 DECODE_PRINTF("ADC\t");
1301 break;
1302 case 3:
1303 DECODE_PRINTF("SBB\t");
1304 break;
1305 case 4:
1306 DECODE_PRINTF("AND\t");
1307 break;
1308 case 5:
1309 DECODE_PRINTF("SUB\t");
1310 break;
1311 case 6:
1312 DECODE_PRINTF("XOR\t");
1313 break;
1314 case 7:
1315 DECODE_PRINTF("CMP\t");
1316 break;
1317 }
Jason Jina63ce952007-07-06 08:34:56 +08001318 }
1319#endif
1320 /* know operation, decode the mod byte to find the addressing
1321 mode. */
1322 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001323 DECODE_PRINTF("BYTE PTR ");
1324 destoffset = decode_rmXX_address(mod, rl);
1325 DECODE_PRINTF(",");
1326 destval = fetch_data_byte(destoffset);
1327 imm = fetch_byte_imm();
1328 DECODE_PRINTF2("%x\n", imm);
1329 TRACE_AND_STEP();
1330 destval = (*genop_byte_operation[rh]) (destval, imm);
1331 if (rh != 7)
1332 store_data_byte(destoffset, destval);
1333 } else { /* register to register */
1334 destreg = DECODE_RM_BYTE_REGISTER(rl);
1335 DECODE_PRINTF(",");
1336 imm = fetch_byte_imm();
1337 DECODE_PRINTF2("%x\n", imm);
1338 TRACE_AND_STEP();
1339 destval = (*genop_byte_operation[rh]) (*destreg, imm);
1340 if (rh != 7)
1341 *destreg = destval;
Jason Jina63ce952007-07-06 08:34:56 +08001342 }
1343 DECODE_CLEAR_SEGOVR();
1344 END_OF_INSTR();
1345}
1346
1347/****************************************************************************
1348REMARKS:
1349Handles opcode 0x81
1350****************************************************************************/
1351void x86emuOp_opc81_word_RM_IMM(u8 X86EMU_UNUSED(op1))
1352{
1353 int mod, rl, rh;
1354 uint destoffset;
1355
1356 /*
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001357 * Weirdo special case instruction format. Part of the opcode
Jason Jina63ce952007-07-06 08:34:56 +08001358 * held below in "RH". Doubly nested case would result, except
1359 * that the decoded instruction
1360 */
1361 START_OF_INSTR();
1362 FETCH_DECODE_MODRM(mod, rh, rl);
1363#ifdef DEBUG
1364 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001365 /* XXX DECODE_PRINTF may be changed to something more
1366 general, so that it is important to leave the strings
1367 in the same format, even though the result is that the
1368 above test is done twice. */
Jason Jina63ce952007-07-06 08:34:56 +08001369
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001370 switch (rh) {
1371 case 0:
1372 DECODE_PRINTF("ADD\t");
1373 break;
1374 case 1:
1375 DECODE_PRINTF("OR\t");
1376 break;
1377 case 2:
1378 DECODE_PRINTF("ADC\t");
1379 break;
1380 case 3:
1381 DECODE_PRINTF("SBB\t");
1382 break;
1383 case 4:
1384 DECODE_PRINTF("AND\t");
1385 break;
1386 case 5:
1387 DECODE_PRINTF("SUB\t");
1388 break;
1389 case 6:
1390 DECODE_PRINTF("XOR\t");
1391 break;
1392 case 7:
1393 DECODE_PRINTF("CMP\t");
1394 break;
1395 }
Jason Jina63ce952007-07-06 08:34:56 +08001396 }
1397#endif
1398 /*
1399 * Know operation, decode the mod byte to find the addressing
1400 * mode.
1401 */
1402 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001403 DECODE_PRINTF("DWORD PTR ");
1404 destoffset = decode_rmXX_address(mod, rl);
1405 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1406 u32 destval,imm;
Jason Jina63ce952007-07-06 08:34:56 +08001407
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001408 DECODE_PRINTF(",");
1409 destval = fetch_data_long(destoffset);
1410 imm = fetch_long_imm();
1411 DECODE_PRINTF2("%x\n", imm);
1412 TRACE_AND_STEP();
1413 destval = (*genop_long_operation[rh]) (destval, imm);
1414 if (rh != 7)
1415 store_data_long(destoffset, destval);
1416 } else {
1417 u16 destval,imm;
Jason Jina63ce952007-07-06 08:34:56 +08001418
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001419 DECODE_PRINTF(",");
1420 destval = fetch_data_word(destoffset);
1421 imm = fetch_word_imm();
1422 DECODE_PRINTF2("%x\n", imm);
1423 TRACE_AND_STEP();
1424 destval = (*genop_word_operation[rh]) (destval, imm);
1425 if (rh != 7)
1426 store_data_word(destoffset, destval);
1427 }
1428 } else { /* register to register */
1429 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1430 u32 *destreg;
1431 u32 destval,imm;
Jason Jina63ce952007-07-06 08:34:56 +08001432
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001433 destreg = DECODE_RM_LONG_REGISTER(rl);
1434 DECODE_PRINTF(",");
1435 imm = fetch_long_imm();
1436 DECODE_PRINTF2("%x\n", imm);
1437 TRACE_AND_STEP();
1438 destval = (*genop_long_operation[rh]) (*destreg, imm);
1439 if (rh != 7)
1440 *destreg = destval;
1441 } else {
1442 u16 *destreg;
1443 u16 destval,imm;
Jason Jina63ce952007-07-06 08:34:56 +08001444
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001445 destreg = DECODE_RM_WORD_REGISTER(rl);
1446 DECODE_PRINTF(",");
1447 imm = fetch_word_imm();
1448 DECODE_PRINTF2("%x\n", imm);
1449 TRACE_AND_STEP();
1450 destval = (*genop_word_operation[rh]) (*destreg, imm);
1451 if (rh != 7)
1452 *destreg = destval;
1453 }
Jason Jina63ce952007-07-06 08:34:56 +08001454 }
1455 DECODE_CLEAR_SEGOVR();
1456 END_OF_INSTR();
1457}
1458
1459/****************************************************************************
1460REMARKS:
1461Handles opcode 0x82
1462****************************************************************************/
1463void x86emuOp_opc82_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
1464{
1465 int mod, rl, rh;
1466 u8 *destreg;
1467 uint destoffset;
1468 u8 imm;
1469 u8 destval;
1470
1471 /*
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001472 * Weirdo special case instruction format. Part of the opcode
Jason Jina63ce952007-07-06 08:34:56 +08001473 * held below in "RH". Doubly nested case would result, except
1474 * that the decoded instruction Similar to opcode 81, except that
1475 * the immediate byte is sign extended to a word length.
1476 */
1477 START_OF_INSTR();
1478 FETCH_DECODE_MODRM(mod, rh, rl);
1479#ifdef DEBUG
1480 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001481 /* XXX DECODE_PRINTF may be changed to something more
1482 general, so that it is important to leave the strings
1483 in the same format, even though the result is that the
1484 above test is done twice. */
1485 switch (rh) {
1486 case 0:
1487 DECODE_PRINTF("ADD\t");
1488 break;
1489 case 1:
1490 DECODE_PRINTF("OR\t");
1491 break;
1492 case 2:
1493 DECODE_PRINTF("ADC\t");
1494 break;
1495 case 3:
1496 DECODE_PRINTF("SBB\t");
1497 break;
1498 case 4:
1499 DECODE_PRINTF("AND\t");
1500 break;
1501 case 5:
1502 DECODE_PRINTF("SUB\t");
1503 break;
1504 case 6:
1505 DECODE_PRINTF("XOR\t");
1506 break;
1507 case 7:
1508 DECODE_PRINTF("CMP\t");
1509 break;
1510 }
Jason Jina63ce952007-07-06 08:34:56 +08001511 }
1512#endif
1513 /* know operation, decode the mod byte to find the addressing
1514 mode. */
1515 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001516 DECODE_PRINTF("BYTE PTR ");
1517 destoffset = decode_rmXX_address(mod, rl);
1518 destval = fetch_data_byte(destoffset);
1519 imm = fetch_byte_imm();
1520 DECODE_PRINTF2(",%x\n", imm);
1521 TRACE_AND_STEP();
1522 destval = (*genop_byte_operation[rh]) (destval, imm);
1523 if (rh != 7)
1524 store_data_byte(destoffset, destval);
1525 } else { /* register to register */
1526 destreg = DECODE_RM_BYTE_REGISTER(rl);
1527 imm = fetch_byte_imm();
1528 DECODE_PRINTF2(",%x\n", imm);
1529 TRACE_AND_STEP();
1530 destval = (*genop_byte_operation[rh]) (*destreg, imm);
1531 if (rh != 7)
1532 *destreg = destval;
Jason Jina63ce952007-07-06 08:34:56 +08001533 }
1534 DECODE_CLEAR_SEGOVR();
1535 END_OF_INSTR();
1536}
1537
1538/****************************************************************************
1539REMARKS:
1540Handles opcode 0x83
1541****************************************************************************/
1542void x86emuOp_opc83_word_RM_IMM(u8 X86EMU_UNUSED(op1))
1543{
1544 int mod, rl, rh;
1545 uint destoffset;
1546
1547 /*
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001548 * Weirdo special case instruction format. Part of the opcode
Jason Jina63ce952007-07-06 08:34:56 +08001549 * held below in "RH". Doubly nested case would result, except
1550 * that the decoded instruction Similar to opcode 81, except that
1551 * the immediate byte is sign extended to a word length.
1552 */
1553 START_OF_INSTR();
1554 FETCH_DECODE_MODRM(mod, rh, rl);
1555#ifdef DEBUG
1556 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001557 /* XXX DECODE_PRINTF may be changed to something more
1558 general, so that it is important to leave the strings
1559 in the same format, even though the result is that the
1560 above test is done twice. */
Jason Jina63ce952007-07-06 08:34:56 +08001561 switch (rh) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001562 case 0:
1563 DECODE_PRINTF("ADD\t");
1564 break;
1565 case 1:
1566 DECODE_PRINTF("OR\t");
1567 break;
1568 case 2:
1569 DECODE_PRINTF("ADC\t");
1570 break;
1571 case 3:
1572 DECODE_PRINTF("SBB\t");
1573 break;
1574 case 4:
1575 DECODE_PRINTF("AND\t");
1576 break;
1577 case 5:
1578 DECODE_PRINTF("SUB\t");
1579 break;
1580 case 6:
1581 DECODE_PRINTF("XOR\t");
1582 break;
1583 case 7:
1584 DECODE_PRINTF("CMP\t");
1585 break;
1586 }
Jason Jina63ce952007-07-06 08:34:56 +08001587 }
1588#endif
1589 /* know operation, decode the mod byte to find the addressing
1590 mode. */
1591 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001592 DECODE_PRINTF("DWORD PTR ");
1593 destoffset = decode_rmXX_address(mod,rl);
Jason Jina63ce952007-07-06 08:34:56 +08001594
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001595 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1596 u32 destval,imm;
Jason Jina63ce952007-07-06 08:34:56 +08001597
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001598 destval = fetch_data_long(destoffset);
1599 imm = (s8) fetch_byte_imm();
1600 DECODE_PRINTF2(",%x\n", imm);
1601 TRACE_AND_STEP();
1602 destval = (*genop_long_operation[rh]) (destval, imm);
1603 if (rh != 7)
1604 store_data_long(destoffset, destval);
1605 } else {
1606 u16 destval,imm;
Jason Jina63ce952007-07-06 08:34:56 +08001607
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001608 destval = fetch_data_word(destoffset);
1609 imm = (s8) fetch_byte_imm();
1610 DECODE_PRINTF2(",%x\n", imm);
1611 TRACE_AND_STEP();
1612 destval = (*genop_word_operation[rh]) (destval, imm);
1613 if (rh != 7)
1614 store_data_word(destoffset, destval);
1615 }
1616 } else { /* register to register */
1617 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1618 u32 *destreg;
1619 u32 destval,imm;
Jason Jina63ce952007-07-06 08:34:56 +08001620
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001621 destreg = DECODE_RM_LONG_REGISTER(rl);
1622 imm = (s8) fetch_byte_imm();
1623 DECODE_PRINTF2(",%x\n", imm);
1624 TRACE_AND_STEP();
1625 destval = (*genop_long_operation[rh]) (*destreg, imm);
1626 if (rh != 7)
1627 *destreg = destval;
1628 } else {
1629 u16 *destreg;
1630 u16 destval,imm;
Jason Jina63ce952007-07-06 08:34:56 +08001631
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001632 destreg = DECODE_RM_WORD_REGISTER(rl);
1633 imm = (s8) fetch_byte_imm();
1634 DECODE_PRINTF2(",%x\n", imm);
1635 TRACE_AND_STEP();
1636 destval = (*genop_word_operation[rh]) (*destreg, imm);
1637 if (rh != 7)
1638 *destreg = destval;
1639 }
Jason Jina63ce952007-07-06 08:34:56 +08001640 }
1641 DECODE_CLEAR_SEGOVR();
1642 END_OF_INSTR();
1643}
1644
1645/****************************************************************************
1646REMARKS:
1647Handles opcode 0x84
1648****************************************************************************/
1649void x86emuOp_test_byte_RM_R(u8 X86EMU_UNUSED(op1))
1650{
1651 int mod, rl, rh;
1652 u8 *destreg, *srcreg;
1653 uint destoffset;
1654 u8 destval;
1655
1656 START_OF_INSTR();
1657 DECODE_PRINTF("TEST\t");
1658 FETCH_DECODE_MODRM(mod, rh, rl);
1659 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001660 destoffset = decode_rmXX_address(mod, rl);
1661 DECODE_PRINTF(",");
1662 destval = fetch_data_byte(destoffset);
1663 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1664 DECODE_PRINTF("\n");
1665 TRACE_AND_STEP();
1666 test_byte(destval, *srcreg);
1667 } else { /* register to register */
1668 destreg = DECODE_RM_BYTE_REGISTER(rl);
1669 DECODE_PRINTF(",");
1670 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1671 DECODE_PRINTF("\n");
1672 TRACE_AND_STEP();
1673 test_byte(*destreg, *srcreg);
Jason Jina63ce952007-07-06 08:34:56 +08001674 }
1675 DECODE_CLEAR_SEGOVR();
1676 END_OF_INSTR();
1677}
1678
1679/****************************************************************************
1680REMARKS:
1681Handles opcode 0x85
1682****************************************************************************/
1683void x86emuOp_test_word_RM_R(u8 X86EMU_UNUSED(op1))
1684{
1685 int mod, rl, rh;
1686 uint destoffset;
1687
1688 START_OF_INSTR();
1689 DECODE_PRINTF("TEST\t");
1690 FETCH_DECODE_MODRM(mod, rh, rl);
1691 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001692 destoffset = decode_rmXX_address(mod, rl);
1693 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1694 u32 destval;
1695 u32 *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08001696
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001697 DECODE_PRINTF(",");
1698 destval = fetch_data_long(destoffset);
1699 srcreg = DECODE_RM_LONG_REGISTER(rh);
1700 DECODE_PRINTF("\n");
1701 TRACE_AND_STEP();
1702 test_long(destval, *srcreg);
1703 } else {
1704 u16 destval;
1705 u16 *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08001706
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001707 DECODE_PRINTF(",");
1708 destval = fetch_data_word(destoffset);
1709 srcreg = DECODE_RM_WORD_REGISTER(rh);
1710 DECODE_PRINTF("\n");
1711 TRACE_AND_STEP();
1712 test_word(destval, *srcreg);
1713 }
1714 } else { /* register to register */
1715 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1716 u32 *destreg,*srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08001717
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001718 destreg = DECODE_RM_LONG_REGISTER(rl);
1719 DECODE_PRINTF(",");
1720 srcreg = DECODE_RM_LONG_REGISTER(rh);
1721 DECODE_PRINTF("\n");
1722 TRACE_AND_STEP();
1723 test_long(*destreg, *srcreg);
1724 } else {
1725 u16 *destreg,*srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08001726
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001727 destreg = DECODE_RM_WORD_REGISTER(rl);
1728 DECODE_PRINTF(",");
1729 srcreg = DECODE_RM_WORD_REGISTER(rh);
1730 DECODE_PRINTF("\n");
1731 TRACE_AND_STEP();
1732 test_word(*destreg, *srcreg);
1733 }
Jason Jina63ce952007-07-06 08:34:56 +08001734 }
1735 DECODE_CLEAR_SEGOVR();
1736 END_OF_INSTR();
1737}
1738
1739/****************************************************************************
1740REMARKS:
1741Handles opcode 0x86
1742****************************************************************************/
1743void x86emuOp_xchg_byte_RM_R(u8 X86EMU_UNUSED(op1))
1744{
1745 int mod, rl, rh;
1746 u8 *destreg, *srcreg;
1747 uint destoffset;
1748 u8 destval;
1749 u8 tmp;
1750
1751 START_OF_INSTR();
1752 DECODE_PRINTF("XCHG\t");
1753 FETCH_DECODE_MODRM(mod, rh, rl);
1754 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001755 destoffset = decode_rmXX_address(mod, rl);
1756 DECODE_PRINTF(",");
1757 destval = fetch_data_byte(destoffset);
1758 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1759 DECODE_PRINTF("\n");
1760 TRACE_AND_STEP();
1761 tmp = *srcreg;
1762 *srcreg = destval;
1763 destval = tmp;
1764 store_data_byte(destoffset, destval);
1765 } else { /* register to register */
1766 destreg = DECODE_RM_BYTE_REGISTER(rl);
1767 DECODE_PRINTF(",");
1768 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1769 DECODE_PRINTF("\n");
1770 TRACE_AND_STEP();
1771 tmp = *srcreg;
1772 *srcreg = *destreg;
1773 *destreg = tmp;
Jason Jina63ce952007-07-06 08:34:56 +08001774 }
1775 DECODE_CLEAR_SEGOVR();
1776 END_OF_INSTR();
1777}
1778
1779/****************************************************************************
1780REMARKS:
1781Handles opcode 0x87
1782****************************************************************************/
1783void x86emuOp_xchg_word_RM_R(u8 X86EMU_UNUSED(op1))
1784{
1785 int mod, rl, rh;
1786 uint destoffset;
1787
1788 START_OF_INSTR();
1789 DECODE_PRINTF("XCHG\t");
1790 FETCH_DECODE_MODRM(mod, rh, rl);
1791 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001792 destoffset = decode_rmXX_address(mod, rl);
1793 DECODE_PRINTF(",");
1794 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1795 u32 *srcreg;
1796 u32 destval,tmp;
Jason Jina63ce952007-07-06 08:34:56 +08001797
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001798 destval = fetch_data_long(destoffset);
1799 srcreg = DECODE_RM_LONG_REGISTER(rh);
1800 DECODE_PRINTF("\n");
1801 TRACE_AND_STEP();
1802 tmp = *srcreg;
1803 *srcreg = destval;
1804 destval = tmp;
1805 store_data_long(destoffset, destval);
1806 } else {
1807 u16 *srcreg;
1808 u16 destval,tmp;
Jason Jina63ce952007-07-06 08:34:56 +08001809
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001810 destval = fetch_data_word(destoffset);
1811 srcreg = DECODE_RM_WORD_REGISTER(rh);
1812 DECODE_PRINTF("\n");
1813 TRACE_AND_STEP();
1814 tmp = *srcreg;
1815 *srcreg = destval;
1816 destval = tmp;
1817 store_data_word(destoffset, destval);
1818 }
1819 } else { /* register to register */
1820 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1821 u32 *destreg,*srcreg;
1822 u32 tmp;
Jason Jina63ce952007-07-06 08:34:56 +08001823
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001824 destreg = DECODE_RM_LONG_REGISTER(rl);
1825 DECODE_PRINTF(",");
1826 srcreg = DECODE_RM_LONG_REGISTER(rh);
1827 DECODE_PRINTF("\n");
1828 TRACE_AND_STEP();
1829 tmp = *srcreg;
1830 *srcreg = *destreg;
1831 *destreg = tmp;
1832 } else {
1833 u16 *destreg,*srcreg;
1834 u16 tmp;
Jason Jina63ce952007-07-06 08:34:56 +08001835
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001836 destreg = DECODE_RM_WORD_REGISTER(rl);
1837 DECODE_PRINTF(",");
1838 srcreg = DECODE_RM_WORD_REGISTER(rh);
1839 DECODE_PRINTF("\n");
1840 TRACE_AND_STEP();
1841 tmp = *srcreg;
1842 *srcreg = *destreg;
1843 *destreg = tmp;
1844 }
Jason Jina63ce952007-07-06 08:34:56 +08001845 }
1846 DECODE_CLEAR_SEGOVR();
1847 END_OF_INSTR();
1848}
1849
1850/****************************************************************************
1851REMARKS:
1852Handles opcode 0x88
1853****************************************************************************/
1854void x86emuOp_mov_byte_RM_R(u8 X86EMU_UNUSED(op1))
1855{
1856 int mod, rl, rh;
1857 u8 *destreg, *srcreg;
1858 uint destoffset;
1859
1860 START_OF_INSTR();
1861 DECODE_PRINTF("MOV\t");
1862 FETCH_DECODE_MODRM(mod, rh, rl);
1863 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001864 destoffset = decode_rmXX_address(mod, rl);
1865 DECODE_PRINTF(",");
1866 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1867 DECODE_PRINTF("\n");
1868 TRACE_AND_STEP();
1869 store_data_byte(destoffset, *srcreg);
1870 } else { /* register to register */
1871 destreg = DECODE_RM_BYTE_REGISTER(rl);
1872 DECODE_PRINTF(",");
1873 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1874 DECODE_PRINTF("\n");
1875 TRACE_AND_STEP();
1876 *destreg = *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08001877 }
1878 DECODE_CLEAR_SEGOVR();
1879 END_OF_INSTR();
1880}
1881
1882/****************************************************************************
1883REMARKS:
1884Handles opcode 0x89
1885****************************************************************************/
1886void x86emuOp_mov_word_RM_R(u8 X86EMU_UNUSED(op1))
1887{
1888 int mod, rl, rh;
1889 uint destoffset;
1890
1891 START_OF_INSTR();
1892 DECODE_PRINTF("MOV\t");
1893 FETCH_DECODE_MODRM(mod, rh, rl);
1894 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001895 destoffset = decode_rmXX_address(mod, rl);
1896 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1897 u32 *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08001898
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001899 DECODE_PRINTF(",");
1900 srcreg = DECODE_RM_LONG_REGISTER(rh);
1901 DECODE_PRINTF("\n");
1902 TRACE_AND_STEP();
1903 store_data_long(destoffset, *srcreg);
1904 } else {
1905 u16 *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08001906
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001907 DECODE_PRINTF(",");
1908 srcreg = DECODE_RM_WORD_REGISTER(rh);
1909 DECODE_PRINTF("\n");
1910 TRACE_AND_STEP();
1911 store_data_word(destoffset, *srcreg);
1912 }
1913 } else { /* register to register */
1914 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1915 u32 *destreg,*srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08001916
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001917 destreg = DECODE_RM_LONG_REGISTER(rl);
1918 DECODE_PRINTF(",");
1919 srcreg = DECODE_RM_LONG_REGISTER(rh);
1920 DECODE_PRINTF("\n");
1921 TRACE_AND_STEP();
1922 *destreg = *srcreg;
1923 } else {
1924 u16 *destreg,*srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08001925
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001926 destreg = DECODE_RM_WORD_REGISTER(rl);
1927 DECODE_PRINTF(",");
1928 srcreg = DECODE_RM_WORD_REGISTER(rh);
1929 DECODE_PRINTF("\n");
1930 TRACE_AND_STEP();
1931 *destreg = *srcreg;
1932 }
Jason Jina63ce952007-07-06 08:34:56 +08001933 }
1934 DECODE_CLEAR_SEGOVR();
1935 END_OF_INSTR();
1936}
1937
1938/****************************************************************************
1939REMARKS:
1940Handles opcode 0x8a
1941****************************************************************************/
1942void x86emuOp_mov_byte_R_RM(u8 X86EMU_UNUSED(op1))
1943{
1944 int mod, rl, rh;
1945 u8 *destreg, *srcreg;
1946 uint srcoffset;
1947 u8 srcval;
1948
1949 START_OF_INSTR();
1950 DECODE_PRINTF("MOV\t");
1951 FETCH_DECODE_MODRM(mod, rh, rl);
1952 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001953 destreg = DECODE_RM_BYTE_REGISTER(rh);
1954 DECODE_PRINTF(",");
1955 srcoffset = decode_rmXX_address(mod, rl);
1956 srcval = fetch_data_byte(srcoffset);
1957 DECODE_PRINTF("\n");
1958 TRACE_AND_STEP();
1959 *destreg = srcval;
1960 } else { /* register to register */
1961 destreg = DECODE_RM_BYTE_REGISTER(rh);
1962 DECODE_PRINTF(",");
1963 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1964 DECODE_PRINTF("\n");
1965 TRACE_AND_STEP();
1966 *destreg = *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08001967 }
1968 DECODE_CLEAR_SEGOVR();
1969 END_OF_INSTR();
1970}
1971
1972/****************************************************************************
1973REMARKS:
1974Handles opcode 0x8b
1975****************************************************************************/
1976void x86emuOp_mov_word_R_RM(u8 X86EMU_UNUSED(op1))
1977{
1978 int mod, rl, rh;
1979 uint srcoffset;
1980
1981 START_OF_INSTR();
1982 DECODE_PRINTF("MOV\t");
1983 FETCH_DECODE_MODRM(mod, rh, rl);
1984 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001985 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1986 u32 *destreg;
1987 u32 srcval;
Jason Jina63ce952007-07-06 08:34:56 +08001988
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001989 destreg = DECODE_RM_LONG_REGISTER(rh);
1990 DECODE_PRINTF(",");
1991 srcoffset = decode_rmXX_address(mod, rl);
1992 srcval = fetch_data_long(srcoffset);
1993 DECODE_PRINTF("\n");
1994 TRACE_AND_STEP();
1995 *destreg = srcval;
1996 } else {
1997 u16 *destreg;
1998 u16 srcval;
Jason Jina63ce952007-07-06 08:34:56 +08001999
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002000 destreg = DECODE_RM_WORD_REGISTER(rh);
2001 DECODE_PRINTF(",");
2002 srcoffset = decode_rmXX_address(mod, rl);
2003 srcval = fetch_data_word(srcoffset);
2004 DECODE_PRINTF("\n");
2005 TRACE_AND_STEP();
2006 *destreg = srcval;
2007 }
2008 } else { /* register to register */
2009 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2010 u32 *destreg, *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08002011
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002012 destreg = DECODE_RM_LONG_REGISTER(rh);
2013 DECODE_PRINTF(",");
2014 srcreg = DECODE_RM_LONG_REGISTER(rl);
2015 DECODE_PRINTF("\n");
2016 TRACE_AND_STEP();
2017 *destreg = *srcreg;
2018 } else {
2019 u16 *destreg, *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08002020
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002021 destreg = DECODE_RM_WORD_REGISTER(rh);
2022 DECODE_PRINTF(",");
2023 srcreg = DECODE_RM_WORD_REGISTER(rl);
2024 DECODE_PRINTF("\n");
2025 TRACE_AND_STEP();
2026 *destreg = *srcreg;
2027 }
Jason Jina63ce952007-07-06 08:34:56 +08002028 }
2029 DECODE_CLEAR_SEGOVR();
2030 END_OF_INSTR();
2031}
2032
2033/****************************************************************************
2034REMARKS:
2035Handles opcode 0x8c
2036****************************************************************************/
2037void x86emuOp_mov_word_RM_SR(u8 X86EMU_UNUSED(op1))
2038{
2039 int mod, rl, rh;
2040 u16 *destreg, *srcreg;
2041 uint destoffset;
2042 u16 destval;
2043
2044 START_OF_INSTR();
2045 DECODE_PRINTF("MOV\t");
2046 FETCH_DECODE_MODRM(mod, rh, rl);
2047 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002048 destoffset = decode_rmXX_address(mod, rl);
2049 DECODE_PRINTF(",");
2050 srcreg = decode_rm_seg_register(rh);
2051 DECODE_PRINTF("\n");
2052 TRACE_AND_STEP();
2053 destval = *srcreg;
2054 store_data_word(destoffset, destval);
2055 } else { /* register to register */
2056 destreg = DECODE_RM_WORD_REGISTER(rl);
2057 DECODE_PRINTF(",");
2058 srcreg = decode_rm_seg_register(rh);
2059 DECODE_PRINTF("\n");
2060 TRACE_AND_STEP();
2061 *destreg = *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08002062 }
2063 DECODE_CLEAR_SEGOVR();
2064 END_OF_INSTR();
2065}
2066
2067/****************************************************************************
2068REMARKS:
2069Handles opcode 0x8d
2070****************************************************************************/
2071void x86emuOp_lea_word_R_M(u8 X86EMU_UNUSED(op1))
2072{
2073 int mod, rl, rh;
2074 u16 *srcreg;
2075 uint destoffset;
2076
2077/*
2078 * TODO: Need to handle address size prefix!
2079 *
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002080 * lea eax,[eax+ebx*2] ??
Jason Jina63ce952007-07-06 08:34:56 +08002081 */
2082
2083 START_OF_INSTR();
2084 DECODE_PRINTF("LEA\t");
2085 FETCH_DECODE_MODRM(mod, rh, rl);
2086 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002087 srcreg = DECODE_RM_WORD_REGISTER(rh);
2088 DECODE_PRINTF(",");
2089 destoffset = decode_rmXX_address(mod, rl);
2090 DECODE_PRINTF("\n");
2091 TRACE_AND_STEP();
2092 *srcreg = (u16)destoffset;
2093 }
Jason Jina63ce952007-07-06 08:34:56 +08002094 /* } else { undefined. Do nothing. } */
2095 DECODE_CLEAR_SEGOVR();
2096 END_OF_INSTR();
2097}
2098
2099/****************************************************************************
2100REMARKS:
2101Handles opcode 0x8e
2102****************************************************************************/
2103void x86emuOp_mov_word_SR_RM(u8 X86EMU_UNUSED(op1))
2104{
2105 int mod, rl, rh;
2106 u16 *destreg, *srcreg;
2107 uint srcoffset;
2108 u16 srcval;
2109
2110 START_OF_INSTR();
2111 DECODE_PRINTF("MOV\t");
2112 FETCH_DECODE_MODRM(mod, rh, rl);
2113 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002114 destreg = decode_rm_seg_register(rh);
2115 DECODE_PRINTF(",");
2116 srcoffset = decode_rmXX_address(mod, rl);
2117 srcval = fetch_data_word(srcoffset);
2118 DECODE_PRINTF("\n");
2119 TRACE_AND_STEP();
2120 *destreg = srcval;
2121 } else { /* register to register */
2122 destreg = decode_rm_seg_register(rh);
2123 DECODE_PRINTF(",");
2124 srcreg = DECODE_RM_WORD_REGISTER(rl);
2125 DECODE_PRINTF("\n");
2126 TRACE_AND_STEP();
2127 *destreg = *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08002128 }
2129 /*
2130 * Clean up, and reset all the R_xSP pointers to the correct
2131 * locations. This is about 3x too much overhead (doing all the
2132 * segreg ptrs when only one is needed, but this instruction
2133 * *cannot* be that common, and this isn't too much work anyway.
2134 */
2135 DECODE_CLEAR_SEGOVR();
2136 END_OF_INSTR();
2137}
2138
2139/****************************************************************************
2140REMARKS:
2141Handles opcode 0x8f
2142****************************************************************************/
2143void x86emuOp_pop_RM(u8 X86EMU_UNUSED(op1))
2144{
2145 int mod, rl, rh;
2146 uint destoffset;
2147
2148 START_OF_INSTR();
2149 DECODE_PRINTF("POP\t");
2150 FETCH_DECODE_MODRM(mod, rh, rl);
2151 if (rh != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002152 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
2153 HALT_SYS();
Jason Jina63ce952007-07-06 08:34:56 +08002154 }
2155 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002156 destoffset = decode_rmXX_address(mod, rl);
2157 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2158 u32 destval;
Jason Jina63ce952007-07-06 08:34:56 +08002159
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002160 DECODE_PRINTF("\n");
2161 TRACE_AND_STEP();
2162 destval = pop_long();
2163 store_data_long(destoffset, destval);
2164 } else {
2165 u16 destval;
Jason Jina63ce952007-07-06 08:34:56 +08002166
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002167 DECODE_PRINTF("\n");
2168 TRACE_AND_STEP();
2169 destval = pop_word();
2170 store_data_word(destoffset, destval);
2171 }
2172 } else { /* register to register */
2173 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2174 u32 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08002175
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002176 destreg = DECODE_RM_LONG_REGISTER(rl);
2177 DECODE_PRINTF("\n");
2178 TRACE_AND_STEP();
2179 *destreg = pop_long();
2180 } else {
2181 u16 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08002182
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002183 destreg = DECODE_RM_WORD_REGISTER(rl);
2184 DECODE_PRINTF("\n");
2185 TRACE_AND_STEP();
2186 *destreg = pop_word();
2187 }
Jason Jina63ce952007-07-06 08:34:56 +08002188 }
2189 DECODE_CLEAR_SEGOVR();
2190 END_OF_INSTR();
2191}
2192
2193/****************************************************************************
2194REMARKS:
2195Handles opcode 0x90
2196****************************************************************************/
2197void x86emuOp_nop(u8 X86EMU_UNUSED(op1))
2198{
2199 START_OF_INSTR();
2200 DECODE_PRINTF("NOP\n");
2201 TRACE_AND_STEP();
2202 DECODE_CLEAR_SEGOVR();
2203 END_OF_INSTR();
2204}
2205
2206/****************************************************************************
2207REMARKS:
2208Handles opcode 0x91-0x97
2209****************************************************************************/
2210void x86emuOp_xchg_word_AX_register(u8 X86EMU_UNUSED(op1))
2211{
2212 u32 tmp;
2213
2214 op1 &= 0x7;
2215
2216 START_OF_INSTR();
2217
2218 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002219 u32 *reg32;
2220 DECODE_PRINTF("XCHG\tEAX,");
2221 reg32 = DECODE_RM_LONG_REGISTER(op1);
2222 DECODE_PRINTF("\n");
2223 TRACE_AND_STEP();
2224 tmp = M.x86.R_EAX;
2225 M.x86.R_EAX = *reg32;
2226 *reg32 = tmp;
Jason Jina63ce952007-07-06 08:34:56 +08002227 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002228 u16 *reg16;
2229 DECODE_PRINTF("XCHG\tAX,");
2230 reg16 = DECODE_RM_WORD_REGISTER(op1);
2231 DECODE_PRINTF("\n");
2232 TRACE_AND_STEP();
2233 tmp = M.x86.R_AX;
2234 M.x86.R_EAX = *reg16;
2235 *reg16 = (u16)tmp;
Jason Jina63ce952007-07-06 08:34:56 +08002236 }
2237 DECODE_CLEAR_SEGOVR();
2238 END_OF_INSTR();
2239}
2240
2241/****************************************************************************
2242REMARKS:
2243Handles opcode 0x98
2244****************************************************************************/
2245void x86emuOp_cbw(u8 X86EMU_UNUSED(op1))
2246{
2247 START_OF_INSTR();
2248 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002249 DECODE_PRINTF("CWDE\n");
Jason Jina63ce952007-07-06 08:34:56 +08002250 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002251 DECODE_PRINTF("CBW\n");
Jason Jina63ce952007-07-06 08:34:56 +08002252 }
2253 TRACE_AND_STEP();
2254 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002255 if (M.x86.R_AX & 0x8000) {
2256 M.x86.R_EAX |= 0xffff0000;
2257 } else {
2258 M.x86.R_EAX &= 0x0000ffff;
2259 }
Jason Jina63ce952007-07-06 08:34:56 +08002260 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002261 if (M.x86.R_AL & 0x80) {
2262 M.x86.R_AH = 0xff;
2263 } else {
2264 M.x86.R_AH = 0x0;
2265 }
Jason Jina63ce952007-07-06 08:34:56 +08002266 }
2267 DECODE_CLEAR_SEGOVR();
2268 END_OF_INSTR();
2269}
2270
2271/****************************************************************************
2272REMARKS:
2273Handles opcode 0x99
2274****************************************************************************/
2275void x86emuOp_cwd(u8 X86EMU_UNUSED(op1))
2276{
2277 START_OF_INSTR();
2278 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002279 DECODE_PRINTF("CDQ\n");
Jason Jina63ce952007-07-06 08:34:56 +08002280 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002281 DECODE_PRINTF("CWD\n");
Jason Jina63ce952007-07-06 08:34:56 +08002282 }
2283 DECODE_PRINTF("CWD\n");
2284 TRACE_AND_STEP();
2285 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002286 if (M.x86.R_EAX & 0x80000000) {
2287 M.x86.R_EDX = 0xffffffff;
2288 } else {
2289 M.x86.R_EDX = 0x0;
2290 }
Jason Jina63ce952007-07-06 08:34:56 +08002291 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002292 if (M.x86.R_AX & 0x8000) {
2293 M.x86.R_DX = 0xffff;
2294 } else {
2295 M.x86.R_DX = 0x0;
2296 }
Jason Jina63ce952007-07-06 08:34:56 +08002297 }
2298 DECODE_CLEAR_SEGOVR();
2299 END_OF_INSTR();
2300}
2301
2302/****************************************************************************
2303REMARKS:
2304Handles opcode 0x9a
2305****************************************************************************/
2306void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1))
2307{
2308 u16 farseg, faroff;
2309
2310 START_OF_INSTR();
2311 DECODE_PRINTF("CALL\t");
2312 faroff = fetch_word_imm();
2313 farseg = fetch_word_imm();
2314 DECODE_PRINTF2("%04x:", farseg);
2315 DECODE_PRINTF2("%04x\n", faroff);
2316 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, farseg, faroff, "FAR ");
2317
2318 /* XXX
2319 *
2320 * Hooked interrupt vectors calling into our "BIOS" will cause
2321 * problems unless all intersegment stuff is checked for BIOS
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002322 * access. Check needed here. For moment, let it alone.
Jason Jina63ce952007-07-06 08:34:56 +08002323 */
2324 TRACE_AND_STEP();
2325 push_word(M.x86.R_CS);
2326 M.x86.R_CS = farseg;
2327 push_word(M.x86.R_IP);
2328 M.x86.R_IP = faroff;
2329 DECODE_CLEAR_SEGOVR();
2330 END_OF_INSTR();
2331}
2332
2333/****************************************************************************
2334REMARKS:
2335Handles opcode 0x9b
2336****************************************************************************/
2337void x86emuOp_wait(u8 X86EMU_UNUSED(op1))
2338{
2339 START_OF_INSTR();
2340 DECODE_PRINTF("WAIT");
2341 TRACE_AND_STEP();
2342 /* NADA. */
2343 DECODE_CLEAR_SEGOVR();
2344 END_OF_INSTR();
2345}
2346
2347/****************************************************************************
2348REMARKS:
2349Handles opcode 0x9c
2350****************************************************************************/
2351void x86emuOp_pushf_word(u8 X86EMU_UNUSED(op1))
2352{
2353 u32 flags;
2354
2355 START_OF_INSTR();
2356 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002357 DECODE_PRINTF("PUSHFD\n");
Jason Jina63ce952007-07-06 08:34:56 +08002358 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002359 DECODE_PRINTF("PUSHF\n");
Jason Jina63ce952007-07-06 08:34:56 +08002360 }
2361 TRACE_AND_STEP();
2362
2363 /* clear out *all* bits not representing flags, and turn on real bits */
2364 flags = (M.x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
2365 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002366 push_long(flags);
Jason Jina63ce952007-07-06 08:34:56 +08002367 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002368 push_word((u16)flags);
Jason Jina63ce952007-07-06 08:34:56 +08002369 }
2370 DECODE_CLEAR_SEGOVR();
2371 END_OF_INSTR();
2372}
2373
2374/****************************************************************************
2375REMARKS:
2376Handles opcode 0x9d
2377****************************************************************************/
2378void x86emuOp_popf_word(u8 X86EMU_UNUSED(op1))
2379{
2380 START_OF_INSTR();
2381 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002382 DECODE_PRINTF("POPFD\n");
Jason Jina63ce952007-07-06 08:34:56 +08002383 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002384 DECODE_PRINTF("POPF\n");
Jason Jina63ce952007-07-06 08:34:56 +08002385 }
2386 TRACE_AND_STEP();
2387 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002388 M.x86.R_EFLG = pop_long();
Jason Jina63ce952007-07-06 08:34:56 +08002389 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002390 M.x86.R_FLG = pop_word();
Jason Jina63ce952007-07-06 08:34:56 +08002391 }
2392 DECODE_CLEAR_SEGOVR();
2393 END_OF_INSTR();
2394}
2395
2396/****************************************************************************
2397REMARKS:
2398Handles opcode 0x9e
2399****************************************************************************/
2400void x86emuOp_sahf(u8 X86EMU_UNUSED(op1))
2401{
2402 START_OF_INSTR();
2403 DECODE_PRINTF("SAHF\n");
2404 TRACE_AND_STEP();
2405 /* clear the lower bits of the flag register */
2406 M.x86.R_FLG &= 0xffffff00;
2407 /* or in the AH register into the flags register */
2408 M.x86.R_FLG |= M.x86.R_AH;
2409 DECODE_CLEAR_SEGOVR();
2410 END_OF_INSTR();
2411}
2412
2413/****************************************************************************
2414REMARKS:
2415Handles opcode 0x9f
2416****************************************************************************/
2417void x86emuOp_lahf(u8 X86EMU_UNUSED(op1))
2418{
2419 START_OF_INSTR();
2420 DECODE_PRINTF("LAHF\n");
2421 TRACE_AND_STEP();
2422 M.x86.R_AH = (u8)(M.x86.R_FLG & 0xff);
2423 /*undocumented TC++ behavior??? Nope. It's documented, but
2424 you have too look real hard to notice it. */
2425 M.x86.R_AH |= 0x2;
2426 DECODE_CLEAR_SEGOVR();
2427 END_OF_INSTR();
2428}
2429
2430/****************************************************************************
2431REMARKS:
2432Handles opcode 0xa0
2433****************************************************************************/
2434void x86emuOp_mov_AL_M_IMM(u8 X86EMU_UNUSED(op1))
2435{
2436 u16 offset;
2437
2438 START_OF_INSTR();
2439 DECODE_PRINTF("MOV\tAL,");
2440 offset = fetch_word_imm();
2441 DECODE_PRINTF2("[%04x]\n", offset);
2442 TRACE_AND_STEP();
2443 M.x86.R_AL = fetch_data_byte(offset);
2444 DECODE_CLEAR_SEGOVR();
2445 END_OF_INSTR();
2446}
2447
2448/****************************************************************************
2449REMARKS:
2450Handles opcode 0xa1
2451****************************************************************************/
2452void x86emuOp_mov_AX_M_IMM(u8 X86EMU_UNUSED(op1))
2453{
2454 u16 offset;
2455
2456 START_OF_INSTR();
2457 offset = fetch_word_imm();
2458 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002459 DECODE_PRINTF2("MOV\tEAX,[%04x]\n", offset);
Jason Jina63ce952007-07-06 08:34:56 +08002460 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002461 DECODE_PRINTF2("MOV\tAX,[%04x]\n", offset);
Jason Jina63ce952007-07-06 08:34:56 +08002462 }
2463 TRACE_AND_STEP();
2464 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002465 M.x86.R_EAX = fetch_data_long(offset);
Jason Jina63ce952007-07-06 08:34:56 +08002466 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002467 M.x86.R_AX = fetch_data_word(offset);
Jason Jina63ce952007-07-06 08:34:56 +08002468 }
2469 DECODE_CLEAR_SEGOVR();
2470 END_OF_INSTR();
2471}
2472
2473/****************************************************************************
2474REMARKS:
2475Handles opcode 0xa2
2476****************************************************************************/
2477void x86emuOp_mov_M_AL_IMM(u8 X86EMU_UNUSED(op1))
2478{
2479 u16 offset;
2480
2481 START_OF_INSTR();
2482 DECODE_PRINTF("MOV\t");
2483 offset = fetch_word_imm();
2484 DECODE_PRINTF2("[%04x],AL\n", offset);
2485 TRACE_AND_STEP();
2486 store_data_byte(offset, M.x86.R_AL);
2487 DECODE_CLEAR_SEGOVR();
2488 END_OF_INSTR();
2489}
2490
2491/****************************************************************************
2492REMARKS:
2493Handles opcode 0xa3
2494****************************************************************************/
2495void x86emuOp_mov_M_AX_IMM(u8 X86EMU_UNUSED(op1))
2496{
2497 u16 offset;
2498
2499 START_OF_INSTR();
2500 offset = fetch_word_imm();
2501 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002502 DECODE_PRINTF2("MOV\t[%04x],EAX\n", offset);
Jason Jina63ce952007-07-06 08:34:56 +08002503 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002504 DECODE_PRINTF2("MOV\t[%04x],AX\n", offset);
Jason Jina63ce952007-07-06 08:34:56 +08002505 }
2506 TRACE_AND_STEP();
2507 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002508 store_data_long(offset, M.x86.R_EAX);
Jason Jina63ce952007-07-06 08:34:56 +08002509 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002510 store_data_word(offset, M.x86.R_AX);
Jason Jina63ce952007-07-06 08:34:56 +08002511 }
2512 DECODE_CLEAR_SEGOVR();
2513 END_OF_INSTR();
2514}
2515
2516/****************************************************************************
2517REMARKS:
2518Handles opcode 0xa4
2519****************************************************************************/
2520void x86emuOp_movs_byte(u8 X86EMU_UNUSED(op1))
2521{
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002522 u8 val;
Jason Jina63ce952007-07-06 08:34:56 +08002523 u32 count;
2524 int inc;
2525
2526 START_OF_INSTR();
2527 DECODE_PRINTF("MOVS\tBYTE\n");
2528 if (ACCESS_FLAG(F_DF)) /* down */
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002529 inc = -1;
Jason Jina63ce952007-07-06 08:34:56 +08002530 else
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002531 inc = 1;
Jason Jina63ce952007-07-06 08:34:56 +08002532 TRACE_AND_STEP();
2533 count = 1;
2534 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002535 /* dont care whether REPE or REPNE */
2536 /* move them until CX is ZERO. */
2537 count = M.x86.R_CX;
2538 M.x86.R_CX = 0;
2539 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
Jason Jina63ce952007-07-06 08:34:56 +08002540 }
2541 while (count--) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002542 val = fetch_data_byte(M.x86.R_SI);
2543 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, val);
2544 M.x86.R_SI += inc;
2545 M.x86.R_DI += inc;
Jason Jina63ce952007-07-06 08:34:56 +08002546 }
2547 DECODE_CLEAR_SEGOVR();
2548 END_OF_INSTR();
2549}
2550
2551/****************************************************************************
2552REMARKS:
2553Handles opcode 0xa5
2554****************************************************************************/
2555void x86emuOp_movs_word(u8 X86EMU_UNUSED(op1))
2556{
2557 u32 val;
2558 int inc;
2559 u32 count;
2560
2561 START_OF_INSTR();
2562 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002563 DECODE_PRINTF("MOVS\tDWORD\n");
2564 if (ACCESS_FLAG(F_DF)) /* down */
2565 inc = -4;
2566 else
2567 inc = 4;
Jason Jina63ce952007-07-06 08:34:56 +08002568 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002569 DECODE_PRINTF("MOVS\tWORD\n");
2570 if (ACCESS_FLAG(F_DF)) /* down */
2571 inc = -2;
2572 else
2573 inc = 2;
Jason Jina63ce952007-07-06 08:34:56 +08002574 }
2575 TRACE_AND_STEP();
2576 count = 1;
2577 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002578 /* dont care whether REPE or REPNE */
2579 /* move them until CX is ZERO. */
2580 count = M.x86.R_CX;
2581 M.x86.R_CX = 0;
2582 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
Jason Jina63ce952007-07-06 08:34:56 +08002583 }
2584 while (count--) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002585 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2586 val = fetch_data_long(M.x86.R_SI);
2587 store_data_long_abs(M.x86.R_ES, M.x86.R_DI, val);
2588 } else {
2589 val = fetch_data_word(M.x86.R_SI);
2590 store_data_word_abs(M.x86.R_ES, M.x86.R_DI, (u16)val);
2591 }
2592 M.x86.R_SI += inc;
2593 M.x86.R_DI += inc;
Jason Jina63ce952007-07-06 08:34:56 +08002594 }
2595 DECODE_CLEAR_SEGOVR();
2596 END_OF_INSTR();
2597}
2598
2599/****************************************************************************
2600REMARKS:
2601Handles opcode 0xa6
2602****************************************************************************/
2603void x86emuOp_cmps_byte(u8 X86EMU_UNUSED(op1))
2604{
2605 s8 val1, val2;
2606 int inc;
2607
2608 START_OF_INSTR();
2609 DECODE_PRINTF("CMPS\tBYTE\n");
2610 TRACE_AND_STEP();
2611 if (ACCESS_FLAG(F_DF)) /* down */
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002612 inc = -1;
Jason Jina63ce952007-07-06 08:34:56 +08002613 else
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002614 inc = 1;
Jason Jina63ce952007-07-06 08:34:56 +08002615
2616 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002617 /* REPE */
2618 /* move them until CX is ZERO. */
2619 while (M.x86.R_CX != 0) {
2620 val1 = fetch_data_byte(M.x86.R_SI);
2621 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2622 cmp_byte(val1, val2);
2623 M.x86.R_CX -= 1;
2624 M.x86.R_SI += inc;
2625 M.x86.R_DI += inc;
2626 if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && (ACCESS_FLAG(F_ZF) == 0) ) break;
2627 if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2628 }
2629 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
Jason Jina63ce952007-07-06 08:34:56 +08002630 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002631 val1 = fetch_data_byte(M.x86.R_SI);
2632 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2633 cmp_byte(val1, val2);
2634 M.x86.R_SI += inc;
2635 M.x86.R_DI += inc;
Jason Jina63ce952007-07-06 08:34:56 +08002636 }
2637 DECODE_CLEAR_SEGOVR();
2638 END_OF_INSTR();
2639}
2640
2641/****************************************************************************
2642REMARKS:
2643Handles opcode 0xa7
2644****************************************************************************/
2645void x86emuOp_cmps_word(u8 X86EMU_UNUSED(op1))
2646{
2647 u32 val1,val2;
2648 int inc;
2649
2650 START_OF_INSTR();
2651 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002652 DECODE_PRINTF("CMPS\tDWORD\n");
2653 inc = 4;
Jason Jina63ce952007-07-06 08:34:56 +08002654 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002655 DECODE_PRINTF("CMPS\tWORD\n");
2656 inc = 2;
Jason Jina63ce952007-07-06 08:34:56 +08002657 }
2658 if (ACCESS_FLAG(F_DF)) /* down */
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002659 inc = -inc;
Jason Jina63ce952007-07-06 08:34:56 +08002660
2661 TRACE_AND_STEP();
2662 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002663 /* REPE */
2664 /* move them until CX is ZERO. */
2665 while (M.x86.R_CX != 0) {
2666 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2667 val1 = fetch_data_long(M.x86.R_SI);
2668 val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2669 cmp_long(val1, val2);
2670 } else {
2671 val1 = fetch_data_word(M.x86.R_SI);
2672 val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2673 cmp_word((u16)val1, (u16)val2);
2674 }
2675 M.x86.R_CX -= 1;
2676 M.x86.R_SI += inc;
2677 M.x86.R_DI += inc;
2678 if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && ACCESS_FLAG(F_ZF) == 0 ) break;
2679 if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2680 }
2681 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
Jason Jina63ce952007-07-06 08:34:56 +08002682 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002683 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2684 val1 = fetch_data_long(M.x86.R_SI);
2685 val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2686 cmp_long(val1, val2);
2687 } else {
2688 val1 = fetch_data_word(M.x86.R_SI);
2689 val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2690 cmp_word((u16)val1, (u16)val2);
2691 }
2692 M.x86.R_SI += inc;
2693 M.x86.R_DI += inc;
Jason Jina63ce952007-07-06 08:34:56 +08002694 }
2695 DECODE_CLEAR_SEGOVR();
2696 END_OF_INSTR();
2697}
2698
2699/****************************************************************************
2700REMARKS:
2701Handles opcode 0xa8
2702****************************************************************************/
2703void x86emuOp_test_AL_IMM(u8 X86EMU_UNUSED(op1))
2704{
2705 int imm;
2706
2707 START_OF_INSTR();
2708 DECODE_PRINTF("TEST\tAL,");
2709 imm = fetch_byte_imm();
2710 DECODE_PRINTF2("%04x\n", imm);
2711 TRACE_AND_STEP();
2712 test_byte(M.x86.R_AL, (u8)imm);
2713 DECODE_CLEAR_SEGOVR();
2714 END_OF_INSTR();
2715}
2716
2717/****************************************************************************
2718REMARKS:
2719Handles opcode 0xa9
2720****************************************************************************/
2721void x86emuOp_test_AX_IMM(u8 X86EMU_UNUSED(op1))
2722{
2723 u32 srcval;
2724
2725 START_OF_INSTR();
2726 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002727 DECODE_PRINTF("TEST\tEAX,");
2728 srcval = fetch_long_imm();
Jason Jina63ce952007-07-06 08:34:56 +08002729 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002730 DECODE_PRINTF("TEST\tAX,");
2731 srcval = fetch_word_imm();
Jason Jina63ce952007-07-06 08:34:56 +08002732 }
2733 DECODE_PRINTF2("%x\n", srcval);
2734 TRACE_AND_STEP();
2735 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002736 test_long(M.x86.R_EAX, srcval);
Jason Jina63ce952007-07-06 08:34:56 +08002737 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002738 test_word(M.x86.R_AX, (u16)srcval);
Jason Jina63ce952007-07-06 08:34:56 +08002739 }
2740 DECODE_CLEAR_SEGOVR();
2741 END_OF_INSTR();
2742}
2743
2744/****************************************************************************
2745REMARKS:
2746Handles opcode 0xaa
2747****************************************************************************/
2748void x86emuOp_stos_byte(u8 X86EMU_UNUSED(op1))
2749{
2750 int inc;
2751
2752 START_OF_INSTR();
2753 DECODE_PRINTF("STOS\tBYTE\n");
2754 if (ACCESS_FLAG(F_DF)) /* down */
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002755 inc = -1;
Jason Jina63ce952007-07-06 08:34:56 +08002756 else
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002757 inc = 1;
Jason Jina63ce952007-07-06 08:34:56 +08002758 TRACE_AND_STEP();
2759 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002760 /* dont care whether REPE or REPNE */
2761 /* move them until CX is ZERO. */
2762 while (M.x86.R_CX != 0) {
2763 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
2764 M.x86.R_CX -= 1;
2765 M.x86.R_DI += inc;
2766 }
2767 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
Jason Jina63ce952007-07-06 08:34:56 +08002768 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002769 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
2770 M.x86.R_DI += inc;
Jason Jina63ce952007-07-06 08:34:56 +08002771 }
2772 DECODE_CLEAR_SEGOVR();
2773 END_OF_INSTR();
2774}
2775
2776/****************************************************************************
2777REMARKS:
2778Handles opcode 0xab
2779****************************************************************************/
2780void x86emuOp_stos_word(u8 X86EMU_UNUSED(op1))
2781{
2782 int inc;
2783 u32 count;
2784
2785 START_OF_INSTR();
2786 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002787 DECODE_PRINTF("STOS\tDWORD\n");
2788 if (ACCESS_FLAG(F_DF)) /* down */
2789 inc = -4;
2790 else
2791 inc = 4;
Jason Jina63ce952007-07-06 08:34:56 +08002792 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002793 DECODE_PRINTF("STOS\tWORD\n");
2794 if (ACCESS_FLAG(F_DF)) /* down */
2795 inc = -2;
2796 else
2797 inc = 2;
Jason Jina63ce952007-07-06 08:34:56 +08002798 }
2799 TRACE_AND_STEP();
2800 count = 1;
2801 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002802 /* dont care whether REPE or REPNE */
2803 /* move them until CX is ZERO. */
2804 count = M.x86.R_CX;
2805 M.x86.R_CX = 0;
2806 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
Jason Jina63ce952007-07-06 08:34:56 +08002807 }
2808 while (count--) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002809 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2810 store_data_long_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_EAX);
2811 } else {
2812 store_data_word_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AX);
2813 }
2814 M.x86.R_DI += inc;
Jason Jina63ce952007-07-06 08:34:56 +08002815 }
2816 DECODE_CLEAR_SEGOVR();
2817 END_OF_INSTR();
2818}
2819
2820/****************************************************************************
2821REMARKS:
2822Handles opcode 0xac
2823****************************************************************************/
2824void x86emuOp_lods_byte(u8 X86EMU_UNUSED(op1))
2825{
2826 int inc;
2827
2828 START_OF_INSTR();
2829 DECODE_PRINTF("LODS\tBYTE\n");
2830 TRACE_AND_STEP();
2831 if (ACCESS_FLAG(F_DF)) /* down */
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002832 inc = -1;
Jason Jina63ce952007-07-06 08:34:56 +08002833 else
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002834 inc = 1;
Jason Jina63ce952007-07-06 08:34:56 +08002835 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002836 /* dont care whether REPE or REPNE */
2837 /* move them until CX is ZERO. */
2838 while (M.x86.R_CX != 0) {
2839 M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
2840 M.x86.R_CX -= 1;
2841 M.x86.R_SI += inc;
2842 }
2843 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
Jason Jina63ce952007-07-06 08:34:56 +08002844 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002845 M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
2846 M.x86.R_SI += inc;
Jason Jina63ce952007-07-06 08:34:56 +08002847 }
2848 DECODE_CLEAR_SEGOVR();
2849 END_OF_INSTR();
2850}
2851
2852/****************************************************************************
2853REMARKS:
2854Handles opcode 0xad
2855****************************************************************************/
2856void x86emuOp_lods_word(u8 X86EMU_UNUSED(op1))
2857{
2858 int inc;
2859 u32 count;
2860
2861 START_OF_INSTR();
2862 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002863 DECODE_PRINTF("LODS\tDWORD\n");
2864 if (ACCESS_FLAG(F_DF)) /* down */
2865 inc = -4;
2866 else
2867 inc = 4;
Jason Jina63ce952007-07-06 08:34:56 +08002868 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002869 DECODE_PRINTF("LODS\tWORD\n");
2870 if (ACCESS_FLAG(F_DF)) /* down */
2871 inc = -2;
2872 else
2873 inc = 2;
Jason Jina63ce952007-07-06 08:34:56 +08002874 }
2875 TRACE_AND_STEP();
2876 count = 1;
2877 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002878 /* dont care whether REPE or REPNE */
2879 /* move them until CX is ZERO. */
2880 count = M.x86.R_CX;
2881 M.x86.R_CX = 0;
2882 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
Jason Jina63ce952007-07-06 08:34:56 +08002883 }
2884 while (count--) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002885 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2886 M.x86.R_EAX = fetch_data_long(M.x86.R_SI);
2887 } else {
2888 M.x86.R_AX = fetch_data_word(M.x86.R_SI);
2889 }
2890 M.x86.R_SI += inc;
Jason Jina63ce952007-07-06 08:34:56 +08002891 }
2892 DECODE_CLEAR_SEGOVR();
2893 END_OF_INSTR();
2894}
2895
2896/****************************************************************************
2897REMARKS:
2898Handles opcode 0xae
2899****************************************************************************/
2900void x86emuOp_scas_byte(u8 X86EMU_UNUSED(op1))
2901{
2902 s8 val2;
2903 int inc;
2904
2905 START_OF_INSTR();
2906 DECODE_PRINTF("SCAS\tBYTE\n");
2907 TRACE_AND_STEP();
2908 if (ACCESS_FLAG(F_DF)) /* down */
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002909 inc = -1;
Jason Jina63ce952007-07-06 08:34:56 +08002910 else
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002911 inc = 1;
Jason Jina63ce952007-07-06 08:34:56 +08002912 if (M.x86.mode & SYSMODE_PREFIX_REPE) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002913 /* REPE */
2914 /* move them until CX is ZERO. */
2915 while (M.x86.R_CX != 0) {
2916 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2917 cmp_byte(M.x86.R_AL, val2);
2918 M.x86.R_CX -= 1;
2919 M.x86.R_DI += inc;
2920 if (ACCESS_FLAG(F_ZF) == 0)
2921 break;
2922 }
2923 M.x86.mode &= ~SYSMODE_PREFIX_REPE;
Jason Jina63ce952007-07-06 08:34:56 +08002924 } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002925 /* REPNE */
2926 /* move them until CX is ZERO. */
2927 while (M.x86.R_CX != 0) {
2928 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2929 cmp_byte(M.x86.R_AL, val2);
2930 M.x86.R_CX -= 1;
2931 M.x86.R_DI += inc;
2932 if (ACCESS_FLAG(F_ZF))
2933 break; /* zero flag set means equal */
2934 }
2935 M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
Jason Jina63ce952007-07-06 08:34:56 +08002936 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002937 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2938 cmp_byte(M.x86.R_AL, val2);
2939 M.x86.R_DI += inc;
Jason Jina63ce952007-07-06 08:34:56 +08002940 }
2941 DECODE_CLEAR_SEGOVR();
2942 END_OF_INSTR();
2943}
2944
2945/****************************************************************************
2946REMARKS:
2947Handles opcode 0xaf
2948****************************************************************************/
2949void x86emuOp_scas_word(u8 X86EMU_UNUSED(op1))
2950{
2951 int inc;
2952 u32 val;
2953
2954 START_OF_INSTR();
2955 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002956 DECODE_PRINTF("SCAS\tDWORD\n");
2957 if (ACCESS_FLAG(F_DF)) /* down */
2958 inc = -4;
2959 else
2960 inc = 4;
Jason Jina63ce952007-07-06 08:34:56 +08002961 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002962 DECODE_PRINTF("SCAS\tWORD\n");
2963 if (ACCESS_FLAG(F_DF)) /* down */
2964 inc = -2;
2965 else
2966 inc = 2;
Jason Jina63ce952007-07-06 08:34:56 +08002967 }
2968 TRACE_AND_STEP();
2969 if (M.x86.mode & SYSMODE_PREFIX_REPE) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002970 /* REPE */
2971 /* move them until CX is ZERO. */
2972 while (M.x86.R_CX != 0) {
2973 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2974 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2975 cmp_long(M.x86.R_EAX, val);
2976 } else {
2977 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2978 cmp_word(M.x86.R_AX, (u16)val);
2979 }
2980 M.x86.R_CX -= 1;
2981 M.x86.R_DI += inc;
2982 if (ACCESS_FLAG(F_ZF) == 0)
2983 break;
2984 }
2985 M.x86.mode &= ~SYSMODE_PREFIX_REPE;
Jason Jina63ce952007-07-06 08:34:56 +08002986 } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002987 /* REPNE */
2988 /* move them until CX is ZERO. */
2989 while (M.x86.R_CX != 0) {
2990 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2991 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2992 cmp_long(M.x86.R_EAX, val);
2993 } else {
2994 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2995 cmp_word(M.x86.R_AX, (u16)val);
2996 }
2997 M.x86.R_CX -= 1;
2998 M.x86.R_DI += inc;
2999 if (ACCESS_FLAG(F_ZF))
3000 break; /* zero flag set means equal */
3001 }
3002 M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
Jason Jina63ce952007-07-06 08:34:56 +08003003 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003004 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3005 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
3006 cmp_long(M.x86.R_EAX, val);
3007 } else {
3008 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
3009 cmp_word(M.x86.R_AX, (u16)val);
3010 }
3011 M.x86.R_DI += inc;
Jason Jina63ce952007-07-06 08:34:56 +08003012 }
3013 DECODE_CLEAR_SEGOVR();
3014 END_OF_INSTR();
3015}
3016
3017/****************************************************************************
3018REMARKS:
3019Handles opcode 0xb0 - 0xb7
3020****************************************************************************/
3021void x86emuOp_mov_byte_register_IMM(u8 op1)
3022{
3023 u8 imm, *ptr;
3024
3025 START_OF_INSTR();
3026 DECODE_PRINTF("MOV\t");
3027 ptr = DECODE_RM_BYTE_REGISTER(op1 & 0x7);
3028 DECODE_PRINTF(",");
3029 imm = fetch_byte_imm();
3030 DECODE_PRINTF2("%x\n", imm);
3031 TRACE_AND_STEP();
3032 *ptr = imm;
3033 DECODE_CLEAR_SEGOVR();
3034 END_OF_INSTR();
3035}
3036
3037/****************************************************************************
3038REMARKS:
3039Handles opcode 0xb8 - 0xbf
3040****************************************************************************/
3041void x86emuOp_mov_word_register_IMM(u8 X86EMU_UNUSED(op1))
3042{
3043 u32 srcval;
3044
3045 op1 &= 0x7;
3046
3047 START_OF_INSTR();
3048 DECODE_PRINTF("MOV\t");
3049 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003050 u32 *reg32;
3051 reg32 = DECODE_RM_LONG_REGISTER(op1);
3052 srcval = fetch_long_imm();
3053 DECODE_PRINTF2(",%x\n", srcval);
3054 TRACE_AND_STEP();
3055 *reg32 = srcval;
Jason Jina63ce952007-07-06 08:34:56 +08003056 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003057 u16 *reg16;
3058 reg16 = DECODE_RM_WORD_REGISTER(op1);
3059 srcval = fetch_word_imm();
3060 DECODE_PRINTF2(",%x\n", srcval);
3061 TRACE_AND_STEP();
3062 *reg16 = (u16)srcval;
Jason Jina63ce952007-07-06 08:34:56 +08003063 }
3064 DECODE_CLEAR_SEGOVR();
3065 END_OF_INSTR();
3066}
3067
3068/****************************************************************************
3069REMARKS:
3070Handles opcode 0xc0
3071****************************************************************************/
3072void x86emuOp_opcC0_byte_RM_MEM(u8 X86EMU_UNUSED(op1))
3073{
3074 int mod, rl, rh;
3075 u8 *destreg;
3076 uint destoffset;
3077 u8 destval;
3078 u8 amt;
3079
3080 /*
3081 * Yet another weirdo special case instruction format. Part of
3082 * the opcode held below in "RH". Doubly nested case would
3083 * result, except that the decoded instruction
3084 */
3085 START_OF_INSTR();
3086 FETCH_DECODE_MODRM(mod, rh, rl);
3087#ifdef DEBUG
3088 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003089 /* XXX DECODE_PRINTF may be changed to something more
3090 general, so that it is important to leave the strings
3091 in the same format, even though the result is that the
3092 above test is done twice. */
Jason Jina63ce952007-07-06 08:34:56 +08003093
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003094 switch (rh) {
3095 case 0:
3096 DECODE_PRINTF("ROL\t");
3097 break;
3098 case 1:
3099 DECODE_PRINTF("ROR\t");
3100 break;
3101 case 2:
3102 DECODE_PRINTF("RCL\t");
3103 break;
3104 case 3:
3105 DECODE_PRINTF("RCR\t");
3106 break;
3107 case 4:
3108 DECODE_PRINTF("SHL\t");
3109 break;
3110 case 5:
3111 DECODE_PRINTF("SHR\t");
3112 break;
3113 case 6:
3114 DECODE_PRINTF("SAL\t");
3115 break;
3116 case 7:
3117 DECODE_PRINTF("SAR\t");
3118 break;
3119 }
Jason Jina63ce952007-07-06 08:34:56 +08003120 }
3121#endif
3122 /* know operation, decode the mod byte to find the addressing
3123 mode. */
3124 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003125 DECODE_PRINTF("BYTE PTR ");
3126 destoffset = decode_rmXX_address(mod, rl);
3127 amt = fetch_byte_imm();
3128 DECODE_PRINTF2(",%x\n", amt);
3129 destval = fetch_data_byte(destoffset);
3130 TRACE_AND_STEP();
3131 destval = (*opcD0_byte_operation[rh]) (destval, amt);
3132 store_data_byte(destoffset, destval);
3133 } else { /* register to register */
3134 destreg = DECODE_RM_BYTE_REGISTER(rl);
3135 amt = fetch_byte_imm();
3136 DECODE_PRINTF2(",%x\n", amt);
3137 TRACE_AND_STEP();
3138 destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3139 *destreg = destval;
Jason Jina63ce952007-07-06 08:34:56 +08003140 }
3141 DECODE_CLEAR_SEGOVR();
3142 END_OF_INSTR();
3143}
3144
3145/****************************************************************************
3146REMARKS:
3147Handles opcode 0xc1
3148****************************************************************************/
3149void x86emuOp_opcC1_word_RM_MEM(u8 X86EMU_UNUSED(op1))
3150{
3151 int mod, rl, rh;
3152 uint destoffset;
3153 u8 amt;
3154
3155 /*
3156 * Yet another weirdo special case instruction format. Part of
3157 * the opcode held below in "RH". Doubly nested case would
3158 * result, except that the decoded instruction
3159 */
3160 START_OF_INSTR();
3161 FETCH_DECODE_MODRM(mod, rh, rl);
3162#ifdef DEBUG
3163 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003164 /* XXX DECODE_PRINTF may be changed to something more
3165 general, so that it is important to leave the strings
3166 in the same format, even though the result is that the
3167 above test is done twice. */
Jason Jina63ce952007-07-06 08:34:56 +08003168
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003169 switch (rh) {
3170 case 0:
3171 DECODE_PRINTF("ROL\t");
3172 break;
3173 case 1:
3174 DECODE_PRINTF("ROR\t");
3175 break;
3176 case 2:
3177 DECODE_PRINTF("RCL\t");
3178 break;
3179 case 3:
3180 DECODE_PRINTF("RCR\t");
3181 break;
3182 case 4:
3183 DECODE_PRINTF("SHL\t");
3184 break;
3185 case 5:
3186 DECODE_PRINTF("SHR\t");
3187 break;
3188 case 6:
3189 DECODE_PRINTF("SAL\t");
3190 break;
3191 case 7:
3192 DECODE_PRINTF("SAR\t");
3193 break;
3194 }
Jason Jina63ce952007-07-06 08:34:56 +08003195 }
3196#endif
3197 /* know operation, decode the mod byte to find the addressing
3198 mode. */
3199 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003200 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3201 u32 destval;
Jason Jina63ce952007-07-06 08:34:56 +08003202
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003203 DECODE_PRINTF("DWORD PTR ");
3204 destoffset = decode_rmXX_address(mod, rl);
3205 amt = fetch_byte_imm();
3206 DECODE_PRINTF2(",%x\n", amt);
3207 destval = fetch_data_long(destoffset);
3208 TRACE_AND_STEP();
3209 destval = (*opcD1_long_operation[rh]) (destval, amt);
3210 store_data_long(destoffset, destval);
3211 } else {
3212 u16 destval;
Jason Jina63ce952007-07-06 08:34:56 +08003213
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003214 DECODE_PRINTF("WORD PTR ");
3215 destoffset = decode_rmXX_address(mod, rl);
3216 amt = fetch_byte_imm();
3217 DECODE_PRINTF2(",%x\n", amt);
3218 destval = fetch_data_word(destoffset);
3219 TRACE_AND_STEP();
3220 destval = (*opcD1_word_operation[rh]) (destval, amt);
3221 store_data_word(destoffset, destval);
3222 }
3223 } else { /* register to register */
3224 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3225 u32 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08003226
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003227 destreg = DECODE_RM_LONG_REGISTER(rl);
3228 amt = fetch_byte_imm();
3229 DECODE_PRINTF2(",%x\n", amt);
3230 TRACE_AND_STEP();
3231 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3232 } else {
3233 u16 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08003234
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003235 destreg = DECODE_RM_WORD_REGISTER(rl);
3236 amt = fetch_byte_imm();
3237 DECODE_PRINTF2(",%x\n", amt);
3238 TRACE_AND_STEP();
3239 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
3240 }
Jason Jina63ce952007-07-06 08:34:56 +08003241 }
3242 DECODE_CLEAR_SEGOVR();
3243 END_OF_INSTR();
3244}
3245
3246/****************************************************************************
3247REMARKS:
3248Handles opcode 0xc2
3249****************************************************************************/
3250void x86emuOp_ret_near_IMM(u8 X86EMU_UNUSED(op1))
3251{
3252 u16 imm;
3253
3254 START_OF_INSTR();
3255 DECODE_PRINTF("RET\t");
3256 imm = fetch_word_imm();
3257 DECODE_PRINTF2("%x\n", imm);
3258 RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
3259 TRACE_AND_STEP();
3260 M.x86.R_IP = pop_word();
3261 M.x86.R_SP += imm;
3262 DECODE_CLEAR_SEGOVR();
3263 END_OF_INSTR();
3264}
3265
3266/****************************************************************************
3267REMARKS:
3268Handles opcode 0xc3
3269****************************************************************************/
3270void x86emuOp_ret_near(u8 X86EMU_UNUSED(op1))
3271{
3272 START_OF_INSTR();
3273 DECODE_PRINTF("RET\n");
3274 RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
3275 TRACE_AND_STEP();
3276 M.x86.R_IP = pop_word();
3277 DECODE_CLEAR_SEGOVR();
3278 END_OF_INSTR();
3279}
3280
3281/****************************************************************************
3282REMARKS:
3283Handles opcode 0xc4
3284****************************************************************************/
3285void x86emuOp_les_R_IMM(u8 X86EMU_UNUSED(op1))
3286{
3287 int mod, rh, rl;
3288 u16 *dstreg;
3289 uint srcoffset;
3290
3291 START_OF_INSTR();
3292 DECODE_PRINTF("LES\t");
3293 FETCH_DECODE_MODRM(mod, rh, rl);
3294 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003295 dstreg = DECODE_RM_WORD_REGISTER(rh);
3296 DECODE_PRINTF(",");
3297 srcoffset = decode_rmXX_address(mod, rl);
3298 DECODE_PRINTF("\n");
3299 TRACE_AND_STEP();
3300 *dstreg = fetch_data_word(srcoffset);
3301 M.x86.R_ES = fetch_data_word(srcoffset + 2);
Jason Jina63ce952007-07-06 08:34:56 +08003302 }
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003303 /* else UNDEFINED! register to register */
Jason Jina63ce952007-07-06 08:34:56 +08003304
3305 DECODE_CLEAR_SEGOVR();
3306 END_OF_INSTR();
3307}
3308
3309/****************************************************************************
3310REMARKS:
3311Handles opcode 0xc5
3312****************************************************************************/
3313void x86emuOp_lds_R_IMM(u8 X86EMU_UNUSED(op1))
3314{
3315 int mod, rh, rl;
3316 u16 *dstreg;
3317 uint srcoffset;
3318
3319 START_OF_INSTR();
3320 DECODE_PRINTF("LDS\t");
3321 FETCH_DECODE_MODRM(mod, rh, rl);
3322 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003323 dstreg = DECODE_RM_WORD_REGISTER(rh);
3324 DECODE_PRINTF(",");
3325 srcoffset = decode_rmXX_address(mod, rl);
3326 DECODE_PRINTF("\n");
3327 TRACE_AND_STEP();
3328 *dstreg = fetch_data_word(srcoffset);
3329 M.x86.R_DS = fetch_data_word(srcoffset + 2);
Jason Jina63ce952007-07-06 08:34:56 +08003330 }
3331 /* else UNDEFINED! */
3332 DECODE_CLEAR_SEGOVR();
3333 END_OF_INSTR();
3334}
3335
3336/****************************************************************************
3337REMARKS:
3338Handles opcode 0xc6
3339****************************************************************************/
3340void x86emuOp_mov_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
3341{
3342 int mod, rl, rh;
3343 u8 *destreg;
3344 uint destoffset;
3345 u8 imm;
3346
3347 START_OF_INSTR();
3348 DECODE_PRINTF("MOV\t");
3349 FETCH_DECODE_MODRM(mod, rh, rl);
3350 if (rh != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003351 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE c6\n");
3352 HALT_SYS();
Jason Jina63ce952007-07-06 08:34:56 +08003353 }
3354 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003355 DECODE_PRINTF("BYTE PTR ");
3356 destoffset = decode_rmXX_address(mod, rl);
3357 imm = fetch_byte_imm();
3358 DECODE_PRINTF2(",%2x\n", imm);
3359 TRACE_AND_STEP();
3360 store_data_byte(destoffset, imm);
3361 } else { /* register to register */
3362 destreg = DECODE_RM_BYTE_REGISTER(rl);
3363 imm = fetch_byte_imm();
3364 DECODE_PRINTF2(",%2x\n", imm);
3365 TRACE_AND_STEP();
3366 *destreg = imm;
Jason Jina63ce952007-07-06 08:34:56 +08003367 }
3368 DECODE_CLEAR_SEGOVR();
3369 END_OF_INSTR();
3370}
3371
3372/****************************************************************************
3373REMARKS:
3374Handles opcode 0xc7
3375****************************************************************************/
3376void x86emuOp_mov_word_RM_IMM(u8 X86EMU_UNUSED(op1))
3377{
3378 int mod, rl, rh;
3379 uint destoffset;
3380
3381 START_OF_INSTR();
3382 DECODE_PRINTF("MOV\t");
3383 FETCH_DECODE_MODRM(mod, rh, rl);
3384 if (rh != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003385 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
3386 HALT_SYS();
Jason Jina63ce952007-07-06 08:34:56 +08003387 }
3388 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003389 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3390 u32 imm;
Jason Jina63ce952007-07-06 08:34:56 +08003391
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003392 DECODE_PRINTF("DWORD PTR ");
3393 destoffset = decode_rmXX_address(mod, rl);
3394 imm = fetch_long_imm();
3395 DECODE_PRINTF2(",%x\n", imm);
3396 TRACE_AND_STEP();
3397 store_data_long(destoffset, imm);
3398 } else {
3399 u16 imm;
Jason Jina63ce952007-07-06 08:34:56 +08003400
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003401 DECODE_PRINTF("WORD PTR ");
3402 destoffset = decode_rmXX_address(mod, rl);
3403 imm = fetch_word_imm();
3404 DECODE_PRINTF2(",%x\n", imm);
3405 TRACE_AND_STEP();
3406 store_data_word(destoffset, imm);
3407 }
3408 } else { /* register to register */
3409 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Jason Jina63ce952007-07-06 08:34:56 +08003410 u32 *destreg;
3411 u32 imm;
3412
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003413 destreg = DECODE_RM_LONG_REGISTER(rl);
3414 imm = fetch_long_imm();
3415 DECODE_PRINTF2(",%x\n", imm);
3416 TRACE_AND_STEP();
3417 *destreg = imm;
3418 } else {
Jason Jina63ce952007-07-06 08:34:56 +08003419 u16 *destreg;
3420 u16 imm;
3421
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003422 destreg = DECODE_RM_WORD_REGISTER(rl);
3423 imm = fetch_word_imm();
3424 DECODE_PRINTF2(",%x\n", imm);
3425 TRACE_AND_STEP();
3426 *destreg = imm;
3427 }
Jason Jina63ce952007-07-06 08:34:56 +08003428 }
3429 DECODE_CLEAR_SEGOVR();
3430 END_OF_INSTR();
3431}
3432
3433/****************************************************************************
3434REMARKS:
3435Handles opcode 0xc8
3436****************************************************************************/
3437void x86emuOp_enter(u8 X86EMU_UNUSED(op1))
3438{
3439 u16 local,frame_pointer;
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003440 u8 nesting;
Jason Jina63ce952007-07-06 08:34:56 +08003441 int i;
3442
3443 START_OF_INSTR();
3444 local = fetch_word_imm();
3445 nesting = fetch_byte_imm();
3446 DECODE_PRINTF2("ENTER %x\n", local);
3447 DECODE_PRINTF2(",%x\n", nesting);
3448 TRACE_AND_STEP();
3449 push_word(M.x86.R_BP);
3450 frame_pointer = M.x86.R_SP;
3451 if (nesting > 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003452 for (i = 1; i < nesting; i++) {
3453 M.x86.R_BP -= 2;
3454 push_word(fetch_data_word_abs(M.x86.R_SS, M.x86.R_BP));
3455 }
3456 push_word(frame_pointer);
3457 }
Jason Jina63ce952007-07-06 08:34:56 +08003458 M.x86.R_BP = frame_pointer;
3459 M.x86.R_SP = (u16)(M.x86.R_SP - local);
3460 DECODE_CLEAR_SEGOVR();
3461 END_OF_INSTR();
3462}
3463
3464/****************************************************************************
3465REMARKS:
3466Handles opcode 0xc9
3467****************************************************************************/
3468void x86emuOp_leave(u8 X86EMU_UNUSED(op1))
3469{
3470 START_OF_INSTR();
3471 DECODE_PRINTF("LEAVE\n");
3472 TRACE_AND_STEP();
3473 M.x86.R_SP = M.x86.R_BP;
3474 M.x86.R_BP = pop_word();
3475 DECODE_CLEAR_SEGOVR();
3476 END_OF_INSTR();
3477}
3478
3479/****************************************************************************
3480REMARKS:
3481Handles opcode 0xca
3482****************************************************************************/
3483void x86emuOp_ret_far_IMM(u8 X86EMU_UNUSED(op1))
3484{
3485 u16 imm;
3486
3487 START_OF_INSTR();
3488 DECODE_PRINTF("RETF\t");
3489 imm = fetch_word_imm();
3490 DECODE_PRINTF2("%x\n", imm);
3491 RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
3492 TRACE_AND_STEP();
3493 M.x86.R_IP = pop_word();
3494 M.x86.R_CS = pop_word();
3495 M.x86.R_SP += imm;
3496 DECODE_CLEAR_SEGOVR();
3497 END_OF_INSTR();
3498}
3499
3500/****************************************************************************
3501REMARKS:
3502Handles opcode 0xcb
3503****************************************************************************/
3504void x86emuOp_ret_far(u8 X86EMU_UNUSED(op1))
3505{
3506 START_OF_INSTR();
3507 DECODE_PRINTF("RETF\n");
3508 RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
3509 TRACE_AND_STEP();
3510 M.x86.R_IP = pop_word();
3511 M.x86.R_CS = pop_word();
3512 DECODE_CLEAR_SEGOVR();
3513 END_OF_INSTR();
3514}
3515
3516/****************************************************************************
3517REMARKS:
3518Handles opcode 0xcc
3519****************************************************************************/
3520void x86emuOp_int3(u8 X86EMU_UNUSED(op1))
3521{
3522 u16 tmp;
3523
3524 START_OF_INSTR();
3525 DECODE_PRINTF("INT 3\n");
3526 tmp = (u16) mem_access_word(3 * 4 + 2);
3527 /* access the segment register */
3528 TRACE_AND_STEP();
3529 if (_X86EMU_intrTab[3]) {
3530 (*_X86EMU_intrTab[3])(3);
3531 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003532 push_word((u16)M.x86.R_FLG);
3533 CLEAR_FLAG(F_IF);
3534 CLEAR_FLAG(F_TF);
3535 push_word(M.x86.R_CS);
3536 M.x86.R_CS = mem_access_word(3 * 4 + 2);
3537 push_word(M.x86.R_IP);
3538 M.x86.R_IP = mem_access_word(3 * 4);
Jason Jina63ce952007-07-06 08:34:56 +08003539 }
3540 DECODE_CLEAR_SEGOVR();
3541 END_OF_INSTR();
3542}
3543
3544/****************************************************************************
3545REMARKS:
3546Handles opcode 0xcd
3547****************************************************************************/
3548void x86emuOp_int_IMM(u8 X86EMU_UNUSED(op1))
3549{
3550 u16 tmp;
3551 u8 intnum;
3552
3553 START_OF_INSTR();
3554 DECODE_PRINTF("INT\t");
3555 intnum = fetch_byte_imm();
3556 DECODE_PRINTF2("%x\n", intnum);
3557 tmp = mem_access_word(intnum * 4 + 2);
3558 TRACE_AND_STEP();
3559 if (_X86EMU_intrTab[intnum]) {
3560 (*_X86EMU_intrTab[intnum])(intnum);
3561 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003562 push_word((u16)M.x86.R_FLG);
3563 CLEAR_FLAG(F_IF);
3564 CLEAR_FLAG(F_TF);
3565 push_word(M.x86.R_CS);
3566 M.x86.R_CS = mem_access_word(intnum * 4 + 2);
3567 push_word(M.x86.R_IP);
3568 M.x86.R_IP = mem_access_word(intnum * 4);
Jason Jina63ce952007-07-06 08:34:56 +08003569 }
3570 DECODE_CLEAR_SEGOVR();
3571 END_OF_INSTR();
3572}
3573
3574/****************************************************************************
3575REMARKS:
3576Handles opcode 0xce
3577****************************************************************************/
3578void x86emuOp_into(u8 X86EMU_UNUSED(op1))
3579{
3580 u16 tmp;
3581
3582 START_OF_INSTR();
3583 DECODE_PRINTF("INTO\n");
3584 TRACE_AND_STEP();
3585 if (ACCESS_FLAG(F_OF)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003586 tmp = mem_access_word(4 * 4 + 2);
Jason Jina63ce952007-07-06 08:34:56 +08003587 if (_X86EMU_intrTab[4]) {
3588 (*_X86EMU_intrTab[4])(4);
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003589 } else {
3590 push_word((u16)M.x86.R_FLG);
3591 CLEAR_FLAG(F_IF);
3592 CLEAR_FLAG(F_TF);
3593 push_word(M.x86.R_CS);
3594 M.x86.R_CS = mem_access_word(4 * 4 + 2);
3595 push_word(M.x86.R_IP);
3596 M.x86.R_IP = mem_access_word(4 * 4);
3597 }
Jason Jina63ce952007-07-06 08:34:56 +08003598 }
3599 DECODE_CLEAR_SEGOVR();
3600 END_OF_INSTR();
3601}
3602
3603/****************************************************************************
3604REMARKS:
3605Handles opcode 0xcf
3606****************************************************************************/
3607void x86emuOp_iret(u8 X86EMU_UNUSED(op1))
3608{
3609 START_OF_INSTR();
3610 DECODE_PRINTF("IRET\n");
3611
3612 TRACE_AND_STEP();
3613
3614 M.x86.R_IP = pop_word();
3615 M.x86.R_CS = pop_word();
3616 M.x86.R_FLG = pop_word();
3617 DECODE_CLEAR_SEGOVR();
3618 END_OF_INSTR();
3619}
3620
3621/****************************************************************************
3622REMARKS:
3623Handles opcode 0xd0
3624****************************************************************************/
3625void x86emuOp_opcD0_byte_RM_1(u8 X86EMU_UNUSED(op1))
3626{
3627 int mod, rl, rh;
3628 u8 *destreg;
3629 uint destoffset;
3630 u8 destval;
3631
3632 /*
3633 * Yet another weirdo special case instruction format. Part of
3634 * the opcode held below in "RH". Doubly nested case would
3635 * result, except that the decoded instruction
3636 */
3637 START_OF_INSTR();
3638 FETCH_DECODE_MODRM(mod, rh, rl);
3639#ifdef DEBUG
3640 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003641 /* XXX DECODE_PRINTF may be changed to something more
3642 general, so that it is important to leave the strings
3643 in the same format, even though the result is that the
3644 above test is done twice. */
3645 switch (rh) {
3646 case 0:
3647 DECODE_PRINTF("ROL\t");
3648 break;
3649 case 1:
3650 DECODE_PRINTF("ROR\t");
3651 break;
3652 case 2:
3653 DECODE_PRINTF("RCL\t");
3654 break;
3655 case 3:
3656 DECODE_PRINTF("RCR\t");
3657 break;
3658 case 4:
3659 DECODE_PRINTF("SHL\t");
3660 break;
3661 case 5:
3662 DECODE_PRINTF("SHR\t");
3663 break;
3664 case 6:
3665 DECODE_PRINTF("SAL\t");
3666 break;
3667 case 7:
3668 DECODE_PRINTF("SAR\t");
3669 break;
3670 }
Jason Jina63ce952007-07-06 08:34:56 +08003671 }
3672#endif
3673 /* know operation, decode the mod byte to find the addressing
3674 mode. */
3675 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003676 DECODE_PRINTF("BYTE PTR ");
3677 destoffset = decode_rmXX_address(mod, rl);
3678 DECODE_PRINTF(",1\n");
3679 destval = fetch_data_byte(destoffset);
3680 TRACE_AND_STEP();
3681 destval = (*opcD0_byte_operation[rh]) (destval, 1);
3682 store_data_byte(destoffset, destval);
3683 } else { /* register to register */
3684 destreg = DECODE_RM_BYTE_REGISTER(rl);
3685 DECODE_PRINTF(",1\n");
3686 TRACE_AND_STEP();
3687 destval = (*opcD0_byte_operation[rh]) (*destreg, 1);
3688 *destreg = destval;
Jason Jina63ce952007-07-06 08:34:56 +08003689 }
3690 DECODE_CLEAR_SEGOVR();
3691 END_OF_INSTR();
3692}
3693
3694/****************************************************************************
3695REMARKS:
3696Handles opcode 0xd1
3697****************************************************************************/
3698void x86emuOp_opcD1_word_RM_1(u8 X86EMU_UNUSED(op1))
3699{
3700 int mod, rl, rh;
3701 uint destoffset;
3702
3703 /*
3704 * Yet another weirdo special case instruction format. Part of
3705 * the opcode held below in "RH". Doubly nested case would
3706 * result, except that the decoded instruction
3707 */
3708 START_OF_INSTR();
3709 FETCH_DECODE_MODRM(mod, rh, rl);
3710#ifdef DEBUG
3711 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003712 /* XXX DECODE_PRINTF may be changed to something more
3713 general, so that it is important to leave the strings
3714 in the same format, even though the result is that the
3715 above test is done twice. */
3716 switch (rh) {
3717 case 0:
3718 DECODE_PRINTF("ROL\t");
3719 break;
3720 case 1:
3721 DECODE_PRINTF("ROR\t");
3722 break;
3723 case 2:
3724 DECODE_PRINTF("RCL\t");
3725 break;
3726 case 3:
3727 DECODE_PRINTF("RCR\t");
3728 break;
3729 case 4:
3730 DECODE_PRINTF("SHL\t");
3731 break;
3732 case 5:
3733 DECODE_PRINTF("SHR\t");
3734 break;
3735 case 6:
3736 DECODE_PRINTF("SAL\t");
3737 break;
3738 case 7:
3739 DECODE_PRINTF("SAR\t");
3740 break;
3741 }
Jason Jina63ce952007-07-06 08:34:56 +08003742 }
3743#endif
3744 /* know operation, decode the mod byte to find the addressing
3745 mode. */
3746 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003747 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3748 u32 destval;
Jason Jina63ce952007-07-06 08:34:56 +08003749
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003750 DECODE_PRINTF("DWORD PTR ");
3751 destoffset = decode_rmXX_address(mod, rl);
3752 DECODE_PRINTF(",1\n");
3753 destval = fetch_data_long(destoffset);
3754 TRACE_AND_STEP();
3755 destval = (*opcD1_long_operation[rh]) (destval, 1);
3756 store_data_long(destoffset, destval);
3757 } else {
3758 u16 destval;
Jason Jina63ce952007-07-06 08:34:56 +08003759
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003760 DECODE_PRINTF("WORD PTR ");
3761 destoffset = decode_rmXX_address(mod, rl);
3762 DECODE_PRINTF(",1\n");
3763 destval = fetch_data_word(destoffset);
3764 TRACE_AND_STEP();
3765 destval = (*opcD1_word_operation[rh]) (destval, 1);
3766 store_data_word(destoffset, destval);
3767 }
3768 } else { /* register to register */
3769 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Jason Jina63ce952007-07-06 08:34:56 +08003770 u32 destval;
3771 u32 *destreg;
3772
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003773 destreg = DECODE_RM_LONG_REGISTER(rl);
3774 DECODE_PRINTF(",1\n");
3775 TRACE_AND_STEP();
3776 destval = (*opcD1_long_operation[rh]) (*destreg, 1);
3777 *destreg = destval;
3778 } else {
Jason Jina63ce952007-07-06 08:34:56 +08003779 u16 destval;
3780 u16 *destreg;
3781
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003782 destreg = DECODE_RM_WORD_REGISTER(rl);
3783 DECODE_PRINTF(",1\n");
3784 TRACE_AND_STEP();
3785 destval = (*opcD1_word_operation[rh]) (*destreg, 1);
3786 *destreg = destval;
3787 }
Jason Jina63ce952007-07-06 08:34:56 +08003788 }
3789 DECODE_CLEAR_SEGOVR();
3790 END_OF_INSTR();
3791}
3792
3793/****************************************************************************
3794REMARKS:
3795Handles opcode 0xd2
3796****************************************************************************/
3797void x86emuOp_opcD2_byte_RM_CL(u8 X86EMU_UNUSED(op1))
3798{
3799 int mod, rl, rh;
3800 u8 *destreg;
3801 uint destoffset;
3802 u8 destval;
3803 u8 amt;
3804
3805 /*
3806 * Yet another weirdo special case instruction format. Part of
3807 * the opcode held below in "RH". Doubly nested case would
3808 * result, except that the decoded instruction
3809 */
3810 START_OF_INSTR();
3811 FETCH_DECODE_MODRM(mod, rh, rl);
3812#ifdef DEBUG
3813 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003814 /* XXX DECODE_PRINTF may be changed to something more
3815 general, so that it is important to leave the strings
3816 in the same format, even though the result is that the
3817 above test is done twice. */
3818 switch (rh) {
3819 case 0:
3820 DECODE_PRINTF("ROL\t");
3821 break;
3822 case 1:
3823 DECODE_PRINTF("ROR\t");
3824 break;
3825 case 2:
3826 DECODE_PRINTF("RCL\t");
3827 break;
3828 case 3:
3829 DECODE_PRINTF("RCR\t");
3830 break;
3831 case 4:
3832 DECODE_PRINTF("SHL\t");
3833 break;
3834 case 5:
3835 DECODE_PRINTF("SHR\t");
3836 break;
3837 case 6:
3838 DECODE_PRINTF("SAL\t");
3839 break;
3840 case 7:
3841 DECODE_PRINTF("SAR\t");
3842 break;
3843 }
Jason Jina63ce952007-07-06 08:34:56 +08003844 }
3845#endif
3846 /* know operation, decode the mod byte to find the addressing
3847 mode. */
3848 amt = M.x86.R_CL;
3849 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003850 DECODE_PRINTF("BYTE PTR ");
3851 destoffset = decode_rmXX_address(mod, rl);
3852 DECODE_PRINTF(",CL\n");
3853 destval = fetch_data_byte(destoffset);
3854 TRACE_AND_STEP();
3855 destval = (*opcD0_byte_operation[rh]) (destval, amt);
3856 store_data_byte(destoffset, destval);
3857 } else { /* register to register */
3858 destreg = DECODE_RM_BYTE_REGISTER(rl);
3859 DECODE_PRINTF(",CL\n");
3860 TRACE_AND_STEP();
3861 destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3862 *destreg = destval;
Jason Jina63ce952007-07-06 08:34:56 +08003863 }
3864 DECODE_CLEAR_SEGOVR();
3865 END_OF_INSTR();
3866}
3867
3868/****************************************************************************
3869REMARKS:
3870Handles opcode 0xd3
3871****************************************************************************/
3872void x86emuOp_opcD3_word_RM_CL(u8 X86EMU_UNUSED(op1))
3873{
3874 int mod, rl, rh;
3875 uint destoffset;
3876 u8 amt;
3877
3878 /*
3879 * Yet another weirdo special case instruction format. Part of
3880 * the opcode held below in "RH". Doubly nested case would
3881 * result, except that the decoded instruction
3882 */
3883 START_OF_INSTR();
3884 FETCH_DECODE_MODRM(mod, rh, rl);
3885#ifdef DEBUG
3886 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003887 /* XXX DECODE_PRINTF may be changed to something more
3888 general, so that it is important to leave the strings
3889 in the same format, even though the result is that the
3890 above test is done twice. */
3891 switch (rh) {
3892 case 0:
3893 DECODE_PRINTF("ROL\t");
3894 break;
3895 case 1:
3896 DECODE_PRINTF("ROR\t");
3897 break;
3898 case 2:
3899 DECODE_PRINTF("RCL\t");
3900 break;
3901 case 3:
3902 DECODE_PRINTF("RCR\t");
3903 break;
3904 case 4:
3905 DECODE_PRINTF("SHL\t");
3906 break;
3907 case 5:
3908 DECODE_PRINTF("SHR\t");
3909 break;
3910 case 6:
3911 DECODE_PRINTF("SAL\t");
3912 break;
3913 case 7:
3914 DECODE_PRINTF("SAR\t");
3915 break;
3916 }
Jason Jina63ce952007-07-06 08:34:56 +08003917 }
3918#endif
3919 /* know operation, decode the mod byte to find the addressing
3920 mode. */
3921 amt = M.x86.R_CL;
3922 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003923 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3924 u32 destval;
Jason Jina63ce952007-07-06 08:34:56 +08003925
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003926 DECODE_PRINTF("DWORD PTR ");
3927 destoffset = decode_rmXX_address(mod, rl);
3928 DECODE_PRINTF(",CL\n");
3929 destval = fetch_data_long(destoffset);
3930 TRACE_AND_STEP();
3931 destval = (*opcD1_long_operation[rh]) (destval, amt);
3932 store_data_long(destoffset, destval);
3933 } else {
3934 u16 destval;
Jason Jina63ce952007-07-06 08:34:56 +08003935
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003936 DECODE_PRINTF("WORD PTR ");
3937 destoffset = decode_rmXX_address(mod, rl);
3938 DECODE_PRINTF(",CL\n");
3939 destval = fetch_data_word(destoffset);
3940 TRACE_AND_STEP();
3941 destval = (*opcD1_word_operation[rh]) (destval, amt);
3942 store_data_word(destoffset, destval);
3943 }
3944 } else { /* register to register */
3945 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3946 u32 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08003947
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003948 destreg = DECODE_RM_LONG_REGISTER(rl);
3949 DECODE_PRINTF(",CL\n");
3950 TRACE_AND_STEP();
3951 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3952 } else {
3953 u16 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08003954
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003955 destreg = DECODE_RM_WORD_REGISTER(rl);
3956 DECODE_PRINTF(",CL\n");
3957 TRACE_AND_STEP();
3958 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
3959 }
Jason Jina63ce952007-07-06 08:34:56 +08003960 }
3961 DECODE_CLEAR_SEGOVR();
3962 END_OF_INSTR();
3963}
3964
3965/****************************************************************************
3966REMARKS:
3967Handles opcode 0xd4
3968****************************************************************************/
3969void x86emuOp_aam(u8 X86EMU_UNUSED(op1))
3970{
3971 u8 a;
3972
3973 START_OF_INSTR();
3974 DECODE_PRINTF("AAM\n");
3975 a = fetch_byte_imm(); /* this is a stupid encoding. */
3976 if (a != 10) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003977 DECODE_PRINTF("ERROR DECODING AAM\n");
3978 TRACE_REGS();
3979 HALT_SYS();
Jason Jina63ce952007-07-06 08:34:56 +08003980 }
3981 TRACE_AND_STEP();
3982 /* note the type change here --- returning AL and AH in AX. */
3983 M.x86.R_AX = aam_word(M.x86.R_AL);
3984 DECODE_CLEAR_SEGOVR();
3985 END_OF_INSTR();
3986}
3987
3988/****************************************************************************
3989REMARKS:
3990Handles opcode 0xd5
3991****************************************************************************/
3992void x86emuOp_aad(u8 X86EMU_UNUSED(op1))
3993{
3994 u8 a;
3995
3996 START_OF_INSTR();
3997 DECODE_PRINTF("AAD\n");
3998 a = fetch_byte_imm();
3999 TRACE_AND_STEP();
4000 M.x86.R_AX = aad_word(M.x86.R_AX);
4001 DECODE_CLEAR_SEGOVR();
4002 END_OF_INSTR();
4003}
4004
4005/* opcode 0xd6 ILLEGAL OPCODE */
4006
4007/****************************************************************************
4008REMARKS:
4009Handles opcode 0xd7
4010****************************************************************************/
4011void x86emuOp_xlat(u8 X86EMU_UNUSED(op1))
4012{
4013 u16 addr;
4014
4015 START_OF_INSTR();
4016 DECODE_PRINTF("XLAT\n");
4017 TRACE_AND_STEP();
4018 addr = (u16)(M.x86.R_BX + (u8)M.x86.R_AL);
4019 M.x86.R_AL = fetch_data_byte(addr);
4020 DECODE_CLEAR_SEGOVR();
4021 END_OF_INSTR();
4022}
4023
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004024/* instuctions D8 .. DF are in i87_ops.c */
Jason Jina63ce952007-07-06 08:34:56 +08004025
4026/****************************************************************************
4027REMARKS:
4028Handles opcode 0xe0
4029****************************************************************************/
4030void x86emuOp_loopne(u8 X86EMU_UNUSED(op1))
4031{
4032 s16 ip;
4033
4034 START_OF_INSTR();
4035 DECODE_PRINTF("LOOPNE\t");
4036 ip = (s8) fetch_byte_imm();
4037 ip += (s16) M.x86.R_IP;
4038 DECODE_PRINTF2("%04x\n", ip);
4039 TRACE_AND_STEP();
4040 M.x86.R_CX -= 1;
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004041 if (M.x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */
4042 M.x86.R_IP = ip;
Jason Jina63ce952007-07-06 08:34:56 +08004043 DECODE_CLEAR_SEGOVR();
4044 END_OF_INSTR();
4045}
4046
4047/****************************************************************************
4048REMARKS:
4049Handles opcode 0xe1
4050****************************************************************************/
4051void x86emuOp_loope(u8 X86EMU_UNUSED(op1))
4052{
4053 s16 ip;
4054
4055 START_OF_INSTR();
4056 DECODE_PRINTF("LOOPE\t");
4057 ip = (s8) fetch_byte_imm();
4058 ip += (s16) M.x86.R_IP;
4059 DECODE_PRINTF2("%04x\n", ip);
4060 TRACE_AND_STEP();
4061 M.x86.R_CX -= 1;
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004062 if (M.x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */
4063 M.x86.R_IP = ip;
Jason Jina63ce952007-07-06 08:34:56 +08004064 DECODE_CLEAR_SEGOVR();
4065 END_OF_INSTR();
4066}
4067
4068/****************************************************************************
4069REMARKS:
4070Handles opcode 0xe2
4071****************************************************************************/
4072void x86emuOp_loop(u8 X86EMU_UNUSED(op1))
4073{
4074 s16 ip;
4075
4076 START_OF_INSTR();
4077 DECODE_PRINTF("LOOP\t");
4078 ip = (s8) fetch_byte_imm();
4079 ip += (s16) M.x86.R_IP;
4080 DECODE_PRINTF2("%04x\n", ip);
4081 TRACE_AND_STEP();
4082 M.x86.R_CX -= 1;
4083 if (M.x86.R_CX != 0)
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004084 M.x86.R_IP = ip;
Jason Jina63ce952007-07-06 08:34:56 +08004085 DECODE_CLEAR_SEGOVR();
4086 END_OF_INSTR();
4087}
4088
4089/****************************************************************************
4090REMARKS:
4091Handles opcode 0xe3
4092****************************************************************************/
4093void x86emuOp_jcxz(u8 X86EMU_UNUSED(op1))
4094{
4095 u16 target;
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004096 s8 offset;
Jason Jina63ce952007-07-06 08:34:56 +08004097
4098 /* jump to byte offset if overflow flag is set */
4099 START_OF_INSTR();
4100 DECODE_PRINTF("JCXZ\t");
4101 offset = (s8)fetch_byte_imm();
4102 target = (u16)(M.x86.R_IP + offset);
4103 DECODE_PRINTF2("%x\n", target);
4104 TRACE_AND_STEP();
4105 if (M.x86.R_CX == 0)
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004106 M.x86.R_IP = target;
Jason Jina63ce952007-07-06 08:34:56 +08004107 DECODE_CLEAR_SEGOVR();
4108 END_OF_INSTR();
4109}
4110
4111/****************************************************************************
4112REMARKS:
4113Handles opcode 0xe4
4114****************************************************************************/
4115void x86emuOp_in_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
4116{
4117 u8 port;
4118
4119 START_OF_INSTR();
4120 DECODE_PRINTF("IN\t");
4121 port = (u8) fetch_byte_imm();
4122 DECODE_PRINTF2("%x,AL\n", port);
4123 TRACE_AND_STEP();
4124 M.x86.R_AL = (*sys_inb)(port);
4125 DECODE_CLEAR_SEGOVR();
4126 END_OF_INSTR();
4127}
4128
4129/****************************************************************************
4130REMARKS:
4131Handles opcode 0xe5
4132****************************************************************************/
4133void x86emuOp_in_word_AX_IMM(u8 X86EMU_UNUSED(op1))
4134{
4135 u8 port;
4136
4137 START_OF_INSTR();
4138 DECODE_PRINTF("IN\t");
4139 port = (u8) fetch_byte_imm();
4140 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004141 DECODE_PRINTF2("EAX,%x\n", port);
Jason Jina63ce952007-07-06 08:34:56 +08004142 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004143 DECODE_PRINTF2("AX,%x\n", port);
Jason Jina63ce952007-07-06 08:34:56 +08004144 }
4145 TRACE_AND_STEP();
4146 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004147 M.x86.R_EAX = (*sys_inl)(port);
Jason Jina63ce952007-07-06 08:34:56 +08004148 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004149 M.x86.R_AX = (*sys_inw)(port);
Jason Jina63ce952007-07-06 08:34:56 +08004150 }
4151 DECODE_CLEAR_SEGOVR();
4152 END_OF_INSTR();
4153}
4154
4155/****************************************************************************
4156REMARKS:
4157Handles opcode 0xe6
4158****************************************************************************/
4159void x86emuOp_out_byte_IMM_AL(u8 X86EMU_UNUSED(op1))
4160{
4161 u8 port;
4162
4163 START_OF_INSTR();
4164 DECODE_PRINTF("OUT\t");
4165 port = (u8) fetch_byte_imm();
4166 DECODE_PRINTF2("%x,AL\n", port);
4167 TRACE_AND_STEP();
4168 (*sys_outb)(port, M.x86.R_AL);
4169 DECODE_CLEAR_SEGOVR();
4170 END_OF_INSTR();
4171}
4172
4173/****************************************************************************
4174REMARKS:
4175Handles opcode 0xe7
4176****************************************************************************/
4177void x86emuOp_out_word_IMM_AX(u8 X86EMU_UNUSED(op1))
4178{
4179 u8 port;
4180
4181 START_OF_INSTR();
4182 DECODE_PRINTF("OUT\t");
4183 port = (u8) fetch_byte_imm();
4184 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004185 DECODE_PRINTF2("%x,EAX\n", port);
Jason Jina63ce952007-07-06 08:34:56 +08004186 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004187 DECODE_PRINTF2("%x,AX\n", port);
Jason Jina63ce952007-07-06 08:34:56 +08004188 }
4189 TRACE_AND_STEP();
4190 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004191 (*sys_outl)(port, M.x86.R_EAX);
Jason Jina63ce952007-07-06 08:34:56 +08004192 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004193 (*sys_outw)(port, M.x86.R_AX);
Jason Jina63ce952007-07-06 08:34:56 +08004194 }
4195 DECODE_CLEAR_SEGOVR();
4196 END_OF_INSTR();
4197}
4198
4199/****************************************************************************
4200REMARKS:
4201Handles opcode 0xe8
4202****************************************************************************/
4203void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1))
4204{
4205 s16 ip;
4206
4207 START_OF_INSTR();
4208 DECODE_PRINTF("CALL\t");
4209 ip = (s16) fetch_word_imm();
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004210 ip += (s16) M.x86.R_IP; /* CHECK SIGN */
Jason Jina63ce952007-07-06 08:34:56 +08004211 DECODE_PRINTF2("%04x\n", ip);
4212 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, "");
4213 TRACE_AND_STEP();
4214 push_word(M.x86.R_IP);
4215 M.x86.R_IP = ip;
4216 DECODE_CLEAR_SEGOVR();
4217 END_OF_INSTR();
4218}
4219
4220/****************************************************************************
4221REMARKS:
4222Handles opcode 0xe9
4223****************************************************************************/
4224void x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1))
4225{
4226 int ip;
4227
4228 START_OF_INSTR();
4229 DECODE_PRINTF("JMP\t");
4230 ip = (s16)fetch_word_imm();
4231 ip += (s16)M.x86.R_IP;
4232 DECODE_PRINTF2("%04x\n", ip);
4233 TRACE_AND_STEP();
4234 M.x86.R_IP = (u16)ip;
4235 DECODE_CLEAR_SEGOVR();
4236 END_OF_INSTR();
4237}
4238
4239/****************************************************************************
4240REMARKS:
4241Handles opcode 0xea
4242****************************************************************************/
4243void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1))
4244{
4245 u16 cs, ip;
4246
4247 START_OF_INSTR();
4248 DECODE_PRINTF("JMP\tFAR ");
4249 ip = fetch_word_imm();
4250 cs = fetch_word_imm();
4251 DECODE_PRINTF2("%04x:", cs);
4252 DECODE_PRINTF2("%04x\n", ip);
4253 TRACE_AND_STEP();
4254 M.x86.R_IP = ip;
4255 M.x86.R_CS = cs;
4256 DECODE_CLEAR_SEGOVR();
4257 END_OF_INSTR();
4258}
4259
4260/****************************************************************************
4261REMARKS:
4262Handles opcode 0xeb
4263****************************************************************************/
4264void x86emuOp_jump_byte_IMM(u8 X86EMU_UNUSED(op1))
4265{
4266 u16 target;
4267 s8 offset;
4268
4269 START_OF_INSTR();
4270 DECODE_PRINTF("JMP\t");
4271 offset = (s8)fetch_byte_imm();
4272 target = (u16)(M.x86.R_IP + offset);
4273 DECODE_PRINTF2("%x\n", target);
4274 TRACE_AND_STEP();
4275 M.x86.R_IP = target;
4276 DECODE_CLEAR_SEGOVR();
4277 END_OF_INSTR();
4278}
4279
4280/****************************************************************************
4281REMARKS:
4282Handles opcode 0xec
4283****************************************************************************/
4284void x86emuOp_in_byte_AL_DX(u8 X86EMU_UNUSED(op1))
4285{
4286 START_OF_INSTR();
4287 DECODE_PRINTF("IN\tAL,DX\n");
4288 TRACE_AND_STEP();
4289 M.x86.R_AL = (*sys_inb)(M.x86.R_DX);
4290 DECODE_CLEAR_SEGOVR();
4291 END_OF_INSTR();
4292}
4293
4294/****************************************************************************
4295REMARKS:
4296Handles opcode 0xed
4297****************************************************************************/
4298void x86emuOp_in_word_AX_DX(u8 X86EMU_UNUSED(op1))
4299{
4300 START_OF_INSTR();
4301 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004302 DECODE_PRINTF("IN\tEAX,DX\n");
Jason Jina63ce952007-07-06 08:34:56 +08004303 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004304 DECODE_PRINTF("IN\tAX,DX\n");
Jason Jina63ce952007-07-06 08:34:56 +08004305 }
4306 TRACE_AND_STEP();
4307 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004308 M.x86.R_EAX = (*sys_inl)(M.x86.R_DX);
Jason Jina63ce952007-07-06 08:34:56 +08004309 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004310 M.x86.R_AX = (*sys_inw)(M.x86.R_DX);
Jason Jina63ce952007-07-06 08:34:56 +08004311 }
4312 DECODE_CLEAR_SEGOVR();
4313 END_OF_INSTR();
4314}
4315
4316/****************************************************************************
4317REMARKS:
4318Handles opcode 0xee
4319****************************************************************************/
4320void x86emuOp_out_byte_DX_AL(u8 X86EMU_UNUSED(op1))
4321{
4322 START_OF_INSTR();
4323 DECODE_PRINTF("OUT\tDX,AL\n");
4324 TRACE_AND_STEP();
4325 (*sys_outb)(M.x86.R_DX, M.x86.R_AL);
4326 DECODE_CLEAR_SEGOVR();
4327 END_OF_INSTR();
4328}
4329
4330/****************************************************************************
4331REMARKS:
4332Handles opcode 0xef
4333****************************************************************************/
4334void x86emuOp_out_word_DX_AX(u8 X86EMU_UNUSED(op1))
4335{
4336 START_OF_INSTR();
4337 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004338 DECODE_PRINTF("OUT\tDX,EAX\n");
Jason Jina63ce952007-07-06 08:34:56 +08004339 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004340 DECODE_PRINTF("OUT\tDX,AX\n");
Jason Jina63ce952007-07-06 08:34:56 +08004341 }
4342 TRACE_AND_STEP();
4343 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004344 (*sys_outl)(M.x86.R_DX, M.x86.R_EAX);
Jason Jina63ce952007-07-06 08:34:56 +08004345 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004346 (*sys_outw)(M.x86.R_DX, M.x86.R_AX);
Jason Jina63ce952007-07-06 08:34:56 +08004347 }
4348 DECODE_CLEAR_SEGOVR();
4349 END_OF_INSTR();
4350}
4351
4352/****************************************************************************
4353REMARKS:
4354Handles opcode 0xf0
4355****************************************************************************/
4356void x86emuOp_lock(u8 X86EMU_UNUSED(op1))
4357{
4358 START_OF_INSTR();
4359 DECODE_PRINTF("LOCK:\n");
4360 TRACE_AND_STEP();
4361 DECODE_CLEAR_SEGOVR();
4362 END_OF_INSTR();
4363}
4364
4365/*opcode 0xf1 ILLEGAL OPERATION */
4366
4367/****************************************************************************
4368REMARKS:
4369Handles opcode 0xf2
4370****************************************************************************/
4371void x86emuOp_repne(u8 X86EMU_UNUSED(op1))
4372{
4373 START_OF_INSTR();
4374 DECODE_PRINTF("REPNE\n");
4375 TRACE_AND_STEP();
4376 M.x86.mode |= SYSMODE_PREFIX_REPNE;
4377 DECODE_CLEAR_SEGOVR();
4378 END_OF_INSTR();
4379}
4380
4381/****************************************************************************
4382REMARKS:
4383Handles opcode 0xf3
4384****************************************************************************/
4385void x86emuOp_repe(u8 X86EMU_UNUSED(op1))
4386{
4387 START_OF_INSTR();
4388 DECODE_PRINTF("REPE\n");
4389 TRACE_AND_STEP();
4390 M.x86.mode |= SYSMODE_PREFIX_REPE;
4391 DECODE_CLEAR_SEGOVR();
4392 END_OF_INSTR();
4393}
4394
4395/****************************************************************************
4396REMARKS:
4397Handles opcode 0xf4
4398****************************************************************************/
4399void x86emuOp_halt(u8 X86EMU_UNUSED(op1))
4400{
4401 START_OF_INSTR();
4402 DECODE_PRINTF("HALT\n");
4403 TRACE_AND_STEP();
4404 HALT_SYS();
4405 DECODE_CLEAR_SEGOVR();
4406 END_OF_INSTR();
4407}
4408
4409/****************************************************************************
4410REMARKS:
4411Handles opcode 0xf5
4412****************************************************************************/
4413void x86emuOp_cmc(u8 X86EMU_UNUSED(op1))
4414{
4415 /* complement the carry flag. */
4416 START_OF_INSTR();
4417 DECODE_PRINTF("CMC\n");
4418 TRACE_AND_STEP();
4419 TOGGLE_FLAG(F_CF);
4420 DECODE_CLEAR_SEGOVR();
4421 END_OF_INSTR();
4422}
4423
4424/****************************************************************************
4425REMARKS:
4426Handles opcode 0xf6
4427****************************************************************************/
4428void x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1))
4429{
4430 int mod, rl, rh;
4431 u8 *destreg;
4432 uint destoffset;
4433 u8 destval, srcval;
4434
4435 /* long, drawn out code follows. Double switch for a total
4436 of 32 cases. */
4437 START_OF_INSTR();
4438 FETCH_DECODE_MODRM(mod, rh, rl);
4439 DECODE_PRINTF(opF6_names[rh]);
4440 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004441 DECODE_PRINTF("BYTE PTR ");
4442 destoffset = decode_rmXX_address(mod, rl);
4443 destval = fetch_data_byte(destoffset);
Jason Jina63ce952007-07-06 08:34:56 +08004444
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004445 switch (rh) {
4446 case 0: /* test byte imm */
4447 DECODE_PRINTF(",");
4448 srcval = fetch_byte_imm();
4449 DECODE_PRINTF2("%02x\n", srcval);
4450 TRACE_AND_STEP();
4451 test_byte(destval, srcval);
4452 break;
4453 case 1:
4454 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4455 HALT_SYS();
4456 break;
4457 case 2:
4458 DECODE_PRINTF("\n");
4459 TRACE_AND_STEP();
4460 destval = not_byte(destval);
4461 store_data_byte(destoffset, destval);
4462 break;
4463 case 3:
4464 DECODE_PRINTF("\n");
4465 TRACE_AND_STEP();
4466 destval = neg_byte(destval);
4467 store_data_byte(destoffset, destval);
4468 break;
4469 case 4:
4470 DECODE_PRINTF("\n");
4471 TRACE_AND_STEP();
4472 mul_byte(destval);
4473 break;
4474 case 5:
4475 DECODE_PRINTF("\n");
4476 TRACE_AND_STEP();
4477 imul_byte(destval);
4478 break;
4479 case 6:
4480 DECODE_PRINTF("\n");
4481 TRACE_AND_STEP();
4482 div_byte(destval);
4483 break;
4484 default:
4485 DECODE_PRINTF("\n");
4486 TRACE_AND_STEP();
4487 idiv_byte(destval);
4488 break;
4489 }
4490 } else { /* mod=11 */
4491 destreg = DECODE_RM_BYTE_REGISTER(rl);
4492 switch (rh) {
4493 case 0: /* test byte imm */
4494 DECODE_PRINTF(",");
4495 srcval = fetch_byte_imm();
4496 DECODE_PRINTF2("%02x\n", srcval);
4497 TRACE_AND_STEP();
4498 test_byte(*destreg, srcval);
4499 break;
4500 case 1:
4501 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4502 HALT_SYS();
4503 break;
4504 case 2:
4505 DECODE_PRINTF("\n");
4506 TRACE_AND_STEP();
4507 *destreg = not_byte(*destreg);
4508 break;
4509 case 3:
4510 DECODE_PRINTF("\n");
4511 TRACE_AND_STEP();
4512 *destreg = neg_byte(*destreg);
4513 break;
4514 case 4:
4515 DECODE_PRINTF("\n");
4516 TRACE_AND_STEP();
4517 mul_byte(*destreg); /*!!! */
4518 break;
4519 case 5:
4520 DECODE_PRINTF("\n");
4521 TRACE_AND_STEP();
4522 imul_byte(*destreg);
4523 break;
4524 case 6:
4525 DECODE_PRINTF("\n");
4526 TRACE_AND_STEP();
4527 div_byte(*destreg);
4528 break;
4529 default:
4530 DECODE_PRINTF("\n");
4531 TRACE_AND_STEP();
4532 idiv_byte(*destreg);
4533 break;
4534 }
Jason Jina63ce952007-07-06 08:34:56 +08004535 }
4536 DECODE_CLEAR_SEGOVR();
4537 END_OF_INSTR();
4538}
4539
4540/****************************************************************************
4541REMARKS:
4542Handles opcode 0xf7
4543****************************************************************************/
4544void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1))
4545{
4546 int mod, rl, rh;
4547 uint destoffset;
4548
4549 START_OF_INSTR();
4550 FETCH_DECODE_MODRM(mod, rh, rl);
4551 DECODE_PRINTF(opF6_names[rh]);
4552 if (mod < 3) {
4553
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004554 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4555 u32 destval, srcval;
Jason Jina63ce952007-07-06 08:34:56 +08004556
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004557 DECODE_PRINTF("DWORD PTR ");
4558 destoffset = decode_rmXX_address(mod, rl);
4559 destval = fetch_data_long(destoffset);
Jason Jina63ce952007-07-06 08:34:56 +08004560
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004561 switch (rh) {
4562 case 0:
4563 DECODE_PRINTF(",");
4564 srcval = fetch_long_imm();
4565 DECODE_PRINTF2("%x\n", srcval);
4566 TRACE_AND_STEP();
4567 test_long(destval, srcval);
4568 break;
4569 case 1:
4570 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4571 HALT_SYS();
4572 break;
4573 case 2:
4574 DECODE_PRINTF("\n");
4575 TRACE_AND_STEP();
4576 destval = not_long(destval);
4577 store_data_long(destoffset, destval);
4578 break;
4579 case 3:
4580 DECODE_PRINTF("\n");
4581 TRACE_AND_STEP();
4582 destval = neg_long(destval);
4583 store_data_long(destoffset, destval);
4584 break;
4585 case 4:
4586 DECODE_PRINTF("\n");
4587 TRACE_AND_STEP();
4588 mul_long(destval);
4589 break;
4590 case 5:
4591 DECODE_PRINTF("\n");
4592 TRACE_AND_STEP();
4593 imul_long(destval);
4594 break;
4595 case 6:
4596 DECODE_PRINTF("\n");
4597 TRACE_AND_STEP();
4598 div_long(destval);
4599 break;
4600 case 7:
4601 DECODE_PRINTF("\n");
4602 TRACE_AND_STEP();
4603 idiv_long(destval);
4604 break;
4605 }
4606 } else {
4607 u16 destval, srcval;
Jason Jina63ce952007-07-06 08:34:56 +08004608
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004609 DECODE_PRINTF("WORD PTR ");
4610 destoffset = decode_rmXX_address(mod, rl);
4611 destval = fetch_data_word(destoffset);
Jason Jina63ce952007-07-06 08:34:56 +08004612
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004613 switch (rh) {
4614 case 0: /* test word imm */
4615 DECODE_PRINTF(",");
4616 srcval = fetch_word_imm();
4617 DECODE_PRINTF2("%x\n", srcval);
4618 TRACE_AND_STEP();
4619 test_word(destval, srcval);
4620 break;
4621 case 1:
4622 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4623 HALT_SYS();
4624 break;
4625 case 2:
4626 DECODE_PRINTF("\n");
4627 TRACE_AND_STEP();
4628 destval = not_word(destval);
4629 store_data_word(destoffset, destval);
4630 break;
4631 case 3:
4632 DECODE_PRINTF("\n");
4633 TRACE_AND_STEP();
4634 destval = neg_word(destval);
4635 store_data_word(destoffset, destval);
4636 break;
4637 case 4:
4638 DECODE_PRINTF("\n");
4639 TRACE_AND_STEP();
4640 mul_word(destval);
4641 break;
4642 case 5:
4643 DECODE_PRINTF("\n");
4644 TRACE_AND_STEP();
4645 imul_word(destval);
4646 break;
4647 case 6:
4648 DECODE_PRINTF("\n");
4649 TRACE_AND_STEP();
4650 div_word(destval);
4651 break;
4652 case 7:
4653 DECODE_PRINTF("\n");
4654 TRACE_AND_STEP();
4655 idiv_word(destval);
4656 break;
4657 }
4658 }
Jason Jina63ce952007-07-06 08:34:56 +08004659
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004660 } else { /* mod=11 */
Jason Jina63ce952007-07-06 08:34:56 +08004661
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004662 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4663 u32 *destreg;
4664 u32 srcval;
Jason Jina63ce952007-07-06 08:34:56 +08004665
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004666 destreg = DECODE_RM_LONG_REGISTER(rl);
Jason Jina63ce952007-07-06 08:34:56 +08004667
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004668 switch (rh) {
4669 case 0: /* test word imm */
4670 DECODE_PRINTF(",");
4671 srcval = fetch_long_imm();
4672 DECODE_PRINTF2("%x\n", srcval);
4673 TRACE_AND_STEP();
4674 test_long(*destreg, srcval);
4675 break;
4676 case 1:
4677 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4678 HALT_SYS();
4679 break;
4680 case 2:
4681 DECODE_PRINTF("\n");
4682 TRACE_AND_STEP();
4683 *destreg = not_long(*destreg);
4684 break;
4685 case 3:
4686 DECODE_PRINTF("\n");
4687 TRACE_AND_STEP();
4688 *destreg = neg_long(*destreg);
4689 break;
4690 case 4:
4691 DECODE_PRINTF("\n");
4692 TRACE_AND_STEP();
4693 mul_long(*destreg); /*!!! */
4694 break;
4695 case 5:
4696 DECODE_PRINTF("\n");
4697 TRACE_AND_STEP();
4698 imul_long(*destreg);
4699 break;
4700 case 6:
4701 DECODE_PRINTF("\n");
4702 TRACE_AND_STEP();
4703 div_long(*destreg);
4704 break;
4705 case 7:
4706 DECODE_PRINTF("\n");
4707 TRACE_AND_STEP();
4708 idiv_long(*destreg);
4709 break;
4710 }
4711 } else {
4712 u16 *destreg;
4713 u16 srcval;
Jason Jina63ce952007-07-06 08:34:56 +08004714
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004715 destreg = DECODE_RM_WORD_REGISTER(rl);
Jason Jina63ce952007-07-06 08:34:56 +08004716
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004717 switch (rh) {
4718 case 0: /* test word imm */
4719 DECODE_PRINTF(",");
4720 srcval = fetch_word_imm();
4721 DECODE_PRINTF2("%x\n", srcval);
4722 TRACE_AND_STEP();
4723 test_word(*destreg, srcval);
4724 break;
4725 case 1:
4726 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4727 HALT_SYS();
4728 break;
4729 case 2:
4730 DECODE_PRINTF("\n");
4731 TRACE_AND_STEP();
4732 *destreg = not_word(*destreg);
4733 break;
4734 case 3:
4735 DECODE_PRINTF("\n");
4736 TRACE_AND_STEP();
4737 *destreg = neg_word(*destreg);
4738 break;
4739 case 4:
4740 DECODE_PRINTF("\n");
4741 TRACE_AND_STEP();
4742 mul_word(*destreg); /*!!! */
4743 break;
4744 case 5:
4745 DECODE_PRINTF("\n");
4746 TRACE_AND_STEP();
4747 imul_word(*destreg);
4748 break;
4749 case 6:
4750 DECODE_PRINTF("\n");
4751 TRACE_AND_STEP();
4752 div_word(*destreg);
4753 break;
4754 case 7:
4755 DECODE_PRINTF("\n");
4756 TRACE_AND_STEP();
4757 idiv_word(*destreg);
4758 break;
4759 }
4760 }
Jason Jina63ce952007-07-06 08:34:56 +08004761 }
4762 DECODE_CLEAR_SEGOVR();
4763 END_OF_INSTR();
4764}
4765
4766/****************************************************************************
4767REMARKS:
4768Handles opcode 0xf8
4769****************************************************************************/
4770void x86emuOp_clc(u8 X86EMU_UNUSED(op1))
4771{
4772 /* clear the carry flag. */
4773 START_OF_INSTR();
4774 DECODE_PRINTF("CLC\n");
4775 TRACE_AND_STEP();
4776 CLEAR_FLAG(F_CF);
4777 DECODE_CLEAR_SEGOVR();
4778 END_OF_INSTR();
4779}
4780
4781/****************************************************************************
4782REMARKS:
4783Handles opcode 0xf9
4784****************************************************************************/
4785void x86emuOp_stc(u8 X86EMU_UNUSED(op1))
4786{
4787 /* set the carry flag. */
4788 START_OF_INSTR();
4789 DECODE_PRINTF("STC\n");
4790 TRACE_AND_STEP();
4791 SET_FLAG(F_CF);
4792 DECODE_CLEAR_SEGOVR();
4793 END_OF_INSTR();
4794}
4795
4796/****************************************************************************
4797REMARKS:
4798Handles opcode 0xfa
4799****************************************************************************/
4800void x86emuOp_cli(u8 X86EMU_UNUSED(op1))
4801{
4802 /* clear interrupts. */
4803 START_OF_INSTR();
4804 DECODE_PRINTF("CLI\n");
4805 TRACE_AND_STEP();
4806 CLEAR_FLAG(F_IF);
4807 DECODE_CLEAR_SEGOVR();
4808 END_OF_INSTR();
4809}
4810
4811/****************************************************************************
4812REMARKS:
4813Handles opcode 0xfb
4814****************************************************************************/
4815void x86emuOp_sti(u8 X86EMU_UNUSED(op1))
4816{
4817 /* enable interrupts. */
4818 START_OF_INSTR();
4819 DECODE_PRINTF("STI\n");
4820 TRACE_AND_STEP();
4821 SET_FLAG(F_IF);
4822 DECODE_CLEAR_SEGOVR();
4823 END_OF_INSTR();
4824}
4825
4826/****************************************************************************
4827REMARKS:
4828Handles opcode 0xfc
4829****************************************************************************/
4830void x86emuOp_cld(u8 X86EMU_UNUSED(op1))
4831{
4832 /* clear interrupts. */
4833 START_OF_INSTR();
4834 DECODE_PRINTF("CLD\n");
4835 TRACE_AND_STEP();
4836 CLEAR_FLAG(F_DF);
4837 DECODE_CLEAR_SEGOVR();
4838 END_OF_INSTR();
4839}
4840
4841/****************************************************************************
4842REMARKS:
4843Handles opcode 0xfd
4844****************************************************************************/
4845void x86emuOp_std(u8 X86EMU_UNUSED(op1))
4846{
4847 /* clear interrupts. */
4848 START_OF_INSTR();
4849 DECODE_PRINTF("STD\n");
4850 TRACE_AND_STEP();
4851 SET_FLAG(F_DF);
4852 DECODE_CLEAR_SEGOVR();
4853 END_OF_INSTR();
4854}
4855
4856/****************************************************************************
4857REMARKS:
4858Handles opcode 0xfe
4859****************************************************************************/
4860void x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1))
4861{
4862 int mod, rh, rl;
4863 u8 destval;
4864 uint destoffset;
4865 u8 *destreg;
4866
4867 /* Yet another special case instruction. */
4868 START_OF_INSTR();
4869 FETCH_DECODE_MODRM(mod, rh, rl);
4870#ifdef DEBUG
4871 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004872 /* XXX DECODE_PRINTF may be changed to something more
4873 general, so that it is important to leave the strings
4874 in the same format, even though the result is that the
4875 above test is done twice. */
Jason Jina63ce952007-07-06 08:34:56 +08004876
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004877 switch (rh) {
4878 case 0:
4879 DECODE_PRINTF("INC\t");
4880 break;
4881 case 1:
4882 DECODE_PRINTF("DEC\t");
4883 break;
4884 case 2:
4885 case 3:
4886 case 4:
4887 case 5:
4888 case 6:
4889 case 7:
4890 DECODE_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x \n", mod);
4891 HALT_SYS();
4892 break;
4893 }
Jason Jina63ce952007-07-06 08:34:56 +08004894 }
4895#endif
4896 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004897 DECODE_PRINTF("BYTE PTR ");
4898 destoffset = decode_rmXX_address(mod, rl);
4899 DECODE_PRINTF("\n");
4900 destval = fetch_data_byte(destoffset);
4901 TRACE_AND_STEP();
4902 if (rh == 0)
4903 destval = inc_byte(destval);
4904 else
4905 destval = dec_byte(destval);
4906 store_data_byte(destoffset, destval);
Jason Jina63ce952007-07-06 08:34:56 +08004907 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004908 destreg = DECODE_RM_BYTE_REGISTER(rl);
4909 DECODE_PRINTF("\n");
4910 TRACE_AND_STEP();
4911 if (rh == 0)
4912 *destreg = inc_byte(*destreg);
4913 else
4914 *destreg = dec_byte(*destreg);
Jason Jina63ce952007-07-06 08:34:56 +08004915 }
4916 DECODE_CLEAR_SEGOVR();
4917 END_OF_INSTR();
4918}
4919
4920/****************************************************************************
4921REMARKS:
4922Handles opcode 0xff
4923****************************************************************************/
4924void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1))
4925{
4926 int mod, rh, rl;
4927 uint destoffset = 0;
4928 u16 *destreg;
4929 u16 destval,destval2;
4930
4931 /* Yet another special case instruction. */
4932 START_OF_INSTR();
4933 FETCH_DECODE_MODRM(mod, rh, rl);
4934#ifdef DEBUG
4935 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004936 /* XXX DECODE_PRINTF may be changed to something more
4937 general, so that it is important to leave the strings
4938 in the same format, even though the result is that the
4939 above test is done twice. */
Jason Jina63ce952007-07-06 08:34:56 +08004940
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004941 switch (rh) {
4942 case 0:
4943 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4944 DECODE_PRINTF("INC\tDWORD PTR ");
4945 } else {
4946 DECODE_PRINTF("INC\tWORD PTR ");
4947 }
4948 break;
4949 case 1:
4950 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4951 DECODE_PRINTF("DEC\tDWORD PTR ");
4952 } else {
4953 DECODE_PRINTF("DEC\tWORD PTR ");
4954 }
4955 break;
4956 case 2:
4957 DECODE_PRINTF("CALL\t ");
4958 break;
4959 case 3:
4960 DECODE_PRINTF("CALL\tFAR ");
4961 break;
4962 case 4:
4963 DECODE_PRINTF("JMP\t");
4964 break;
4965 case 5:
4966 DECODE_PRINTF("JMP\tFAR ");
4967 break;
4968 case 6:
4969 DECODE_PRINTF("PUSH\t");
4970 break;
4971 case 7:
4972 DECODE_PRINTF("ILLEGAL DECODING OF OPCODE FF\t");
4973 HALT_SYS();
4974 break;
4975 }
Jason Jina63ce952007-07-06 08:34:56 +08004976 }
4977#endif
4978 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004979 destoffset = decode_rmXX_address(mod, rl);
4980 DECODE_PRINTF("\n");
4981 switch (rh) {
4982 case 0: /* inc word ptr ... */
4983 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4984 u32 destval;
Jason Jina63ce952007-07-06 08:34:56 +08004985
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004986 destval = fetch_data_long(destoffset);
4987 TRACE_AND_STEP();
4988 destval = inc_long(destval);
4989 store_data_long(destoffset, destval);
4990 } else {
4991 u16 destval;
Jason Jina63ce952007-07-06 08:34:56 +08004992
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004993 destval = fetch_data_word(destoffset);
4994 TRACE_AND_STEP();
4995 destval = inc_word(destval);
4996 store_data_word(destoffset, destval);
4997 }
4998 break;
4999 case 1: /* dec word ptr ... */
5000 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5001 u32 destval;
Jason Jina63ce952007-07-06 08:34:56 +08005002
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005003 destval = fetch_data_long(destoffset);
5004 TRACE_AND_STEP();
5005 destval = dec_long(destval);
5006 store_data_long(destoffset, destval);
5007 } else {
5008 u16 destval;
Jason Jina63ce952007-07-06 08:34:56 +08005009
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005010 destval = fetch_data_word(destoffset);
5011 TRACE_AND_STEP();
5012 destval = dec_word(destval);
5013 store_data_word(destoffset, destval);
5014 }
5015 break;
5016 case 2: /* call word ptr ... */
5017 destval = fetch_data_word(destoffset);
5018 TRACE_AND_STEP();
5019 push_word(M.x86.R_IP);
5020 M.x86.R_IP = destval;
5021 break;
5022 case 3: /* call far ptr ... */
5023 destval = fetch_data_word(destoffset);
5024 destval2 = fetch_data_word(destoffset + 2);
5025 TRACE_AND_STEP();
5026 push_word(M.x86.R_CS);
5027 M.x86.R_CS = destval2;
5028 push_word(M.x86.R_IP);
5029 M.x86.R_IP = destval;
5030 break;
5031 case 4: /* jmp word ptr ... */
5032 destval = fetch_data_word(destoffset);
5033 TRACE_AND_STEP();
5034 M.x86.R_IP = destval;
5035 break;
5036 case 5: /* jmp far ptr ... */
5037 destval = fetch_data_word(destoffset);
5038 destval2 = fetch_data_word(destoffset + 2);
5039 TRACE_AND_STEP();
5040 M.x86.R_IP = destval;
5041 M.x86.R_CS = destval2;
5042 break;
5043 case 6: /* push word ptr ... */
5044 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5045 u32 destval;
Jason Jina63ce952007-07-06 08:34:56 +08005046
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005047 destval = fetch_data_long(destoffset);
5048 TRACE_AND_STEP();
5049 push_long(destval);
5050 } else {
5051 u16 destval;
Jason Jina63ce952007-07-06 08:34:56 +08005052
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005053 destval = fetch_data_word(destoffset);
5054 TRACE_AND_STEP();
5055 push_word(destval);
5056 }
5057 break;
5058 }
Jason Jina63ce952007-07-06 08:34:56 +08005059 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005060 switch (rh) {
5061 case 0:
5062 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5063 u32 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08005064
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005065 destreg = DECODE_RM_LONG_REGISTER(rl);
5066 DECODE_PRINTF("\n");
5067 TRACE_AND_STEP();
5068 *destreg = inc_long(*destreg);
5069 } else {
5070 u16 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08005071
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005072 destreg = DECODE_RM_WORD_REGISTER(rl);
5073 DECODE_PRINTF("\n");
5074 TRACE_AND_STEP();
5075 *destreg = inc_word(*destreg);
5076 }
5077 break;
5078 case 1:
5079 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5080 u32 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08005081
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005082 destreg = DECODE_RM_LONG_REGISTER(rl);
5083 DECODE_PRINTF("\n");
5084 TRACE_AND_STEP();
5085 *destreg = dec_long(*destreg);
5086 } else {
5087 u16 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08005088
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005089 destreg = DECODE_RM_WORD_REGISTER(rl);
5090 DECODE_PRINTF("\n");
5091 TRACE_AND_STEP();
5092 *destreg = dec_word(*destreg);
5093 }
5094 break;
5095 case 2: /* call word ptr ... */
5096 destreg = DECODE_RM_WORD_REGISTER(rl);
5097 DECODE_PRINTF("\n");
5098 TRACE_AND_STEP();
5099 push_word(M.x86.R_IP);
5100 M.x86.R_IP = *destreg;
5101 break;
5102 case 3: /* jmp far ptr ... */
5103 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5104 TRACE_AND_STEP();
5105 HALT_SYS();
5106 break;
Jason Jina63ce952007-07-06 08:34:56 +08005107
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005108 case 4: /* jmp ... */
5109 destreg = DECODE_RM_WORD_REGISTER(rl);
5110 DECODE_PRINTF("\n");
5111 TRACE_AND_STEP();
5112 M.x86.R_IP = (u16) (*destreg);
5113 break;
5114 case 5: /* jmp far ptr ... */
5115 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5116 TRACE_AND_STEP();
5117 HALT_SYS();
5118 break;
5119 case 6:
5120 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5121 u32 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08005122
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005123 destreg = DECODE_RM_LONG_REGISTER(rl);
5124 DECODE_PRINTF("\n");
5125 TRACE_AND_STEP();
5126 push_long(*destreg);
5127 } else {
5128 u16 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08005129
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005130 destreg = DECODE_RM_WORD_REGISTER(rl);
5131 DECODE_PRINTF("\n");
5132 TRACE_AND_STEP();
5133 push_word(*destreg);
5134 }
5135 break;
5136 }
Jason Jina63ce952007-07-06 08:34:56 +08005137 }
5138 DECODE_CLEAR_SEGOVR();
5139 END_OF_INSTR();
5140}
5141
5142/***************************************************************************
5143 * Single byte operation code table:
5144 **************************************************************************/
5145void (*x86emu_optab[256])(u8) __attribute__ ((section(".got2"))) =
5146{
5147/* 0x00 */ x86emuOp_genop_byte_RM_R,
5148/* 0x01 */ x86emuOp_genop_word_RM_R,
5149/* 0x02 */ x86emuOp_genop_byte_R_RM,
5150/* 0x03 */ x86emuOp_genop_word_R_RM,
5151/* 0x04 */ x86emuOp_genop_byte_AL_IMM,
5152/* 0x05 */ x86emuOp_genop_word_AX_IMM,
5153/* 0x06 */ x86emuOp_push_ES,
5154/* 0x07 */ x86emuOp_pop_ES,
5155
5156/* 0x08 */ x86emuOp_genop_byte_RM_R,
5157/* 0x09 */ x86emuOp_genop_word_RM_R,
5158/* 0x0a */ x86emuOp_genop_byte_R_RM,
5159/* 0x0b */ x86emuOp_genop_word_R_RM,
5160/* 0x0c */ x86emuOp_genop_byte_AL_IMM,
5161/* 0x0d */ x86emuOp_genop_word_AX_IMM,
5162/* 0x0e */ x86emuOp_push_CS,
5163/* 0x0f */ x86emuOp_two_byte,
5164
5165/* 0x10 */ x86emuOp_genop_byte_RM_R,
5166/* 0x11 */ x86emuOp_genop_word_RM_R,
5167/* 0x12 */ x86emuOp_genop_byte_R_RM,
5168/* 0x13 */ x86emuOp_genop_word_R_RM,
5169/* 0x14 */ x86emuOp_genop_byte_AL_IMM,
5170/* 0x15 */ x86emuOp_genop_word_AX_IMM,
5171/* 0x16 */ x86emuOp_push_SS,
5172/* 0x17 */ x86emuOp_pop_SS,
5173
5174/* 0x18 */ x86emuOp_genop_byte_RM_R,
5175/* 0x19 */ x86emuOp_genop_word_RM_R,
5176/* 0x1a */ x86emuOp_genop_byte_R_RM,
5177/* 0x1b */ x86emuOp_genop_word_R_RM,
5178/* 0x1c */ x86emuOp_genop_byte_AL_IMM,
5179/* 0x1d */ x86emuOp_genop_word_AX_IMM,
5180/* 0x1e */ x86emuOp_push_DS,
5181/* 0x1f */ x86emuOp_pop_DS,
5182
5183/* 0x20 */ x86emuOp_genop_byte_RM_R,
5184/* 0x21 */ x86emuOp_genop_word_RM_R,
5185/* 0x22 */ x86emuOp_genop_byte_R_RM,
5186/* 0x23 */ x86emuOp_genop_word_R_RM,
5187/* 0x24 */ x86emuOp_genop_byte_AL_IMM,
5188/* 0x25 */ x86emuOp_genop_word_AX_IMM,
5189/* 0x26 */ x86emuOp_segovr_ES,
5190/* 0x27 */ x86emuOp_daa,
5191
5192/* 0x28 */ x86emuOp_genop_byte_RM_R,
5193/* 0x29 */ x86emuOp_genop_word_RM_R,
5194/* 0x2a */ x86emuOp_genop_byte_R_RM,
5195/* 0x2b */ x86emuOp_genop_word_R_RM,
5196/* 0x2c */ x86emuOp_genop_byte_AL_IMM,
5197/* 0x2d */ x86emuOp_genop_word_AX_IMM,
5198/* 0x2e */ x86emuOp_segovr_CS,
5199/* 0x2f */ x86emuOp_das,
5200
5201/* 0x30 */ x86emuOp_genop_byte_RM_R,
5202/* 0x31 */ x86emuOp_genop_word_RM_R,
5203/* 0x32 */ x86emuOp_genop_byte_R_RM,
5204/* 0x33 */ x86emuOp_genop_word_R_RM,
5205/* 0x34 */ x86emuOp_genop_byte_AL_IMM,
5206/* 0x35 */ x86emuOp_genop_word_AX_IMM,
5207/* 0x36 */ x86emuOp_segovr_SS,
5208/* 0x37 */ x86emuOp_aaa,
5209
5210/* 0x38 */ x86emuOp_genop_byte_RM_R,
5211/* 0x39 */ x86emuOp_genop_word_RM_R,
5212/* 0x3a */ x86emuOp_genop_byte_R_RM,
5213/* 0x3b */ x86emuOp_genop_word_R_RM,
5214/* 0x3c */ x86emuOp_genop_byte_AL_IMM,
5215/* 0x3d */ x86emuOp_genop_word_AX_IMM,
5216/* 0x3e */ x86emuOp_segovr_DS,
5217/* 0x3f */ x86emuOp_aas,
5218
5219/* 0x40 */ x86emuOp_inc_register,
5220/* 0x41 */ x86emuOp_inc_register,
5221/* 0x42 */ x86emuOp_inc_register,
5222/* 0x43 */ x86emuOp_inc_register,
5223/* 0x44 */ x86emuOp_inc_register,
5224/* 0x45 */ x86emuOp_inc_register,
5225/* 0x46 */ x86emuOp_inc_register,
5226/* 0x47 */ x86emuOp_inc_register,
5227
5228/* 0x48 */ x86emuOp_dec_register,
5229/* 0x49 */ x86emuOp_dec_register,
5230/* 0x4a */ x86emuOp_dec_register,
5231/* 0x4b */ x86emuOp_dec_register,
5232/* 0x4c */ x86emuOp_dec_register,
5233/* 0x4d */ x86emuOp_dec_register,
5234/* 0x4e */ x86emuOp_dec_register,
5235/* 0x4f */ x86emuOp_dec_register,
5236
5237/* 0x50 */ x86emuOp_push_register,
5238/* 0x51 */ x86emuOp_push_register,
5239/* 0x52 */ x86emuOp_push_register,
5240/* 0x53 */ x86emuOp_push_register,
5241/* 0x54 */ x86emuOp_push_register,
5242/* 0x55 */ x86emuOp_push_register,
5243/* 0x56 */ x86emuOp_push_register,
5244/* 0x57 */ x86emuOp_push_register,
5245
5246/* 0x58 */ x86emuOp_pop_register,
5247/* 0x59 */ x86emuOp_pop_register,
5248/* 0x5a */ x86emuOp_pop_register,
5249/* 0x5b */ x86emuOp_pop_register,
5250/* 0x5c */ x86emuOp_pop_register,
5251/* 0x5d */ x86emuOp_pop_register,
5252/* 0x5e */ x86emuOp_pop_register,
5253/* 0x5f */ x86emuOp_pop_register,
5254
5255/* 0x60 */ x86emuOp_push_all,
5256/* 0x61 */ x86emuOp_pop_all,
5257/* 0x62 */ x86emuOp_illegal_op, /* bound */
5258/* 0x63 */ x86emuOp_illegal_op, /* arpl */
5259/* 0x64 */ x86emuOp_segovr_FS,
5260/* 0x65 */ x86emuOp_segovr_GS,
5261/* 0x66 */ x86emuOp_prefix_data,
5262/* 0x67 */ x86emuOp_prefix_addr,
5263
5264/* 0x68 */ x86emuOp_push_word_IMM,
5265/* 0x69 */ x86emuOp_imul_word_IMM,
5266/* 0x6a */ x86emuOp_push_byte_IMM,
5267/* 0x6b */ x86emuOp_imul_byte_IMM,
5268/* 0x6c */ x86emuOp_ins_byte,
5269/* 0x6d */ x86emuOp_ins_word,
5270/* 0x6e */ x86emuOp_outs_byte,
5271/* 0x6f */ x86emuOp_outs_word,
5272
5273/* 0x70 */ x86emuOp_jump_near_cond,
5274/* 0x71 */ x86emuOp_jump_near_cond,
5275/* 0x72 */ x86emuOp_jump_near_cond,
5276/* 0x73 */ x86emuOp_jump_near_cond,
5277/* 0x74 */ x86emuOp_jump_near_cond,
5278/* 0x75 */ x86emuOp_jump_near_cond,
5279/* 0x76 */ x86emuOp_jump_near_cond,
5280/* 0x77 */ x86emuOp_jump_near_cond,
5281
5282/* 0x78 */ x86emuOp_jump_near_cond,
5283/* 0x79 */ x86emuOp_jump_near_cond,
5284/* 0x7a */ x86emuOp_jump_near_cond,
5285/* 0x7b */ x86emuOp_jump_near_cond,
5286/* 0x7c */ x86emuOp_jump_near_cond,
5287/* 0x7d */ x86emuOp_jump_near_cond,
5288/* 0x7e */ x86emuOp_jump_near_cond,
5289/* 0x7f */ x86emuOp_jump_near_cond,
5290
5291/* 0x80 */ x86emuOp_opc80_byte_RM_IMM,
5292/* 0x81 */ x86emuOp_opc81_word_RM_IMM,
5293/* 0x82 */ x86emuOp_opc82_byte_RM_IMM,
5294/* 0x83 */ x86emuOp_opc83_word_RM_IMM,
5295/* 0x84 */ x86emuOp_test_byte_RM_R,
5296/* 0x85 */ x86emuOp_test_word_RM_R,
5297/* 0x86 */ x86emuOp_xchg_byte_RM_R,
5298/* 0x87 */ x86emuOp_xchg_word_RM_R,
5299
5300/* 0x88 */ x86emuOp_mov_byte_RM_R,
5301/* 0x89 */ x86emuOp_mov_word_RM_R,
5302/* 0x8a */ x86emuOp_mov_byte_R_RM,
5303/* 0x8b */ x86emuOp_mov_word_R_RM,
5304/* 0x8c */ x86emuOp_mov_word_RM_SR,
5305/* 0x8d */ x86emuOp_lea_word_R_M,
5306/* 0x8e */ x86emuOp_mov_word_SR_RM,
5307/* 0x8f */ x86emuOp_pop_RM,
5308
5309/* 0x90 */ x86emuOp_nop,
5310/* 0x91 */ x86emuOp_xchg_word_AX_register,
5311/* 0x92 */ x86emuOp_xchg_word_AX_register,
5312/* 0x93 */ x86emuOp_xchg_word_AX_register,
5313/* 0x94 */ x86emuOp_xchg_word_AX_register,
5314/* 0x95 */ x86emuOp_xchg_word_AX_register,
5315/* 0x96 */ x86emuOp_xchg_word_AX_register,
5316/* 0x97 */ x86emuOp_xchg_word_AX_register,
5317
5318/* 0x98 */ x86emuOp_cbw,
5319/* 0x99 */ x86emuOp_cwd,
5320/* 0x9a */ x86emuOp_call_far_IMM,
5321/* 0x9b */ x86emuOp_wait,
5322/* 0x9c */ x86emuOp_pushf_word,
5323/* 0x9d */ x86emuOp_popf_word,
5324/* 0x9e */ x86emuOp_sahf,
5325/* 0x9f */ x86emuOp_lahf,
5326
5327/* 0xa0 */ x86emuOp_mov_AL_M_IMM,
5328/* 0xa1 */ x86emuOp_mov_AX_M_IMM,
5329/* 0xa2 */ x86emuOp_mov_M_AL_IMM,
5330/* 0xa3 */ x86emuOp_mov_M_AX_IMM,
5331/* 0xa4 */ x86emuOp_movs_byte,
5332/* 0xa5 */ x86emuOp_movs_word,
5333/* 0xa6 */ x86emuOp_cmps_byte,
5334/* 0xa7 */ x86emuOp_cmps_word,
5335/* 0xa8 */ x86emuOp_test_AL_IMM,
5336/* 0xa9 */ x86emuOp_test_AX_IMM,
5337/* 0xaa */ x86emuOp_stos_byte,
5338/* 0xab */ x86emuOp_stos_word,
5339/* 0xac */ x86emuOp_lods_byte,
5340/* 0xad */ x86emuOp_lods_word,
5341/* 0xac */ x86emuOp_scas_byte,
5342/* 0xad */ x86emuOp_scas_word,
5343
5344/* 0xb0 */ x86emuOp_mov_byte_register_IMM,
5345/* 0xb1 */ x86emuOp_mov_byte_register_IMM,
5346/* 0xb2 */ x86emuOp_mov_byte_register_IMM,
5347/* 0xb3 */ x86emuOp_mov_byte_register_IMM,
5348/* 0xb4 */ x86emuOp_mov_byte_register_IMM,
5349/* 0xb5 */ x86emuOp_mov_byte_register_IMM,
5350/* 0xb6 */ x86emuOp_mov_byte_register_IMM,
5351/* 0xb7 */ x86emuOp_mov_byte_register_IMM,
5352
5353/* 0xb8 */ x86emuOp_mov_word_register_IMM,
5354/* 0xb9 */ x86emuOp_mov_word_register_IMM,
5355/* 0xba */ x86emuOp_mov_word_register_IMM,
5356/* 0xbb */ x86emuOp_mov_word_register_IMM,
5357/* 0xbc */ x86emuOp_mov_word_register_IMM,
5358/* 0xbd */ x86emuOp_mov_word_register_IMM,
5359/* 0xbe */ x86emuOp_mov_word_register_IMM,
5360/* 0xbf */ x86emuOp_mov_word_register_IMM,
5361
5362/* 0xc0 */ x86emuOp_opcC0_byte_RM_MEM,
5363/* 0xc1 */ x86emuOp_opcC1_word_RM_MEM,
5364/* 0xc2 */ x86emuOp_ret_near_IMM,
5365/* 0xc3 */ x86emuOp_ret_near,
5366/* 0xc4 */ x86emuOp_les_R_IMM,
5367/* 0xc5 */ x86emuOp_lds_R_IMM,
5368/* 0xc6 */ x86emuOp_mov_byte_RM_IMM,
5369/* 0xc7 */ x86emuOp_mov_word_RM_IMM,
5370/* 0xc8 */ x86emuOp_enter,
5371/* 0xc9 */ x86emuOp_leave,
5372/* 0xca */ x86emuOp_ret_far_IMM,
5373/* 0xcb */ x86emuOp_ret_far,
5374/* 0xcc */ x86emuOp_int3,
5375/* 0xcd */ x86emuOp_int_IMM,
5376/* 0xce */ x86emuOp_into,
5377/* 0xcf */ x86emuOp_iret,
5378
5379/* 0xd0 */ x86emuOp_opcD0_byte_RM_1,
5380/* 0xd1 */ x86emuOp_opcD1_word_RM_1,
5381/* 0xd2 */ x86emuOp_opcD2_byte_RM_CL,
5382/* 0xd3 */ x86emuOp_opcD3_word_RM_CL,
5383/* 0xd4 */ x86emuOp_aam,
5384/* 0xd5 */ x86emuOp_aad,
5385/* 0xd6 */ x86emuOp_illegal_op, /* Undocumented SETALC instruction */
5386/* 0xd7 */ x86emuOp_xlat,
5387/* 0xd8 */ NULL, /*x86emuOp_esc_coprocess_d8,*/
5388/* 0xd9 */ NULL, /*x86emuOp_esc_coprocess_d9,*/
5389/* 0xda */ NULL, /*x86emuOp_esc_coprocess_da,*/
5390/* 0xdb */ NULL, /*x86emuOp_esc_coprocess_db,*/
5391/* 0xdc */ NULL, /*x86emuOp_esc_coprocess_dc,*/
5392/* 0xdd */ NULL, /*x86emuOp_esc_coprocess_dd,*/
5393/* 0xde */ NULL, /*x86emuOp_esc_coprocess_de,*/
5394/* 0xdf */ NULL, /*x86emuOp_esc_coprocess_df,*/
5395
5396/* 0xe0 */ x86emuOp_loopne,
5397/* 0xe1 */ x86emuOp_loope,
5398/* 0xe2 */ x86emuOp_loop,
5399/* 0xe3 */ x86emuOp_jcxz,
5400/* 0xe4 */ x86emuOp_in_byte_AL_IMM,
5401/* 0xe5 */ x86emuOp_in_word_AX_IMM,
5402/* 0xe6 */ x86emuOp_out_byte_IMM_AL,
5403/* 0xe7 */ x86emuOp_out_word_IMM_AX,
5404
5405/* 0xe8 */ x86emuOp_call_near_IMM,
5406/* 0xe9 */ x86emuOp_jump_near_IMM,
5407/* 0xea */ x86emuOp_jump_far_IMM,
5408/* 0xeb */ x86emuOp_jump_byte_IMM,
5409/* 0xec */ x86emuOp_in_byte_AL_DX,
5410/* 0xed */ x86emuOp_in_word_AX_DX,
5411/* 0xee */ x86emuOp_out_byte_DX_AL,
5412/* 0xef */ x86emuOp_out_word_DX_AX,
5413
5414/* 0xf0 */ x86emuOp_lock,
5415/* 0xf1 */ x86emuOp_illegal_op,
5416/* 0xf2 */ x86emuOp_repne,
5417/* 0xf3 */ x86emuOp_repe,
5418/* 0xf4 */ x86emuOp_halt,
5419/* 0xf5 */ x86emuOp_cmc,
5420/* 0xf6 */ x86emuOp_opcF6_byte_RM,
5421/* 0xf7 */ x86emuOp_opcF7_word_RM,
5422
5423/* 0xf8 */ x86emuOp_clc,
5424/* 0xf9 */ x86emuOp_stc,
5425/* 0xfa */ x86emuOp_cli,
5426/* 0xfb */ x86emuOp_sti,
5427/* 0xfc */ x86emuOp_cld,
5428/* 0xfd */ x86emuOp_std,
5429/* 0xfe */ x86emuOp_opcFE_byte_RM,
5430/* 0xff */ x86emuOp_opcFF_word_RM,
5431};