blob: f8e093d751ae59adbeed9329b09cf9dc8ee1e2f5 [file] [log] [blame]
Jason Jina63ce952007-07-06 08:34:56 +08001/****************************************************************************
2* Realmode X86 Emulator Library
3*
Kumar Gala6a6d9482009-07-28 21:49:52 -05004* Copyright (C) 2007 Freescale Semiconductor, Inc.
Jason Jina63ce952007-07-06 08:34:56 +08005* 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*
Jason Jina63ce952007-07-06 08:34:56 +080073****************************************************************************/
74
Michal Simekc73a4772007-08-16 10:46:28 +020075#include <common.h>
Michal Simek952d8612007-08-15 21:15:05 +020076#include "x86emu/x86emui.h"
77
Jason Jina63ce952007-07-06 08:34:56 +080078/*----------------------------- Implementation ----------------------------*/
79
80/* constant arrays to do several instructions in just one function */
81
82#ifdef DEBUG
83static char *x86emu_GenOpName[8] = {
84 "ADD", "OR", "ADC", "SBB", "AND", "SUB", "XOR", "CMP"};
85#endif
86
87/* used by several opcodes */
Ed Swarthout1cffcde2008-10-09 01:27:18 -050088static u8 (*genop_byte_operation[])(u8 d, u8 s) =
Jason Jina63ce952007-07-06 08:34:56 +080089{
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020090 add_byte, /* 00 */
91 or_byte, /* 01 */
92 adc_byte, /* 02 */
93 sbb_byte, /* 03 */
94 and_byte, /* 04 */
95 sub_byte, /* 05 */
96 xor_byte, /* 06 */
97 cmp_byte, /* 07 */
Jason Jina63ce952007-07-06 08:34:56 +080098};
99
Ed Swarthout1cffcde2008-10-09 01:27:18 -0500100static u16 (*genop_word_operation[])(u16 d, u16 s) =
Jason Jina63ce952007-07-06 08:34:56 +0800101{
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200102 add_word, /*00 */
103 or_word, /*01 */
104 adc_word, /*02 */
105 sbb_word, /*03 */
106 and_word, /*04 */
107 sub_word, /*05 */
108 xor_word, /*06 */
109 cmp_word, /*07 */
Jason Jina63ce952007-07-06 08:34:56 +0800110};
111
Ed Swarthout1cffcde2008-10-09 01:27:18 -0500112static u32 (*genop_long_operation[])(u32 d, u32 s) =
Jason Jina63ce952007-07-06 08:34:56 +0800113{
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200114 add_long, /*00 */
115 or_long, /*01 */
116 adc_long, /*02 */
117 sbb_long, /*03 */
118 and_long, /*04 */
119 sub_long, /*05 */
120 xor_long, /*06 */
121 cmp_long, /*07 */
Jason Jina63ce952007-07-06 08:34:56 +0800122};
123
124/* used by opcodes 80, c0, d0, and d2. */
Ed Swarthout1cffcde2008-10-09 01:27:18 -0500125static u8(*opcD0_byte_operation[])(u8 d, u8 s) =
Jason Jina63ce952007-07-06 08:34:56 +0800126{
127 rol_byte,
128 ror_byte,
129 rcl_byte,
130 rcr_byte,
131 shl_byte,
132 shr_byte,
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200133 shl_byte, /* sal_byte === shl_byte by definition */
Jason Jina63ce952007-07-06 08:34:56 +0800134 sar_byte,
135};
136
137/* used by opcodes c1, d1, and d3. */
Ed Swarthout1cffcde2008-10-09 01:27:18 -0500138static u16(*opcD1_word_operation[])(u16 s, u8 d) =
Jason Jina63ce952007-07-06 08:34:56 +0800139{
140 rol_word,
141 ror_word,
142 rcl_word,
143 rcr_word,
144 shl_word,
145 shr_word,
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200146 shl_word, /* sal_byte === shl_byte by definition */
Jason Jina63ce952007-07-06 08:34:56 +0800147 sar_word,
148};
149
150/* used by opcodes c1, d1, and d3. */
Ed Swarthout1cffcde2008-10-09 01:27:18 -0500151static u32 (*opcD1_long_operation[])(u32 s, u8 d) =
Jason Jina63ce952007-07-06 08:34:56 +0800152{
153 rol_long,
154 ror_long,
155 rcl_long,
156 rcr_long,
157 shl_long,
158 shr_long,
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200159 shl_long, /* sal_byte === shl_byte by definition */
Jason Jina63ce952007-07-06 08:34:56 +0800160 sar_long,
161};
162
163#ifdef DEBUG
164
165static char *opF6_names[8] =
166 { "TEST\t", "", "NOT\t", "NEG\t", "MUL\t", "IMUL\t", "DIV\t", "IDIV\t" };
167
168#endif
169
170/****************************************************************************
171PARAMETERS:
172op1 - Instruction op code
173
174REMARKS:
175Handles illegal opcodes.
176****************************************************************************/
177void x86emuOp_illegal_op(
178 u8 op1)
179{
180 START_OF_INSTR();
181 if (M.x86.R_SP != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200182 DECODE_PRINTF("ILLEGAL X86 OPCODE\n");
183 TRACE_REGS();
184 DB( printk("%04x:%04x: %02X ILLEGAL X86 OPCODE!\n",
185 M.x86.R_CS, M.x86.R_IP-1,op1));
186 HALT_SYS();
187 }
Jason Jina63ce952007-07-06 08:34:56 +0800188 else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200189 /* If we get here, it means the stack pointer is back to zero
190 * so we are just returning from an emulator service call
191 * so therte is no need to display an error message. We trap
192 * the emulator with an 0xF1 opcode to finish the service
193 * call.
194 */
195 X86EMU_halt_sys();
196 }
Jason Jina63ce952007-07-06 08:34:56 +0800197 END_OF_INSTR();
198}
199
200/****************************************************************************
201REMARKS:
202Handles opcodes 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38
203****************************************************************************/
204void x86emuOp_genop_byte_RM_R(u8 op1)
205{
206 int mod, rl, rh;
207 uint destoffset;
208 u8 *destreg, *srcreg;
209 u8 destval;
210
211 op1 = (op1 >> 3) & 0x7;
212
213 START_OF_INSTR();
214 DECODE_PRINTF(x86emu_GenOpName[op1]);
215 DECODE_PRINTF("\t");
216 FETCH_DECODE_MODRM(mod, rh, rl);
217 if(mod<3)
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200218 { destoffset = decode_rmXX_address(mod,rl);
219 DECODE_PRINTF(",");
220 destval = fetch_data_byte(destoffset);
221 srcreg = DECODE_RM_BYTE_REGISTER(rh);
222 DECODE_PRINTF("\n");
223 TRACE_AND_STEP();
224 destval = genop_byte_operation[op1](destval, *srcreg);
225 store_data_byte(destoffset, destval);
226 }
Jason Jina63ce952007-07-06 08:34:56 +0800227 else
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200228 { /* register to register */
229 destreg = DECODE_RM_BYTE_REGISTER(rl);
230 DECODE_PRINTF(",");
231 srcreg = DECODE_RM_BYTE_REGISTER(rh);
232 DECODE_PRINTF("\n");
233 TRACE_AND_STEP();
234 *destreg = genop_byte_operation[op1](*destreg, *srcreg);
235 }
Jason Jina63ce952007-07-06 08:34:56 +0800236 DECODE_CLEAR_SEGOVR();
237 END_OF_INSTR();
238}
239
240/****************************************************************************
241REMARKS:
242Handles opcodes 0x01, 0x09, 0x11, 0x19, 0x21, 0x29, 0x31, 0x39
243****************************************************************************/
244void x86emuOp_genop_word_RM_R(u8 op1)
245{
246 int mod, rl, rh;
247 uint destoffset;
248
249 op1 = (op1 >> 3) & 0x7;
250
251 START_OF_INSTR();
252 DECODE_PRINTF(x86emu_GenOpName[op1]);
253 DECODE_PRINTF("\t");
254 FETCH_DECODE_MODRM(mod, rh, rl);
255
256 if(mod<3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200257 destoffset = decode_rmXX_address(mod,rl);
258 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
259 u32 destval;
260 u32 *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +0800261
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200262 DECODE_PRINTF(",");
263 destval = fetch_data_long(destoffset);
264 srcreg = DECODE_RM_LONG_REGISTER(rh);
265 DECODE_PRINTF("\n");
266 TRACE_AND_STEP();
267 destval = genop_long_operation[op1](destval, *srcreg);
268 store_data_long(destoffset, destval);
269 } else {
270 u16 destval;
271 u16 *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +0800272
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200273 DECODE_PRINTF(",");
274 destval = fetch_data_word(destoffset);
275 srcreg = DECODE_RM_WORD_REGISTER(rh);
276 DECODE_PRINTF("\n");
277 TRACE_AND_STEP();
278 destval = genop_word_operation[op1](destval, *srcreg);
279 store_data_word(destoffset, destval);
280 }
281 } else { /* register to register */
282 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
283 u32 *destreg,*srcreg;
Jason Jina63ce952007-07-06 08:34:56 +0800284
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200285 destreg = DECODE_RM_LONG_REGISTER(rl);
286 DECODE_PRINTF(",");
287 srcreg = DECODE_RM_LONG_REGISTER(rh);
288 DECODE_PRINTF("\n");
289 TRACE_AND_STEP();
290 *destreg = genop_long_operation[op1](*destreg, *srcreg);
291 } else {
292 u16 *destreg,*srcreg;
Jason Jina63ce952007-07-06 08:34:56 +0800293
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200294 destreg = DECODE_RM_WORD_REGISTER(rl);
295 DECODE_PRINTF(",");
296 srcreg = DECODE_RM_WORD_REGISTER(rh);
297 DECODE_PRINTF("\n");
298 TRACE_AND_STEP();
299 *destreg = genop_word_operation[op1](*destreg, *srcreg);
300 }
Jason Jina63ce952007-07-06 08:34:56 +0800301 }
302 DECODE_CLEAR_SEGOVR();
303 END_OF_INSTR();
304}
305
306/****************************************************************************
307REMARKS:
308Handles opcodes 0x02, 0x0a, 0x12, 0x1a, 0x22, 0x2a, 0x32, 0x3a
309****************************************************************************/
310void x86emuOp_genop_byte_R_RM(u8 op1)
311{
312 int mod, rl, rh;
313 u8 *destreg, *srcreg;
314 uint srcoffset;
315 u8 srcval;
316
317 op1 = (op1 >> 3) & 0x7;
318
319 START_OF_INSTR();
320 DECODE_PRINTF(x86emu_GenOpName[op1]);
321 DECODE_PRINTF("\t");
322 FETCH_DECODE_MODRM(mod, rh, rl);
323 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200324 destreg = DECODE_RM_BYTE_REGISTER(rh);
325 DECODE_PRINTF(",");
326 srcoffset = decode_rmXX_address(mod,rl);
327 srcval = fetch_data_byte(srcoffset);
328 } else { /* register to register */
329 destreg = DECODE_RM_BYTE_REGISTER(rh);
330 DECODE_PRINTF(",");
331 srcreg = DECODE_RM_BYTE_REGISTER(rl);
332 srcval = *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +0800333 }
334 DECODE_PRINTF("\n");
335 TRACE_AND_STEP();
336 *destreg = genop_byte_operation[op1](*destreg, srcval);
337
338 DECODE_CLEAR_SEGOVR();
339 END_OF_INSTR();
340}
341
342/****************************************************************************
343REMARKS:
344Handles opcodes 0x03, 0x0b, 0x13, 0x1b, 0x23, 0x2b, 0x33, 0x3b
345****************************************************************************/
346void x86emuOp_genop_word_R_RM(u8 op1)
347{
348 int mod, rl, rh;
349 uint srcoffset;
350 u32 *destreg32, srcval;
351 u16 *destreg;
352
353 op1 = (op1 >> 3) & 0x7;
354
355 START_OF_INSTR();
356 DECODE_PRINTF(x86emu_GenOpName[op1]);
357 DECODE_PRINTF("\t");
358 FETCH_DECODE_MODRM(mod, rh, rl);
359 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200360 srcoffset = decode_rmXX_address(mod,rl);
361 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
362 destreg32 = DECODE_RM_LONG_REGISTER(rh);
363 DECODE_PRINTF(",");
364 srcval = fetch_data_long(srcoffset);
365 DECODE_PRINTF("\n");
366 TRACE_AND_STEP();
367 *destreg32 = genop_long_operation[op1](*destreg32, srcval);
368 } else {
369 destreg = DECODE_RM_WORD_REGISTER(rh);
370 DECODE_PRINTF(",");
371 srcval = fetch_data_word(srcoffset);
372 DECODE_PRINTF("\n");
373 TRACE_AND_STEP();
374 *destreg = genop_word_operation[op1](*destreg, srcval);
375 }
376 } else { /* register to register */
377 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
378 u32 *srcreg;
379 destreg32 = DECODE_RM_LONG_REGISTER(rh);
380 DECODE_PRINTF(",");
381 srcreg = DECODE_RM_LONG_REGISTER(rl);
382 DECODE_PRINTF("\n");
383 TRACE_AND_STEP();
384 *destreg32 = genop_long_operation[op1](*destreg32, *srcreg);
385 } else {
386 u16 *srcreg;
387 destreg = DECODE_RM_WORD_REGISTER(rh);
388 DECODE_PRINTF(",");
389 srcreg = DECODE_RM_WORD_REGISTER(rl);
390 DECODE_PRINTF("\n");
391 TRACE_AND_STEP();
392 *destreg = genop_word_operation[op1](*destreg, *srcreg);
393 }
Jason Jina63ce952007-07-06 08:34:56 +0800394 }
395 DECODE_CLEAR_SEGOVR();
396 END_OF_INSTR();
397}
398
399/****************************************************************************
400REMARKS:
401Handles opcodes 0x04, 0x0c, 0x14, 0x1c, 0x24, 0x2c, 0x34, 0x3c
402****************************************************************************/
403void x86emuOp_genop_byte_AL_IMM(u8 op1)
404{
405 u8 srcval;
406
407 op1 = (op1 >> 3) & 0x7;
408
409 START_OF_INSTR();
410 DECODE_PRINTF(x86emu_GenOpName[op1]);
411 DECODE_PRINTF("\tAL,");
412 srcval = fetch_byte_imm();
413 DECODE_PRINTF2("%x\n", srcval);
414 TRACE_AND_STEP();
415 M.x86.R_AL = genop_byte_operation[op1](M.x86.R_AL, srcval);
416 DECODE_CLEAR_SEGOVR();
417 END_OF_INSTR();
418}
419
420/****************************************************************************
421REMARKS:
422Handles opcodes 0x05, 0x0d, 0x15, 0x1d, 0x25, 0x2d, 0x35, 0x3d
423****************************************************************************/
424void x86emuOp_genop_word_AX_IMM(u8 op1)
425{
426 u32 srcval;
427
428 op1 = (op1 >> 3) & 0x7;
429
430 START_OF_INSTR();
431 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200432 DECODE_PRINTF(x86emu_GenOpName[op1]);
433 DECODE_PRINTF("\tEAX,");
434 srcval = fetch_long_imm();
Jason Jina63ce952007-07-06 08:34:56 +0800435 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200436 DECODE_PRINTF(x86emu_GenOpName[op1]);
437 DECODE_PRINTF("\tAX,");
438 srcval = fetch_word_imm();
Jason Jina63ce952007-07-06 08:34:56 +0800439 }
440 DECODE_PRINTF2("%x\n", srcval);
441 TRACE_AND_STEP();
442 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200443 M.x86.R_EAX = genop_long_operation[op1](M.x86.R_EAX, srcval);
Jason Jina63ce952007-07-06 08:34:56 +0800444 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200445 M.x86.R_AX = genop_word_operation[op1](M.x86.R_AX, (u16)srcval);
Jason Jina63ce952007-07-06 08:34:56 +0800446 }
447 DECODE_CLEAR_SEGOVR();
448 END_OF_INSTR();
449}
450
451/****************************************************************************
452REMARKS:
453Handles opcode 0x06
454****************************************************************************/
455void x86emuOp_push_ES(u8 X86EMU_UNUSED(op1))
456{
457 START_OF_INSTR();
458 DECODE_PRINTF("PUSH\tES\n");
459 TRACE_AND_STEP();
460 push_word(M.x86.R_ES);
461 DECODE_CLEAR_SEGOVR();
462 END_OF_INSTR();
463}
464
465/****************************************************************************
466REMARKS:
467Handles opcode 0x07
468****************************************************************************/
469void x86emuOp_pop_ES(u8 X86EMU_UNUSED(op1))
470{
471 START_OF_INSTR();
472 DECODE_PRINTF("POP\tES\n");
473 TRACE_AND_STEP();
474 M.x86.R_ES = pop_word();
475 DECODE_CLEAR_SEGOVR();
476 END_OF_INSTR();
477}
478
479/****************************************************************************
480REMARKS:
481Handles opcode 0x0e
482****************************************************************************/
483void x86emuOp_push_CS(u8 X86EMU_UNUSED(op1))
484{
485 START_OF_INSTR();
486 DECODE_PRINTF("PUSH\tCS\n");
487 TRACE_AND_STEP();
488 push_word(M.x86.R_CS);
489 DECODE_CLEAR_SEGOVR();
490 END_OF_INSTR();
491}
492
493/****************************************************************************
494REMARKS:
495Handles opcode 0x0f. Escape for two-byte opcode (286 or better)
496****************************************************************************/
497void x86emuOp_two_byte(u8 X86EMU_UNUSED(op1))
498{
499 u8 op2 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
500 INC_DECODED_INST_LEN(1);
501 (*x86emu_optab2[op2])(op2);
502}
503
504/****************************************************************************
505REMARKS:
506Handles opcode 0x16
507****************************************************************************/
508void x86emuOp_push_SS(u8 X86EMU_UNUSED(op1))
509{
510 START_OF_INSTR();
511 DECODE_PRINTF("PUSH\tSS\n");
512 TRACE_AND_STEP();
513 push_word(M.x86.R_SS);
514 DECODE_CLEAR_SEGOVR();
515 END_OF_INSTR();
516}
517
518/****************************************************************************
519REMARKS:
520Handles opcode 0x17
521****************************************************************************/
522void x86emuOp_pop_SS(u8 X86EMU_UNUSED(op1))
523{
524 START_OF_INSTR();
525 DECODE_PRINTF("POP\tSS\n");
526 TRACE_AND_STEP();
527 M.x86.R_SS = pop_word();
528 DECODE_CLEAR_SEGOVR();
529 END_OF_INSTR();
530}
531
532/****************************************************************************
533REMARKS:
534Handles opcode 0x1e
535****************************************************************************/
536void x86emuOp_push_DS(u8 X86EMU_UNUSED(op1))
537{
538 START_OF_INSTR();
539 DECODE_PRINTF("PUSH\tDS\n");
540 TRACE_AND_STEP();
541 push_word(M.x86.R_DS);
542 DECODE_CLEAR_SEGOVR();
543 END_OF_INSTR();
544}
545
546/****************************************************************************
547REMARKS:
548Handles opcode 0x1f
549****************************************************************************/
550void x86emuOp_pop_DS(u8 X86EMU_UNUSED(op1))
551{
552 START_OF_INSTR();
553 DECODE_PRINTF("POP\tDS\n");
554 TRACE_AND_STEP();
555 M.x86.R_DS = pop_word();
556 DECODE_CLEAR_SEGOVR();
557 END_OF_INSTR();
558}
559
560/****************************************************************************
561REMARKS:
562Handles opcode 0x26
563****************************************************************************/
564void x86emuOp_segovr_ES(u8 X86EMU_UNUSED(op1))
565{
566 START_OF_INSTR();
567 DECODE_PRINTF("ES:\n");
568 TRACE_AND_STEP();
569 M.x86.mode |= SYSMODE_SEGOVR_ES;
570 /*
571 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
572 * opcode subroutines we do not want to do this.
573 */
574 END_OF_INSTR();
575}
576
577/****************************************************************************
578REMARKS:
579Handles opcode 0x27
580****************************************************************************/
581void x86emuOp_daa(u8 X86EMU_UNUSED(op1))
582{
583 START_OF_INSTR();
584 DECODE_PRINTF("DAA\n");
585 TRACE_AND_STEP();
586 M.x86.R_AL = daa_byte(M.x86.R_AL);
587 DECODE_CLEAR_SEGOVR();
588 END_OF_INSTR();
589}
590
591/****************************************************************************
592REMARKS:
593Handles opcode 0x2e
594****************************************************************************/
595void x86emuOp_segovr_CS(u8 X86EMU_UNUSED(op1))
596{
597 START_OF_INSTR();
598 DECODE_PRINTF("CS:\n");
599 TRACE_AND_STEP();
600 M.x86.mode |= SYSMODE_SEGOVR_CS;
601 /* note no DECODE_CLEAR_SEGOVR here. */
602 END_OF_INSTR();
603}
604
605/****************************************************************************
606REMARKS:
607Handles opcode 0x2f
608****************************************************************************/
609void x86emuOp_das(u8 X86EMU_UNUSED(op1))
610{
611 START_OF_INSTR();
612 DECODE_PRINTF("DAS\n");
613 TRACE_AND_STEP();
614 M.x86.R_AL = das_byte(M.x86.R_AL);
615 DECODE_CLEAR_SEGOVR();
616 END_OF_INSTR();
617}
618
619/****************************************************************************
620REMARKS:
621Handles opcode 0x36
622****************************************************************************/
623void x86emuOp_segovr_SS(u8 X86EMU_UNUSED(op1))
624{
625 START_OF_INSTR();
626 DECODE_PRINTF("SS:\n");
627 TRACE_AND_STEP();
628 M.x86.mode |= SYSMODE_SEGOVR_SS;
629 /* no DECODE_CLEAR_SEGOVR ! */
630 END_OF_INSTR();
631}
632
633/****************************************************************************
634REMARKS:
635Handles opcode 0x37
636****************************************************************************/
637void x86emuOp_aaa(u8 X86EMU_UNUSED(op1))
638{
639 START_OF_INSTR();
640 DECODE_PRINTF("AAA\n");
641 TRACE_AND_STEP();
642 M.x86.R_AX = aaa_word(M.x86.R_AX);
643 DECODE_CLEAR_SEGOVR();
644 END_OF_INSTR();
645}
646
647/****************************************************************************
648REMARKS:
649Handles opcode 0x3e
650****************************************************************************/
651void x86emuOp_segovr_DS(u8 X86EMU_UNUSED(op1))
652{
653 START_OF_INSTR();
654 DECODE_PRINTF("DS:\n");
655 TRACE_AND_STEP();
656 M.x86.mode |= SYSMODE_SEGOVR_DS;
657 /* NO DECODE_CLEAR_SEGOVR! */
658 END_OF_INSTR();
659}
660
661/****************************************************************************
662REMARKS:
663Handles opcode 0x3f
664****************************************************************************/
665void x86emuOp_aas(u8 X86EMU_UNUSED(op1))
666{
667 START_OF_INSTR();
668 DECODE_PRINTF("AAS\n");
669 TRACE_AND_STEP();
670 M.x86.R_AX = aas_word(M.x86.R_AX);
671 DECODE_CLEAR_SEGOVR();
672 END_OF_INSTR();
673}
674
675/****************************************************************************
676REMARKS:
677Handles opcode 0x40 - 0x47
678****************************************************************************/
679void x86emuOp_inc_register(u8 op1)
680{
681 START_OF_INSTR();
682 op1 &= 0x7;
683 DECODE_PRINTF("INC\t");
684 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200685 u32 *reg;
686 reg = DECODE_RM_LONG_REGISTER(op1);
687 DECODE_PRINTF("\n");
688 TRACE_AND_STEP();
689 *reg = inc_long(*reg);
Jason Jina63ce952007-07-06 08:34:56 +0800690 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200691 u16 *reg;
692 reg = DECODE_RM_WORD_REGISTER(op1);
693 DECODE_PRINTF("\n");
694 TRACE_AND_STEP();
695 *reg = inc_word(*reg);
Jason Jina63ce952007-07-06 08:34:56 +0800696 }
697 DECODE_CLEAR_SEGOVR();
698 END_OF_INSTR();
699}
700
701/****************************************************************************
702REMARKS:
703Handles opcode 0x48 - 0x4F
704****************************************************************************/
705void x86emuOp_dec_register(u8 op1)
706{
707 START_OF_INSTR();
708 op1 &= 0x7;
709 DECODE_PRINTF("DEC\t");
710 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200711 u32 *reg;
712 reg = DECODE_RM_LONG_REGISTER(op1);
713 DECODE_PRINTF("\n");
714 TRACE_AND_STEP();
715 *reg = dec_long(*reg);
Jason Jina63ce952007-07-06 08:34:56 +0800716 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200717 u16 *reg;
718 reg = DECODE_RM_WORD_REGISTER(op1);
719 DECODE_PRINTF("\n");
720 TRACE_AND_STEP();
721 *reg = dec_word(*reg);
Jason Jina63ce952007-07-06 08:34:56 +0800722 }
723 DECODE_CLEAR_SEGOVR();
724 END_OF_INSTR();
725}
726
727/****************************************************************************
728REMARKS:
729Handles opcode 0x50 - 0x57
730****************************************************************************/
731void x86emuOp_push_register(u8 op1)
732{
733 START_OF_INSTR();
734 op1 &= 0x7;
735 DECODE_PRINTF("PUSH\t");
736 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200737 u32 *reg;
738 reg = DECODE_RM_LONG_REGISTER(op1);
739 DECODE_PRINTF("\n");
740 TRACE_AND_STEP();
741 push_long(*reg);
Jason Jina63ce952007-07-06 08:34:56 +0800742 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200743 u16 *reg;
744 reg = DECODE_RM_WORD_REGISTER(op1);
745 DECODE_PRINTF("\n");
746 TRACE_AND_STEP();
747 push_word(*reg);
Jason Jina63ce952007-07-06 08:34:56 +0800748 }
749 DECODE_CLEAR_SEGOVR();
750 END_OF_INSTR();
751}
752
753/****************************************************************************
754REMARKS:
755Handles opcode 0x58 - 0x5F
756****************************************************************************/
757void x86emuOp_pop_register(u8 op1)
758{
759 START_OF_INSTR();
760 op1 &= 0x7;
761 DECODE_PRINTF("POP\t");
762 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200763 u32 *reg;
764 reg = DECODE_RM_LONG_REGISTER(op1);
765 DECODE_PRINTF("\n");
766 TRACE_AND_STEP();
767 *reg = pop_long();
Jason Jina63ce952007-07-06 08:34:56 +0800768 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200769 u16 *reg;
770 reg = DECODE_RM_WORD_REGISTER(op1);
771 DECODE_PRINTF("\n");
772 TRACE_AND_STEP();
773 *reg = pop_word();
Jason Jina63ce952007-07-06 08:34:56 +0800774 }
775 DECODE_CLEAR_SEGOVR();
776 END_OF_INSTR();
777}
778
779/****************************************************************************
780REMARKS:
781Handles opcode 0x60
782****************************************************************************/
783void x86emuOp_push_all(u8 X86EMU_UNUSED(op1))
784{
785 START_OF_INSTR();
786 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200787 DECODE_PRINTF("PUSHAD\n");
Jason Jina63ce952007-07-06 08:34:56 +0800788 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200789 DECODE_PRINTF("PUSHA\n");
Jason Jina63ce952007-07-06 08:34:56 +0800790 }
791 TRACE_AND_STEP();
792 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200793 u32 old_sp = M.x86.R_ESP;
Jason Jina63ce952007-07-06 08:34:56 +0800794
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200795 push_long(M.x86.R_EAX);
796 push_long(M.x86.R_ECX);
797 push_long(M.x86.R_EDX);
798 push_long(M.x86.R_EBX);
799 push_long(old_sp);
800 push_long(M.x86.R_EBP);
801 push_long(M.x86.R_ESI);
802 push_long(M.x86.R_EDI);
Jason Jina63ce952007-07-06 08:34:56 +0800803 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200804 u16 old_sp = M.x86.R_SP;
Jason Jina63ce952007-07-06 08:34:56 +0800805
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200806 push_word(M.x86.R_AX);
807 push_word(M.x86.R_CX);
808 push_word(M.x86.R_DX);
809 push_word(M.x86.R_BX);
810 push_word(old_sp);
811 push_word(M.x86.R_BP);
812 push_word(M.x86.R_SI);
813 push_word(M.x86.R_DI);
Jason Jina63ce952007-07-06 08:34:56 +0800814 }
815 DECODE_CLEAR_SEGOVR();
816 END_OF_INSTR();
817}
818
819/****************************************************************************
820REMARKS:
821Handles opcode 0x61
822****************************************************************************/
823void x86emuOp_pop_all(u8 X86EMU_UNUSED(op1))
824{
825 START_OF_INSTR();
826 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200827 DECODE_PRINTF("POPAD\n");
Jason Jina63ce952007-07-06 08:34:56 +0800828 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200829 DECODE_PRINTF("POPA\n");
Jason Jina63ce952007-07-06 08:34:56 +0800830 }
831 TRACE_AND_STEP();
832 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200833 M.x86.R_EDI = pop_long();
834 M.x86.R_ESI = pop_long();
835 M.x86.R_EBP = pop_long();
836 M.x86.R_ESP += 4; /* skip ESP */
837 M.x86.R_EBX = pop_long();
838 M.x86.R_EDX = pop_long();
839 M.x86.R_ECX = pop_long();
840 M.x86.R_EAX = pop_long();
Jason Jina63ce952007-07-06 08:34:56 +0800841 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200842 M.x86.R_DI = pop_word();
843 M.x86.R_SI = pop_word();
844 M.x86.R_BP = pop_word();
845 M.x86.R_SP += 2; /* skip SP */
846 M.x86.R_BX = pop_word();
847 M.x86.R_DX = pop_word();
848 M.x86.R_CX = pop_word();
849 M.x86.R_AX = pop_word();
Jason Jina63ce952007-07-06 08:34:56 +0800850 }
851 DECODE_CLEAR_SEGOVR();
852 END_OF_INSTR();
853}
854
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200855/*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */
856/*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */
Jason Jina63ce952007-07-06 08:34:56 +0800857
858/****************************************************************************
859REMARKS:
860Handles opcode 0x64
861****************************************************************************/
862void x86emuOp_segovr_FS(u8 X86EMU_UNUSED(op1))
863{
864 START_OF_INSTR();
865 DECODE_PRINTF("FS:\n");
866 TRACE_AND_STEP();
867 M.x86.mode |= SYSMODE_SEGOVR_FS;
868 /*
869 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
870 * opcode subroutines we do not want to do this.
871 */
872 END_OF_INSTR();
873}
874
875/****************************************************************************
876REMARKS:
877Handles opcode 0x65
878****************************************************************************/
879void x86emuOp_segovr_GS(u8 X86EMU_UNUSED(op1))
880{
881 START_OF_INSTR();
882 DECODE_PRINTF("GS:\n");
883 TRACE_AND_STEP();
884 M.x86.mode |= SYSMODE_SEGOVR_GS;
885 /*
886 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
887 * opcode subroutines we do not want to do this.
888 */
889 END_OF_INSTR();
890}
891
892/****************************************************************************
893REMARKS:
894Handles opcode 0x66 - prefix for 32-bit register
895****************************************************************************/
896void x86emuOp_prefix_data(u8 X86EMU_UNUSED(op1))
897{
898 START_OF_INSTR();
899 DECODE_PRINTF("DATA:\n");
900 TRACE_AND_STEP();
901 M.x86.mode |= SYSMODE_PREFIX_DATA;
902 /* note no DECODE_CLEAR_SEGOVR here. */
903 END_OF_INSTR();
904}
905
906/****************************************************************************
907REMARKS:
908Handles opcode 0x67 - prefix for 32-bit address
909****************************************************************************/
910void x86emuOp_prefix_addr(u8 X86EMU_UNUSED(op1))
911{
912 START_OF_INSTR();
913 DECODE_PRINTF("ADDR:\n");
914 TRACE_AND_STEP();
915 M.x86.mode |= SYSMODE_PREFIX_ADDR;
916 /* note no DECODE_CLEAR_SEGOVR here. */
917 END_OF_INSTR();
918}
919
920/****************************************************************************
921REMARKS:
922Handles opcode 0x68
923****************************************************************************/
924void x86emuOp_push_word_IMM(u8 X86EMU_UNUSED(op1))
925{
926 u32 imm;
927
928 START_OF_INSTR();
929 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200930 imm = fetch_long_imm();
Jason Jina63ce952007-07-06 08:34:56 +0800931 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200932 imm = fetch_word_imm();
Jason Jina63ce952007-07-06 08:34:56 +0800933 }
934 DECODE_PRINTF2("PUSH\t%x\n", imm);
935 TRACE_AND_STEP();
936 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200937 push_long(imm);
Jason Jina63ce952007-07-06 08:34:56 +0800938 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200939 push_word((u16)imm);
Jason Jina63ce952007-07-06 08:34:56 +0800940 }
941 DECODE_CLEAR_SEGOVR();
942 END_OF_INSTR();
943}
944
945/****************************************************************************
946REMARKS:
947Handles opcode 0x69
948****************************************************************************/
949void x86emuOp_imul_word_IMM(u8 X86EMU_UNUSED(op1))
950{
951 int mod, rl, rh;
952 uint srcoffset;
953
954 START_OF_INSTR();
955 DECODE_PRINTF("IMUL\t");
956 FETCH_DECODE_MODRM(mod, rh, rl);
957 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200958 srcoffset = decode_rmXX_address(mod, rl);
959 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
960 u32 *destreg;
961 u32 srcval;
962 u32 res_lo,res_hi;
963 s32 imm;
Jason Jina63ce952007-07-06 08:34:56 +0800964
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200965 destreg = DECODE_RM_LONG_REGISTER(rh);
966 DECODE_PRINTF(",");
967 srcval = fetch_data_long(srcoffset);
968 imm = fetch_long_imm();
969 DECODE_PRINTF2(",%d\n", (s32)imm);
970 TRACE_AND_STEP();
971 imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
972 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
973 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
974 CLEAR_FLAG(F_CF);
975 CLEAR_FLAG(F_OF);
976 } else {
977 SET_FLAG(F_CF);
978 SET_FLAG(F_OF);
979 }
980 *destreg = (u32)res_lo;
981 } else {
982 u16 *destreg;
983 u16 srcval;
984 u32 res;
985 s16 imm;
Jason Jina63ce952007-07-06 08:34:56 +0800986
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200987 destreg = DECODE_RM_WORD_REGISTER(rh);
988 DECODE_PRINTF(",");
989 srcval = fetch_data_word(srcoffset);
990 imm = fetch_word_imm();
991 DECODE_PRINTF2(",%d\n", (s32)imm);
992 TRACE_AND_STEP();
993 res = (s16)srcval * (s16)imm;
994 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
995 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
996 CLEAR_FLAG(F_CF);
997 CLEAR_FLAG(F_OF);
998 } else {
999 SET_FLAG(F_CF);
1000 SET_FLAG(F_OF);
1001 }
1002 *destreg = (u16)res;
1003 }
1004 } else { /* register to register */
1005 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1006 u32 *destreg,*srcreg;
1007 u32 res_lo,res_hi;
1008 s32 imm;
Jason Jina63ce952007-07-06 08:34:56 +08001009
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001010 destreg = DECODE_RM_LONG_REGISTER(rh);
1011 DECODE_PRINTF(",");
1012 srcreg = DECODE_RM_LONG_REGISTER(rl);
1013 imm = fetch_long_imm();
1014 DECODE_PRINTF2(",%d\n", (s32)imm);
1015 TRACE_AND_STEP();
1016 imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
1017 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1018 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1019 CLEAR_FLAG(F_CF);
1020 CLEAR_FLAG(F_OF);
1021 } else {
1022 SET_FLAG(F_CF);
1023 SET_FLAG(F_OF);
1024 }
1025 *destreg = (u32)res_lo;
1026 } else {
1027 u16 *destreg,*srcreg;
1028 u32 res;
1029 s16 imm;
Jason Jina63ce952007-07-06 08:34:56 +08001030
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001031 destreg = DECODE_RM_WORD_REGISTER(rh);
1032 DECODE_PRINTF(",");
1033 srcreg = DECODE_RM_WORD_REGISTER(rl);
1034 imm = fetch_word_imm();
1035 DECODE_PRINTF2(",%d\n", (s32)imm);
1036 res = (s16)*srcreg * (s16)imm;
1037 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1038 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1039 CLEAR_FLAG(F_CF);
1040 CLEAR_FLAG(F_OF);
1041 } else {
1042 SET_FLAG(F_CF);
1043 SET_FLAG(F_OF);
1044 }
1045 *destreg = (u16)res;
1046 }
Jason Jina63ce952007-07-06 08:34:56 +08001047 }
1048 DECODE_CLEAR_SEGOVR();
1049 END_OF_INSTR();
1050}
1051
1052/****************************************************************************
1053REMARKS:
1054Handles opcode 0x6a
1055****************************************************************************/
1056void x86emuOp_push_byte_IMM(u8 X86EMU_UNUSED(op1))
1057{
1058 s16 imm;
1059
1060 START_OF_INSTR();
1061 imm = (s8)fetch_byte_imm();
1062 DECODE_PRINTF2("PUSH\t%d\n", imm);
1063 TRACE_AND_STEP();
1064 push_word(imm);
1065 DECODE_CLEAR_SEGOVR();
1066 END_OF_INSTR();
1067}
1068
1069/****************************************************************************
1070REMARKS:
1071Handles opcode 0x6b
1072****************************************************************************/
1073void x86emuOp_imul_byte_IMM(u8 X86EMU_UNUSED(op1))
1074{
1075 int mod, rl, rh;
1076 uint srcoffset;
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001077 s8 imm;
Jason Jina63ce952007-07-06 08:34:56 +08001078
1079 START_OF_INSTR();
1080 DECODE_PRINTF("IMUL\t");
1081 FETCH_DECODE_MODRM(mod, rh, rl);
1082 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001083 srcoffset = decode_rmXX_address(mod, rl);
1084 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1085 u32 *destreg;
1086 u32 srcval;
1087 u32 res_lo,res_hi;
Jason Jina63ce952007-07-06 08:34:56 +08001088
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001089 destreg = DECODE_RM_LONG_REGISTER(rh);
1090 DECODE_PRINTF(",");
1091 srcval = fetch_data_long(srcoffset);
1092 imm = fetch_byte_imm();
1093 DECODE_PRINTF2(",%d\n", (s32)imm);
1094 TRACE_AND_STEP();
1095 imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
1096 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1097 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1098 CLEAR_FLAG(F_CF);
1099 CLEAR_FLAG(F_OF);
1100 } else {
1101 SET_FLAG(F_CF);
1102 SET_FLAG(F_OF);
1103 }
1104 *destreg = (u32)res_lo;
1105 } else {
1106 u16 *destreg;
1107 u16 srcval;
1108 u32 res;
Jason Jina63ce952007-07-06 08:34:56 +08001109
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001110 destreg = DECODE_RM_WORD_REGISTER(rh);
1111 DECODE_PRINTF(",");
1112 srcval = fetch_data_word(srcoffset);
1113 imm = fetch_byte_imm();
1114 DECODE_PRINTF2(",%d\n", (s32)imm);
1115 TRACE_AND_STEP();
1116 res = (s16)srcval * (s16)imm;
1117 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1118 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1119 CLEAR_FLAG(F_CF);
1120 CLEAR_FLAG(F_OF);
1121 } else {
1122 SET_FLAG(F_CF);
1123 SET_FLAG(F_OF);
1124 }
1125 *destreg = (u16)res;
1126 }
1127 } else { /* register to register */
1128 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1129 u32 *destreg,*srcreg;
1130 u32 res_lo,res_hi;
Jason Jina63ce952007-07-06 08:34:56 +08001131
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001132 destreg = DECODE_RM_LONG_REGISTER(rh);
1133 DECODE_PRINTF(",");
1134 srcreg = DECODE_RM_LONG_REGISTER(rl);
1135 imm = fetch_byte_imm();
1136 DECODE_PRINTF2(",%d\n", (s32)imm);
1137 TRACE_AND_STEP();
1138 imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
1139 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1140 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1141 CLEAR_FLAG(F_CF);
1142 CLEAR_FLAG(F_OF);
1143 } else {
1144 SET_FLAG(F_CF);
1145 SET_FLAG(F_OF);
1146 }
1147 *destreg = (u32)res_lo;
1148 } else {
1149 u16 *destreg,*srcreg;
1150 u32 res;
Jason Jina63ce952007-07-06 08:34:56 +08001151
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001152 destreg = DECODE_RM_WORD_REGISTER(rh);
1153 DECODE_PRINTF(",");
1154 srcreg = DECODE_RM_WORD_REGISTER(rl);
1155 imm = fetch_byte_imm();
1156 DECODE_PRINTF2(",%d\n", (s32)imm);
1157 TRACE_AND_STEP();
1158 res = (s16)*srcreg * (s16)imm;
1159 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1160 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1161 CLEAR_FLAG(F_CF);
1162 CLEAR_FLAG(F_OF);
1163 } else {
1164 SET_FLAG(F_CF);
1165 SET_FLAG(F_OF);
1166 }
1167 *destreg = (u16)res;
1168 }
Jason Jina63ce952007-07-06 08:34:56 +08001169 }
1170 DECODE_CLEAR_SEGOVR();
1171 END_OF_INSTR();
1172}
1173
1174/****************************************************************************
1175REMARKS:
1176Handles opcode 0x6c
1177****************************************************************************/
1178void x86emuOp_ins_byte(u8 X86EMU_UNUSED(op1))
1179{
1180 START_OF_INSTR();
1181 DECODE_PRINTF("INSB\n");
1182 ins(1);
1183 TRACE_AND_STEP();
1184 DECODE_CLEAR_SEGOVR();
1185 END_OF_INSTR();
1186}
1187
1188/****************************************************************************
1189REMARKS:
1190Handles opcode 0x6d
1191****************************************************************************/
1192void x86emuOp_ins_word(u8 X86EMU_UNUSED(op1))
1193{
1194 START_OF_INSTR();
1195 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001196 DECODE_PRINTF("INSD\n");
1197 ins(4);
Jason Jina63ce952007-07-06 08:34:56 +08001198 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001199 DECODE_PRINTF("INSW\n");
1200 ins(2);
Jason Jina63ce952007-07-06 08:34:56 +08001201 }
1202 TRACE_AND_STEP();
1203 DECODE_CLEAR_SEGOVR();
1204 END_OF_INSTR();
1205}
1206
1207/****************************************************************************
1208REMARKS:
1209Handles opcode 0x6e
1210****************************************************************************/
1211void x86emuOp_outs_byte(u8 X86EMU_UNUSED(op1))
1212{
1213 START_OF_INSTR();
1214 DECODE_PRINTF("OUTSB\n");
1215 outs(1);
1216 TRACE_AND_STEP();
1217 DECODE_CLEAR_SEGOVR();
1218 END_OF_INSTR();
1219}
1220
1221/****************************************************************************
1222REMARKS:
1223Handles opcode 0x6f
1224****************************************************************************/
1225void x86emuOp_outs_word(u8 X86EMU_UNUSED(op1))
1226{
1227 START_OF_INSTR();
1228 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001229 DECODE_PRINTF("OUTSD\n");
1230 outs(4);
Jason Jina63ce952007-07-06 08:34:56 +08001231 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001232 DECODE_PRINTF("OUTSW\n");
1233 outs(2);
Jason Jina63ce952007-07-06 08:34:56 +08001234 }
1235 TRACE_AND_STEP();
1236 DECODE_CLEAR_SEGOVR();
1237 END_OF_INSTR();
1238}
1239
1240/****************************************************************************
1241REMARKS:
1242Handles opcode 0x70 - 0x7F
1243****************************************************************************/
1244int x86emu_check_jump_condition(u8 op);
1245
1246void x86emuOp_jump_near_cond(u8 op1)
1247{
1248 s8 offset;
1249 u16 target;
1250 int cond;
1251
1252 /* jump to byte offset if overflow flag is set */
1253 START_OF_INSTR();
1254 cond = x86emu_check_jump_condition(op1 & 0xF);
1255 offset = (s8)fetch_byte_imm();
1256 target = (u16)(M.x86.R_IP + (s16)offset);
1257 DECODE_PRINTF2("%x\n", target);
1258 TRACE_AND_STEP();
1259 if (cond)
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001260 M.x86.R_IP = target;
Jason Jina63ce952007-07-06 08:34:56 +08001261 DECODE_CLEAR_SEGOVR();
1262 END_OF_INSTR();
1263}
1264
1265/****************************************************************************
1266REMARKS:
1267Handles opcode 0x80
1268****************************************************************************/
1269void x86emuOp_opc80_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
1270{
1271 int mod, rl, rh;
1272 u8 *destreg;
1273 uint destoffset;
1274 u8 imm;
1275 u8 destval;
1276
1277 /*
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001278 * Weirdo special case instruction format. Part of the opcode
Jason Jina63ce952007-07-06 08:34:56 +08001279 * held below in "RH". Doubly nested case would result, except
1280 * that the decoded instruction
1281 */
1282 START_OF_INSTR();
1283 FETCH_DECODE_MODRM(mod, rh, rl);
1284#ifdef DEBUG
1285 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001286 /* XXX DECODE_PRINTF may be changed to something more
1287 general, so that it is important to leave the strings
1288 in the same format, even though the result is that the
1289 above test is done twice. */
Jason Jina63ce952007-07-06 08:34:56 +08001290
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001291 switch (rh) {
1292 case 0:
1293 DECODE_PRINTF("ADD\t");
1294 break;
1295 case 1:
1296 DECODE_PRINTF("OR\t");
1297 break;
1298 case 2:
1299 DECODE_PRINTF("ADC\t");
1300 break;
1301 case 3:
1302 DECODE_PRINTF("SBB\t");
1303 break;
1304 case 4:
1305 DECODE_PRINTF("AND\t");
1306 break;
1307 case 5:
1308 DECODE_PRINTF("SUB\t");
1309 break;
1310 case 6:
1311 DECODE_PRINTF("XOR\t");
1312 break;
1313 case 7:
1314 DECODE_PRINTF("CMP\t");
1315 break;
1316 }
Jason Jina63ce952007-07-06 08:34:56 +08001317 }
1318#endif
1319 /* know operation, decode the mod byte to find the addressing
1320 mode. */
1321 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001322 DECODE_PRINTF("BYTE PTR ");
1323 destoffset = decode_rmXX_address(mod, rl);
1324 DECODE_PRINTF(",");
1325 destval = fetch_data_byte(destoffset);
1326 imm = fetch_byte_imm();
1327 DECODE_PRINTF2("%x\n", imm);
1328 TRACE_AND_STEP();
1329 destval = (*genop_byte_operation[rh]) (destval, imm);
1330 if (rh != 7)
1331 store_data_byte(destoffset, destval);
1332 } else { /* register to register */
1333 destreg = DECODE_RM_BYTE_REGISTER(rl);
1334 DECODE_PRINTF(",");
1335 imm = fetch_byte_imm();
1336 DECODE_PRINTF2("%x\n", imm);
1337 TRACE_AND_STEP();
1338 destval = (*genop_byte_operation[rh]) (*destreg, imm);
1339 if (rh != 7)
1340 *destreg = destval;
Jason Jina63ce952007-07-06 08:34:56 +08001341 }
1342 DECODE_CLEAR_SEGOVR();
1343 END_OF_INSTR();
1344}
1345
1346/****************************************************************************
1347REMARKS:
1348Handles opcode 0x81
1349****************************************************************************/
1350void x86emuOp_opc81_word_RM_IMM(u8 X86EMU_UNUSED(op1))
1351{
1352 int mod, rl, rh;
1353 uint destoffset;
1354
1355 /*
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001356 * Weirdo special case instruction format. Part of the opcode
Jason Jina63ce952007-07-06 08:34:56 +08001357 * held below in "RH". Doubly nested case would result, except
1358 * that the decoded instruction
1359 */
1360 START_OF_INSTR();
1361 FETCH_DECODE_MODRM(mod, rh, rl);
1362#ifdef DEBUG
1363 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001364 /* XXX DECODE_PRINTF may be changed to something more
1365 general, so that it is important to leave the strings
1366 in the same format, even though the result is that the
1367 above test is done twice. */
Jason Jina63ce952007-07-06 08:34:56 +08001368
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001369 switch (rh) {
1370 case 0:
1371 DECODE_PRINTF("ADD\t");
1372 break;
1373 case 1:
1374 DECODE_PRINTF("OR\t");
1375 break;
1376 case 2:
1377 DECODE_PRINTF("ADC\t");
1378 break;
1379 case 3:
1380 DECODE_PRINTF("SBB\t");
1381 break;
1382 case 4:
1383 DECODE_PRINTF("AND\t");
1384 break;
1385 case 5:
1386 DECODE_PRINTF("SUB\t");
1387 break;
1388 case 6:
1389 DECODE_PRINTF("XOR\t");
1390 break;
1391 case 7:
1392 DECODE_PRINTF("CMP\t");
1393 break;
1394 }
Jason Jina63ce952007-07-06 08:34:56 +08001395 }
1396#endif
1397 /*
1398 * Know operation, decode the mod byte to find the addressing
1399 * mode.
1400 */
1401 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001402 DECODE_PRINTF("DWORD PTR ");
1403 destoffset = decode_rmXX_address(mod, rl);
1404 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1405 u32 destval,imm;
Jason Jina63ce952007-07-06 08:34:56 +08001406
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001407 DECODE_PRINTF(",");
1408 destval = fetch_data_long(destoffset);
1409 imm = fetch_long_imm();
1410 DECODE_PRINTF2("%x\n", imm);
1411 TRACE_AND_STEP();
1412 destval = (*genop_long_operation[rh]) (destval, imm);
1413 if (rh != 7)
1414 store_data_long(destoffset, destval);
1415 } else {
1416 u16 destval,imm;
Jason Jina63ce952007-07-06 08:34:56 +08001417
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001418 DECODE_PRINTF(",");
1419 destval = fetch_data_word(destoffset);
1420 imm = fetch_word_imm();
1421 DECODE_PRINTF2("%x\n", imm);
1422 TRACE_AND_STEP();
1423 destval = (*genop_word_operation[rh]) (destval, imm);
1424 if (rh != 7)
1425 store_data_word(destoffset, destval);
1426 }
1427 } else { /* register to register */
1428 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1429 u32 *destreg;
1430 u32 destval,imm;
Jason Jina63ce952007-07-06 08:34:56 +08001431
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001432 destreg = DECODE_RM_LONG_REGISTER(rl);
1433 DECODE_PRINTF(",");
1434 imm = fetch_long_imm();
1435 DECODE_PRINTF2("%x\n", imm);
1436 TRACE_AND_STEP();
1437 destval = (*genop_long_operation[rh]) (*destreg, imm);
1438 if (rh != 7)
1439 *destreg = destval;
1440 } else {
1441 u16 *destreg;
1442 u16 destval,imm;
Jason Jina63ce952007-07-06 08:34:56 +08001443
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001444 destreg = DECODE_RM_WORD_REGISTER(rl);
1445 DECODE_PRINTF(",");
1446 imm = fetch_word_imm();
1447 DECODE_PRINTF2("%x\n", imm);
1448 TRACE_AND_STEP();
1449 destval = (*genop_word_operation[rh]) (*destreg, imm);
1450 if (rh != 7)
1451 *destreg = destval;
1452 }
Jason Jina63ce952007-07-06 08:34:56 +08001453 }
1454 DECODE_CLEAR_SEGOVR();
1455 END_OF_INSTR();
1456}
1457
1458/****************************************************************************
1459REMARKS:
1460Handles opcode 0x82
1461****************************************************************************/
1462void x86emuOp_opc82_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
1463{
1464 int mod, rl, rh;
1465 u8 *destreg;
1466 uint destoffset;
1467 u8 imm;
1468 u8 destval;
1469
1470 /*
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001471 * Weirdo special case instruction format. Part of the opcode
Jason Jina63ce952007-07-06 08:34:56 +08001472 * held below in "RH". Doubly nested case would result, except
1473 * that the decoded instruction Similar to opcode 81, except that
1474 * the immediate byte is sign extended to a word length.
1475 */
1476 START_OF_INSTR();
1477 FETCH_DECODE_MODRM(mod, rh, rl);
1478#ifdef DEBUG
1479 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001480 /* XXX DECODE_PRINTF may be changed to something more
1481 general, so that it is important to leave the strings
1482 in the same format, even though the result is that the
1483 above test is done twice. */
1484 switch (rh) {
1485 case 0:
1486 DECODE_PRINTF("ADD\t");
1487 break;
1488 case 1:
1489 DECODE_PRINTF("OR\t");
1490 break;
1491 case 2:
1492 DECODE_PRINTF("ADC\t");
1493 break;
1494 case 3:
1495 DECODE_PRINTF("SBB\t");
1496 break;
1497 case 4:
1498 DECODE_PRINTF("AND\t");
1499 break;
1500 case 5:
1501 DECODE_PRINTF("SUB\t");
1502 break;
1503 case 6:
1504 DECODE_PRINTF("XOR\t");
1505 break;
1506 case 7:
1507 DECODE_PRINTF("CMP\t");
1508 break;
1509 }
Jason Jina63ce952007-07-06 08:34:56 +08001510 }
1511#endif
1512 /* know operation, decode the mod byte to find the addressing
1513 mode. */
1514 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001515 DECODE_PRINTF("BYTE PTR ");
1516 destoffset = decode_rmXX_address(mod, rl);
1517 destval = fetch_data_byte(destoffset);
1518 imm = fetch_byte_imm();
1519 DECODE_PRINTF2(",%x\n", imm);
1520 TRACE_AND_STEP();
1521 destval = (*genop_byte_operation[rh]) (destval, imm);
1522 if (rh != 7)
1523 store_data_byte(destoffset, destval);
1524 } else { /* register to register */
1525 destreg = DECODE_RM_BYTE_REGISTER(rl);
1526 imm = fetch_byte_imm();
1527 DECODE_PRINTF2(",%x\n", imm);
1528 TRACE_AND_STEP();
1529 destval = (*genop_byte_operation[rh]) (*destreg, imm);
1530 if (rh != 7)
1531 *destreg = destval;
Jason Jina63ce952007-07-06 08:34:56 +08001532 }
1533 DECODE_CLEAR_SEGOVR();
1534 END_OF_INSTR();
1535}
1536
1537/****************************************************************************
1538REMARKS:
1539Handles opcode 0x83
1540****************************************************************************/
1541void x86emuOp_opc83_word_RM_IMM(u8 X86EMU_UNUSED(op1))
1542{
1543 int mod, rl, rh;
1544 uint destoffset;
1545
1546 /*
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001547 * Weirdo special case instruction format. Part of the opcode
Jason Jina63ce952007-07-06 08:34:56 +08001548 * held below in "RH". Doubly nested case would result, except
1549 * that the decoded instruction Similar to opcode 81, except that
1550 * the immediate byte is sign extended to a word length.
1551 */
1552 START_OF_INSTR();
1553 FETCH_DECODE_MODRM(mod, rh, rl);
1554#ifdef DEBUG
1555 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001556 /* XXX DECODE_PRINTF may be changed to something more
1557 general, so that it is important to leave the strings
1558 in the same format, even though the result is that the
1559 above test is done twice. */
Jason Jina63ce952007-07-06 08:34:56 +08001560 switch (rh) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001561 case 0:
1562 DECODE_PRINTF("ADD\t");
1563 break;
1564 case 1:
1565 DECODE_PRINTF("OR\t");
1566 break;
1567 case 2:
1568 DECODE_PRINTF("ADC\t");
1569 break;
1570 case 3:
1571 DECODE_PRINTF("SBB\t");
1572 break;
1573 case 4:
1574 DECODE_PRINTF("AND\t");
1575 break;
1576 case 5:
1577 DECODE_PRINTF("SUB\t");
1578 break;
1579 case 6:
1580 DECODE_PRINTF("XOR\t");
1581 break;
1582 case 7:
1583 DECODE_PRINTF("CMP\t");
1584 break;
1585 }
Jason Jina63ce952007-07-06 08:34:56 +08001586 }
1587#endif
1588 /* know operation, decode the mod byte to find the addressing
1589 mode. */
1590 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001591 DECODE_PRINTF("DWORD PTR ");
1592 destoffset = decode_rmXX_address(mod,rl);
Jason Jina63ce952007-07-06 08:34:56 +08001593
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001594 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1595 u32 destval,imm;
Jason Jina63ce952007-07-06 08:34:56 +08001596
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001597 destval = fetch_data_long(destoffset);
1598 imm = (s8) fetch_byte_imm();
1599 DECODE_PRINTF2(",%x\n", imm);
1600 TRACE_AND_STEP();
1601 destval = (*genop_long_operation[rh]) (destval, imm);
1602 if (rh != 7)
1603 store_data_long(destoffset, destval);
1604 } else {
1605 u16 destval,imm;
Jason Jina63ce952007-07-06 08:34:56 +08001606
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001607 destval = fetch_data_word(destoffset);
1608 imm = (s8) fetch_byte_imm();
1609 DECODE_PRINTF2(",%x\n", imm);
1610 TRACE_AND_STEP();
1611 destval = (*genop_word_operation[rh]) (destval, imm);
1612 if (rh != 7)
1613 store_data_word(destoffset, destval);
1614 }
1615 } else { /* register to register */
1616 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1617 u32 *destreg;
1618 u32 destval,imm;
Jason Jina63ce952007-07-06 08:34:56 +08001619
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001620 destreg = DECODE_RM_LONG_REGISTER(rl);
1621 imm = (s8) fetch_byte_imm();
1622 DECODE_PRINTF2(",%x\n", imm);
1623 TRACE_AND_STEP();
1624 destval = (*genop_long_operation[rh]) (*destreg, imm);
1625 if (rh != 7)
1626 *destreg = destval;
1627 } else {
1628 u16 *destreg;
1629 u16 destval,imm;
Jason Jina63ce952007-07-06 08:34:56 +08001630
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001631 destreg = DECODE_RM_WORD_REGISTER(rl);
1632 imm = (s8) fetch_byte_imm();
1633 DECODE_PRINTF2(",%x\n", imm);
1634 TRACE_AND_STEP();
1635 destval = (*genop_word_operation[rh]) (*destreg, imm);
1636 if (rh != 7)
1637 *destreg = destval;
1638 }
Jason Jina63ce952007-07-06 08:34:56 +08001639 }
1640 DECODE_CLEAR_SEGOVR();
1641 END_OF_INSTR();
1642}
1643
1644/****************************************************************************
1645REMARKS:
1646Handles opcode 0x84
1647****************************************************************************/
1648void x86emuOp_test_byte_RM_R(u8 X86EMU_UNUSED(op1))
1649{
1650 int mod, rl, rh;
1651 u8 *destreg, *srcreg;
1652 uint destoffset;
1653 u8 destval;
1654
1655 START_OF_INSTR();
1656 DECODE_PRINTF("TEST\t");
1657 FETCH_DECODE_MODRM(mod, rh, rl);
1658 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001659 destoffset = decode_rmXX_address(mod, rl);
1660 DECODE_PRINTF(",");
1661 destval = fetch_data_byte(destoffset);
1662 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1663 DECODE_PRINTF("\n");
1664 TRACE_AND_STEP();
1665 test_byte(destval, *srcreg);
1666 } else { /* register to register */
1667 destreg = DECODE_RM_BYTE_REGISTER(rl);
1668 DECODE_PRINTF(",");
1669 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1670 DECODE_PRINTF("\n");
1671 TRACE_AND_STEP();
1672 test_byte(*destreg, *srcreg);
Jason Jina63ce952007-07-06 08:34:56 +08001673 }
1674 DECODE_CLEAR_SEGOVR();
1675 END_OF_INSTR();
1676}
1677
1678/****************************************************************************
1679REMARKS:
1680Handles opcode 0x85
1681****************************************************************************/
1682void x86emuOp_test_word_RM_R(u8 X86EMU_UNUSED(op1))
1683{
1684 int mod, rl, rh;
1685 uint destoffset;
1686
1687 START_OF_INSTR();
1688 DECODE_PRINTF("TEST\t");
1689 FETCH_DECODE_MODRM(mod, rh, rl);
1690 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001691 destoffset = decode_rmXX_address(mod, rl);
1692 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1693 u32 destval;
1694 u32 *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08001695
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001696 DECODE_PRINTF(",");
1697 destval = fetch_data_long(destoffset);
1698 srcreg = DECODE_RM_LONG_REGISTER(rh);
1699 DECODE_PRINTF("\n");
1700 TRACE_AND_STEP();
1701 test_long(destval, *srcreg);
1702 } else {
1703 u16 destval;
1704 u16 *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08001705
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001706 DECODE_PRINTF(",");
1707 destval = fetch_data_word(destoffset);
1708 srcreg = DECODE_RM_WORD_REGISTER(rh);
1709 DECODE_PRINTF("\n");
1710 TRACE_AND_STEP();
1711 test_word(destval, *srcreg);
1712 }
1713 } else { /* register to register */
1714 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1715 u32 *destreg,*srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08001716
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001717 destreg = DECODE_RM_LONG_REGISTER(rl);
1718 DECODE_PRINTF(",");
1719 srcreg = DECODE_RM_LONG_REGISTER(rh);
1720 DECODE_PRINTF("\n");
1721 TRACE_AND_STEP();
1722 test_long(*destreg, *srcreg);
1723 } else {
1724 u16 *destreg,*srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08001725
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001726 destreg = DECODE_RM_WORD_REGISTER(rl);
1727 DECODE_PRINTF(",");
1728 srcreg = DECODE_RM_WORD_REGISTER(rh);
1729 DECODE_PRINTF("\n");
1730 TRACE_AND_STEP();
1731 test_word(*destreg, *srcreg);
1732 }
Jason Jina63ce952007-07-06 08:34:56 +08001733 }
1734 DECODE_CLEAR_SEGOVR();
1735 END_OF_INSTR();
1736}
1737
1738/****************************************************************************
1739REMARKS:
1740Handles opcode 0x86
1741****************************************************************************/
1742void x86emuOp_xchg_byte_RM_R(u8 X86EMU_UNUSED(op1))
1743{
1744 int mod, rl, rh;
1745 u8 *destreg, *srcreg;
1746 uint destoffset;
1747 u8 destval;
1748 u8 tmp;
1749
1750 START_OF_INSTR();
1751 DECODE_PRINTF("XCHG\t");
1752 FETCH_DECODE_MODRM(mod, rh, rl);
1753 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001754 destoffset = decode_rmXX_address(mod, rl);
1755 DECODE_PRINTF(",");
1756 destval = fetch_data_byte(destoffset);
1757 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1758 DECODE_PRINTF("\n");
1759 TRACE_AND_STEP();
1760 tmp = *srcreg;
1761 *srcreg = destval;
1762 destval = tmp;
1763 store_data_byte(destoffset, destval);
1764 } else { /* register to register */
1765 destreg = DECODE_RM_BYTE_REGISTER(rl);
1766 DECODE_PRINTF(",");
1767 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1768 DECODE_PRINTF("\n");
1769 TRACE_AND_STEP();
1770 tmp = *srcreg;
1771 *srcreg = *destreg;
1772 *destreg = tmp;
Jason Jina63ce952007-07-06 08:34:56 +08001773 }
1774 DECODE_CLEAR_SEGOVR();
1775 END_OF_INSTR();
1776}
1777
1778/****************************************************************************
1779REMARKS:
1780Handles opcode 0x87
1781****************************************************************************/
1782void x86emuOp_xchg_word_RM_R(u8 X86EMU_UNUSED(op1))
1783{
1784 int mod, rl, rh;
1785 uint destoffset;
1786
1787 START_OF_INSTR();
1788 DECODE_PRINTF("XCHG\t");
1789 FETCH_DECODE_MODRM(mod, rh, rl);
1790 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001791 destoffset = decode_rmXX_address(mod, rl);
1792 DECODE_PRINTF(",");
1793 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1794 u32 *srcreg;
1795 u32 destval,tmp;
Jason Jina63ce952007-07-06 08:34:56 +08001796
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001797 destval = fetch_data_long(destoffset);
1798 srcreg = DECODE_RM_LONG_REGISTER(rh);
1799 DECODE_PRINTF("\n");
1800 TRACE_AND_STEP();
1801 tmp = *srcreg;
1802 *srcreg = destval;
1803 destval = tmp;
1804 store_data_long(destoffset, destval);
1805 } else {
1806 u16 *srcreg;
1807 u16 destval,tmp;
Jason Jina63ce952007-07-06 08:34:56 +08001808
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001809 destval = fetch_data_word(destoffset);
1810 srcreg = DECODE_RM_WORD_REGISTER(rh);
1811 DECODE_PRINTF("\n");
1812 TRACE_AND_STEP();
1813 tmp = *srcreg;
1814 *srcreg = destval;
1815 destval = tmp;
1816 store_data_word(destoffset, destval);
1817 }
1818 } else { /* register to register */
1819 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1820 u32 *destreg,*srcreg;
1821 u32 tmp;
Jason Jina63ce952007-07-06 08:34:56 +08001822
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001823 destreg = DECODE_RM_LONG_REGISTER(rl);
1824 DECODE_PRINTF(",");
1825 srcreg = DECODE_RM_LONG_REGISTER(rh);
1826 DECODE_PRINTF("\n");
1827 TRACE_AND_STEP();
1828 tmp = *srcreg;
1829 *srcreg = *destreg;
1830 *destreg = tmp;
1831 } else {
1832 u16 *destreg,*srcreg;
1833 u16 tmp;
Jason Jina63ce952007-07-06 08:34:56 +08001834
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001835 destreg = DECODE_RM_WORD_REGISTER(rl);
1836 DECODE_PRINTF(",");
1837 srcreg = DECODE_RM_WORD_REGISTER(rh);
1838 DECODE_PRINTF("\n");
1839 TRACE_AND_STEP();
1840 tmp = *srcreg;
1841 *srcreg = *destreg;
1842 *destreg = tmp;
1843 }
Jason Jina63ce952007-07-06 08:34:56 +08001844 }
1845 DECODE_CLEAR_SEGOVR();
1846 END_OF_INSTR();
1847}
1848
1849/****************************************************************************
1850REMARKS:
1851Handles opcode 0x88
1852****************************************************************************/
1853void x86emuOp_mov_byte_RM_R(u8 X86EMU_UNUSED(op1))
1854{
1855 int mod, rl, rh;
1856 u8 *destreg, *srcreg;
1857 uint destoffset;
1858
1859 START_OF_INSTR();
1860 DECODE_PRINTF("MOV\t");
1861 FETCH_DECODE_MODRM(mod, rh, rl);
1862 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001863 destoffset = decode_rmXX_address(mod, rl);
1864 DECODE_PRINTF(",");
1865 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1866 DECODE_PRINTF("\n");
1867 TRACE_AND_STEP();
1868 store_data_byte(destoffset, *srcreg);
1869 } else { /* register to register */
1870 destreg = DECODE_RM_BYTE_REGISTER(rl);
1871 DECODE_PRINTF(",");
1872 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1873 DECODE_PRINTF("\n");
1874 TRACE_AND_STEP();
1875 *destreg = *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08001876 }
1877 DECODE_CLEAR_SEGOVR();
1878 END_OF_INSTR();
1879}
1880
1881/****************************************************************************
1882REMARKS:
1883Handles opcode 0x89
1884****************************************************************************/
1885void x86emuOp_mov_word_RM_R(u8 X86EMU_UNUSED(op1))
1886{
1887 int mod, rl, rh;
1888 uint destoffset;
1889
1890 START_OF_INSTR();
1891 DECODE_PRINTF("MOV\t");
1892 FETCH_DECODE_MODRM(mod, rh, rl);
1893 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001894 destoffset = decode_rmXX_address(mod, rl);
1895 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1896 u32 *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08001897
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001898 DECODE_PRINTF(",");
1899 srcreg = DECODE_RM_LONG_REGISTER(rh);
1900 DECODE_PRINTF("\n");
1901 TRACE_AND_STEP();
1902 store_data_long(destoffset, *srcreg);
1903 } else {
1904 u16 *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08001905
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001906 DECODE_PRINTF(",");
1907 srcreg = DECODE_RM_WORD_REGISTER(rh);
1908 DECODE_PRINTF("\n");
1909 TRACE_AND_STEP();
1910 store_data_word(destoffset, *srcreg);
1911 }
1912 } else { /* register to register */
1913 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1914 u32 *destreg,*srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08001915
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001916 destreg = DECODE_RM_LONG_REGISTER(rl);
1917 DECODE_PRINTF(",");
1918 srcreg = DECODE_RM_LONG_REGISTER(rh);
1919 DECODE_PRINTF("\n");
1920 TRACE_AND_STEP();
1921 *destreg = *srcreg;
1922 } else {
1923 u16 *destreg,*srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08001924
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001925 destreg = DECODE_RM_WORD_REGISTER(rl);
1926 DECODE_PRINTF(",");
1927 srcreg = DECODE_RM_WORD_REGISTER(rh);
1928 DECODE_PRINTF("\n");
1929 TRACE_AND_STEP();
1930 *destreg = *srcreg;
1931 }
Jason Jina63ce952007-07-06 08:34:56 +08001932 }
1933 DECODE_CLEAR_SEGOVR();
1934 END_OF_INSTR();
1935}
1936
1937/****************************************************************************
1938REMARKS:
1939Handles opcode 0x8a
1940****************************************************************************/
1941void x86emuOp_mov_byte_R_RM(u8 X86EMU_UNUSED(op1))
1942{
1943 int mod, rl, rh;
1944 u8 *destreg, *srcreg;
1945 uint srcoffset;
1946 u8 srcval;
1947
1948 START_OF_INSTR();
1949 DECODE_PRINTF("MOV\t");
1950 FETCH_DECODE_MODRM(mod, rh, rl);
1951 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001952 destreg = DECODE_RM_BYTE_REGISTER(rh);
1953 DECODE_PRINTF(",");
1954 srcoffset = decode_rmXX_address(mod, rl);
1955 srcval = fetch_data_byte(srcoffset);
1956 DECODE_PRINTF("\n");
1957 TRACE_AND_STEP();
1958 *destreg = srcval;
1959 } else { /* register to register */
1960 destreg = DECODE_RM_BYTE_REGISTER(rh);
1961 DECODE_PRINTF(",");
1962 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1963 DECODE_PRINTF("\n");
1964 TRACE_AND_STEP();
1965 *destreg = *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08001966 }
1967 DECODE_CLEAR_SEGOVR();
1968 END_OF_INSTR();
1969}
1970
1971/****************************************************************************
1972REMARKS:
1973Handles opcode 0x8b
1974****************************************************************************/
1975void x86emuOp_mov_word_R_RM(u8 X86EMU_UNUSED(op1))
1976{
1977 int mod, rl, rh;
1978 uint srcoffset;
1979
1980 START_OF_INSTR();
1981 DECODE_PRINTF("MOV\t");
1982 FETCH_DECODE_MODRM(mod, rh, rl);
1983 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001984 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1985 u32 *destreg;
1986 u32 srcval;
Jason Jina63ce952007-07-06 08:34:56 +08001987
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001988 destreg = DECODE_RM_LONG_REGISTER(rh);
1989 DECODE_PRINTF(",");
1990 srcoffset = decode_rmXX_address(mod, rl);
1991 srcval = fetch_data_long(srcoffset);
1992 DECODE_PRINTF("\n");
1993 TRACE_AND_STEP();
1994 *destreg = srcval;
1995 } else {
1996 u16 *destreg;
1997 u16 srcval;
Jason Jina63ce952007-07-06 08:34:56 +08001998
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001999 destreg = DECODE_RM_WORD_REGISTER(rh);
2000 DECODE_PRINTF(",");
2001 srcoffset = decode_rmXX_address(mod, rl);
2002 srcval = fetch_data_word(srcoffset);
2003 DECODE_PRINTF("\n");
2004 TRACE_AND_STEP();
2005 *destreg = srcval;
2006 }
2007 } else { /* register to register */
2008 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2009 u32 *destreg, *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08002010
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002011 destreg = DECODE_RM_LONG_REGISTER(rh);
2012 DECODE_PRINTF(",");
2013 srcreg = DECODE_RM_LONG_REGISTER(rl);
2014 DECODE_PRINTF("\n");
2015 TRACE_AND_STEP();
2016 *destreg = *srcreg;
2017 } else {
2018 u16 *destreg, *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08002019
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002020 destreg = DECODE_RM_WORD_REGISTER(rh);
2021 DECODE_PRINTF(",");
2022 srcreg = DECODE_RM_WORD_REGISTER(rl);
2023 DECODE_PRINTF("\n");
2024 TRACE_AND_STEP();
2025 *destreg = *srcreg;
2026 }
Jason Jina63ce952007-07-06 08:34:56 +08002027 }
2028 DECODE_CLEAR_SEGOVR();
2029 END_OF_INSTR();
2030}
2031
2032/****************************************************************************
2033REMARKS:
2034Handles opcode 0x8c
2035****************************************************************************/
2036void x86emuOp_mov_word_RM_SR(u8 X86EMU_UNUSED(op1))
2037{
2038 int mod, rl, rh;
2039 u16 *destreg, *srcreg;
2040 uint destoffset;
2041 u16 destval;
2042
2043 START_OF_INSTR();
2044 DECODE_PRINTF("MOV\t");
2045 FETCH_DECODE_MODRM(mod, rh, rl);
2046 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002047 destoffset = decode_rmXX_address(mod, rl);
2048 DECODE_PRINTF(",");
2049 srcreg = decode_rm_seg_register(rh);
2050 DECODE_PRINTF("\n");
2051 TRACE_AND_STEP();
2052 destval = *srcreg;
2053 store_data_word(destoffset, destval);
2054 } else { /* register to register */
2055 destreg = DECODE_RM_WORD_REGISTER(rl);
2056 DECODE_PRINTF(",");
2057 srcreg = decode_rm_seg_register(rh);
2058 DECODE_PRINTF("\n");
2059 TRACE_AND_STEP();
2060 *destreg = *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08002061 }
2062 DECODE_CLEAR_SEGOVR();
2063 END_OF_INSTR();
2064}
2065
2066/****************************************************************************
2067REMARKS:
2068Handles opcode 0x8d
2069****************************************************************************/
2070void x86emuOp_lea_word_R_M(u8 X86EMU_UNUSED(op1))
2071{
2072 int mod, rl, rh;
2073 u16 *srcreg;
2074 uint destoffset;
2075
2076/*
2077 * TODO: Need to handle address size prefix!
2078 *
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002079 * lea eax,[eax+ebx*2] ??
Jason Jina63ce952007-07-06 08:34:56 +08002080 */
2081
2082 START_OF_INSTR();
2083 DECODE_PRINTF("LEA\t");
2084 FETCH_DECODE_MODRM(mod, rh, rl);
2085 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002086 srcreg = DECODE_RM_WORD_REGISTER(rh);
2087 DECODE_PRINTF(",");
2088 destoffset = decode_rmXX_address(mod, rl);
2089 DECODE_PRINTF("\n");
2090 TRACE_AND_STEP();
2091 *srcreg = (u16)destoffset;
2092 }
Jason Jina63ce952007-07-06 08:34:56 +08002093 /* } else { undefined. Do nothing. } */
2094 DECODE_CLEAR_SEGOVR();
2095 END_OF_INSTR();
2096}
2097
2098/****************************************************************************
2099REMARKS:
2100Handles opcode 0x8e
2101****************************************************************************/
2102void x86emuOp_mov_word_SR_RM(u8 X86EMU_UNUSED(op1))
2103{
2104 int mod, rl, rh;
2105 u16 *destreg, *srcreg;
2106 uint srcoffset;
2107 u16 srcval;
2108
2109 START_OF_INSTR();
2110 DECODE_PRINTF("MOV\t");
2111 FETCH_DECODE_MODRM(mod, rh, rl);
2112 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002113 destreg = decode_rm_seg_register(rh);
2114 DECODE_PRINTF(",");
2115 srcoffset = decode_rmXX_address(mod, rl);
2116 srcval = fetch_data_word(srcoffset);
2117 DECODE_PRINTF("\n");
2118 TRACE_AND_STEP();
2119 *destreg = srcval;
2120 } else { /* register to register */
2121 destreg = decode_rm_seg_register(rh);
2122 DECODE_PRINTF(",");
2123 srcreg = DECODE_RM_WORD_REGISTER(rl);
2124 DECODE_PRINTF("\n");
2125 TRACE_AND_STEP();
2126 *destreg = *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08002127 }
2128 /*
2129 * Clean up, and reset all the R_xSP pointers to the correct
2130 * locations. This is about 3x too much overhead (doing all the
2131 * segreg ptrs when only one is needed, but this instruction
2132 * *cannot* be that common, and this isn't too much work anyway.
2133 */
2134 DECODE_CLEAR_SEGOVR();
2135 END_OF_INSTR();
2136}
2137
2138/****************************************************************************
2139REMARKS:
2140Handles opcode 0x8f
2141****************************************************************************/
2142void x86emuOp_pop_RM(u8 X86EMU_UNUSED(op1))
2143{
2144 int mod, rl, rh;
2145 uint destoffset;
2146
2147 START_OF_INSTR();
2148 DECODE_PRINTF("POP\t");
2149 FETCH_DECODE_MODRM(mod, rh, rl);
2150 if (rh != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002151 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
2152 HALT_SYS();
Jason Jina63ce952007-07-06 08:34:56 +08002153 }
2154 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002155 destoffset = decode_rmXX_address(mod, rl);
2156 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2157 u32 destval;
Jason Jina63ce952007-07-06 08:34:56 +08002158
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002159 DECODE_PRINTF("\n");
2160 TRACE_AND_STEP();
2161 destval = pop_long();
2162 store_data_long(destoffset, destval);
2163 } else {
2164 u16 destval;
Jason Jina63ce952007-07-06 08:34:56 +08002165
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002166 DECODE_PRINTF("\n");
2167 TRACE_AND_STEP();
2168 destval = pop_word();
2169 store_data_word(destoffset, destval);
2170 }
2171 } else { /* register to register */
2172 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2173 u32 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08002174
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002175 destreg = DECODE_RM_LONG_REGISTER(rl);
2176 DECODE_PRINTF("\n");
2177 TRACE_AND_STEP();
2178 *destreg = pop_long();
2179 } else {
2180 u16 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08002181
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002182 destreg = DECODE_RM_WORD_REGISTER(rl);
2183 DECODE_PRINTF("\n");
2184 TRACE_AND_STEP();
2185 *destreg = pop_word();
2186 }
Jason Jina63ce952007-07-06 08:34:56 +08002187 }
2188 DECODE_CLEAR_SEGOVR();
2189 END_OF_INSTR();
2190}
2191
2192/****************************************************************************
2193REMARKS:
2194Handles opcode 0x90
2195****************************************************************************/
2196void x86emuOp_nop(u8 X86EMU_UNUSED(op1))
2197{
2198 START_OF_INSTR();
2199 DECODE_PRINTF("NOP\n");
2200 TRACE_AND_STEP();
2201 DECODE_CLEAR_SEGOVR();
2202 END_OF_INSTR();
2203}
2204
2205/****************************************************************************
2206REMARKS:
2207Handles opcode 0x91-0x97
2208****************************************************************************/
2209void x86emuOp_xchg_word_AX_register(u8 X86EMU_UNUSED(op1))
2210{
2211 u32 tmp;
2212
2213 op1 &= 0x7;
2214
2215 START_OF_INSTR();
2216
2217 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002218 u32 *reg32;
2219 DECODE_PRINTF("XCHG\tEAX,");
2220 reg32 = DECODE_RM_LONG_REGISTER(op1);
2221 DECODE_PRINTF("\n");
2222 TRACE_AND_STEP();
2223 tmp = M.x86.R_EAX;
2224 M.x86.R_EAX = *reg32;
2225 *reg32 = tmp;
Jason Jina63ce952007-07-06 08:34:56 +08002226 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002227 u16 *reg16;
2228 DECODE_PRINTF("XCHG\tAX,");
2229 reg16 = DECODE_RM_WORD_REGISTER(op1);
2230 DECODE_PRINTF("\n");
2231 TRACE_AND_STEP();
2232 tmp = M.x86.R_AX;
2233 M.x86.R_EAX = *reg16;
2234 *reg16 = (u16)tmp;
Jason Jina63ce952007-07-06 08:34:56 +08002235 }
2236 DECODE_CLEAR_SEGOVR();
2237 END_OF_INSTR();
2238}
2239
2240/****************************************************************************
2241REMARKS:
2242Handles opcode 0x98
2243****************************************************************************/
2244void x86emuOp_cbw(u8 X86EMU_UNUSED(op1))
2245{
2246 START_OF_INSTR();
2247 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002248 DECODE_PRINTF("CWDE\n");
Jason Jina63ce952007-07-06 08:34:56 +08002249 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002250 DECODE_PRINTF("CBW\n");
Jason Jina63ce952007-07-06 08:34:56 +08002251 }
2252 TRACE_AND_STEP();
2253 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002254 if (M.x86.R_AX & 0x8000) {
2255 M.x86.R_EAX |= 0xffff0000;
2256 } else {
2257 M.x86.R_EAX &= 0x0000ffff;
2258 }
Jason Jina63ce952007-07-06 08:34:56 +08002259 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002260 if (M.x86.R_AL & 0x80) {
2261 M.x86.R_AH = 0xff;
2262 } else {
2263 M.x86.R_AH = 0x0;
2264 }
Jason Jina63ce952007-07-06 08:34:56 +08002265 }
2266 DECODE_CLEAR_SEGOVR();
2267 END_OF_INSTR();
2268}
2269
2270/****************************************************************************
2271REMARKS:
2272Handles opcode 0x99
2273****************************************************************************/
2274void x86emuOp_cwd(u8 X86EMU_UNUSED(op1))
2275{
2276 START_OF_INSTR();
2277 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002278 DECODE_PRINTF("CDQ\n");
Jason Jina63ce952007-07-06 08:34:56 +08002279 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002280 DECODE_PRINTF("CWD\n");
Jason Jina63ce952007-07-06 08:34:56 +08002281 }
2282 DECODE_PRINTF("CWD\n");
2283 TRACE_AND_STEP();
2284 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002285 if (M.x86.R_EAX & 0x80000000) {
2286 M.x86.R_EDX = 0xffffffff;
2287 } else {
2288 M.x86.R_EDX = 0x0;
2289 }
Jason Jina63ce952007-07-06 08:34:56 +08002290 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002291 if (M.x86.R_AX & 0x8000) {
2292 M.x86.R_DX = 0xffff;
2293 } else {
2294 M.x86.R_DX = 0x0;
2295 }
Jason Jina63ce952007-07-06 08:34:56 +08002296 }
2297 DECODE_CLEAR_SEGOVR();
2298 END_OF_INSTR();
2299}
2300
2301/****************************************************************************
2302REMARKS:
2303Handles opcode 0x9a
2304****************************************************************************/
2305void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1))
2306{
2307 u16 farseg, faroff;
2308
2309 START_OF_INSTR();
2310 DECODE_PRINTF("CALL\t");
2311 faroff = fetch_word_imm();
2312 farseg = fetch_word_imm();
2313 DECODE_PRINTF2("%04x:", farseg);
2314 DECODE_PRINTF2("%04x\n", faroff);
2315 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, farseg, faroff, "FAR ");
2316
2317 /* XXX
2318 *
2319 * Hooked interrupt vectors calling into our "BIOS" will cause
2320 * problems unless all intersegment stuff is checked for BIOS
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002321 * access. Check needed here. For moment, let it alone.
Jason Jina63ce952007-07-06 08:34:56 +08002322 */
2323 TRACE_AND_STEP();
2324 push_word(M.x86.R_CS);
2325 M.x86.R_CS = farseg;
2326 push_word(M.x86.R_IP);
2327 M.x86.R_IP = faroff;
2328 DECODE_CLEAR_SEGOVR();
2329 END_OF_INSTR();
2330}
2331
2332/****************************************************************************
2333REMARKS:
2334Handles opcode 0x9b
2335****************************************************************************/
2336void x86emuOp_wait(u8 X86EMU_UNUSED(op1))
2337{
2338 START_OF_INSTR();
2339 DECODE_PRINTF("WAIT");
2340 TRACE_AND_STEP();
2341 /* NADA. */
2342 DECODE_CLEAR_SEGOVR();
2343 END_OF_INSTR();
2344}
2345
2346/****************************************************************************
2347REMARKS:
2348Handles opcode 0x9c
2349****************************************************************************/
2350void x86emuOp_pushf_word(u8 X86EMU_UNUSED(op1))
2351{
2352 u32 flags;
2353
2354 START_OF_INSTR();
2355 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002356 DECODE_PRINTF("PUSHFD\n");
Jason Jina63ce952007-07-06 08:34:56 +08002357 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002358 DECODE_PRINTF("PUSHF\n");
Jason Jina63ce952007-07-06 08:34:56 +08002359 }
2360 TRACE_AND_STEP();
2361
2362 /* clear out *all* bits not representing flags, and turn on real bits */
2363 flags = (M.x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
2364 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002365 push_long(flags);
Jason Jina63ce952007-07-06 08:34:56 +08002366 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002367 push_word((u16)flags);
Jason Jina63ce952007-07-06 08:34:56 +08002368 }
2369 DECODE_CLEAR_SEGOVR();
2370 END_OF_INSTR();
2371}
2372
2373/****************************************************************************
2374REMARKS:
2375Handles opcode 0x9d
2376****************************************************************************/
2377void x86emuOp_popf_word(u8 X86EMU_UNUSED(op1))
2378{
2379 START_OF_INSTR();
2380 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002381 DECODE_PRINTF("POPFD\n");
Jason Jina63ce952007-07-06 08:34:56 +08002382 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002383 DECODE_PRINTF("POPF\n");
Jason Jina63ce952007-07-06 08:34:56 +08002384 }
2385 TRACE_AND_STEP();
2386 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002387 M.x86.R_EFLG = pop_long();
Jason Jina63ce952007-07-06 08:34:56 +08002388 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002389 M.x86.R_FLG = pop_word();
Jason Jina63ce952007-07-06 08:34:56 +08002390 }
2391 DECODE_CLEAR_SEGOVR();
2392 END_OF_INSTR();
2393}
2394
2395/****************************************************************************
2396REMARKS:
2397Handles opcode 0x9e
2398****************************************************************************/
2399void x86emuOp_sahf(u8 X86EMU_UNUSED(op1))
2400{
2401 START_OF_INSTR();
2402 DECODE_PRINTF("SAHF\n");
2403 TRACE_AND_STEP();
2404 /* clear the lower bits of the flag register */
2405 M.x86.R_FLG &= 0xffffff00;
2406 /* or in the AH register into the flags register */
2407 M.x86.R_FLG |= M.x86.R_AH;
2408 DECODE_CLEAR_SEGOVR();
2409 END_OF_INSTR();
2410}
2411
2412/****************************************************************************
2413REMARKS:
2414Handles opcode 0x9f
2415****************************************************************************/
2416void x86emuOp_lahf(u8 X86EMU_UNUSED(op1))
2417{
2418 START_OF_INSTR();
2419 DECODE_PRINTF("LAHF\n");
2420 TRACE_AND_STEP();
2421 M.x86.R_AH = (u8)(M.x86.R_FLG & 0xff);
2422 /*undocumented TC++ behavior??? Nope. It's documented, but
2423 you have too look real hard to notice it. */
2424 M.x86.R_AH |= 0x2;
2425 DECODE_CLEAR_SEGOVR();
2426 END_OF_INSTR();
2427}
2428
2429/****************************************************************************
2430REMARKS:
2431Handles opcode 0xa0
2432****************************************************************************/
2433void x86emuOp_mov_AL_M_IMM(u8 X86EMU_UNUSED(op1))
2434{
2435 u16 offset;
2436
2437 START_OF_INSTR();
2438 DECODE_PRINTF("MOV\tAL,");
2439 offset = fetch_word_imm();
2440 DECODE_PRINTF2("[%04x]\n", offset);
2441 TRACE_AND_STEP();
2442 M.x86.R_AL = fetch_data_byte(offset);
2443 DECODE_CLEAR_SEGOVR();
2444 END_OF_INSTR();
2445}
2446
2447/****************************************************************************
2448REMARKS:
2449Handles opcode 0xa1
2450****************************************************************************/
2451void x86emuOp_mov_AX_M_IMM(u8 X86EMU_UNUSED(op1))
2452{
2453 u16 offset;
2454
2455 START_OF_INSTR();
2456 offset = fetch_word_imm();
2457 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002458 DECODE_PRINTF2("MOV\tEAX,[%04x]\n", offset);
Jason Jina63ce952007-07-06 08:34:56 +08002459 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002460 DECODE_PRINTF2("MOV\tAX,[%04x]\n", offset);
Jason Jina63ce952007-07-06 08:34:56 +08002461 }
2462 TRACE_AND_STEP();
2463 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002464 M.x86.R_EAX = fetch_data_long(offset);
Jason Jina63ce952007-07-06 08:34:56 +08002465 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002466 M.x86.R_AX = fetch_data_word(offset);
Jason Jina63ce952007-07-06 08:34:56 +08002467 }
2468 DECODE_CLEAR_SEGOVR();
2469 END_OF_INSTR();
2470}
2471
2472/****************************************************************************
2473REMARKS:
2474Handles opcode 0xa2
2475****************************************************************************/
2476void x86emuOp_mov_M_AL_IMM(u8 X86EMU_UNUSED(op1))
2477{
2478 u16 offset;
2479
2480 START_OF_INSTR();
2481 DECODE_PRINTF("MOV\t");
2482 offset = fetch_word_imm();
2483 DECODE_PRINTF2("[%04x],AL\n", offset);
2484 TRACE_AND_STEP();
2485 store_data_byte(offset, M.x86.R_AL);
2486 DECODE_CLEAR_SEGOVR();
2487 END_OF_INSTR();
2488}
2489
2490/****************************************************************************
2491REMARKS:
2492Handles opcode 0xa3
2493****************************************************************************/
2494void x86emuOp_mov_M_AX_IMM(u8 X86EMU_UNUSED(op1))
2495{
2496 u16 offset;
2497
2498 START_OF_INSTR();
2499 offset = fetch_word_imm();
2500 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002501 DECODE_PRINTF2("MOV\t[%04x],EAX\n", offset);
Jason Jina63ce952007-07-06 08:34:56 +08002502 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002503 DECODE_PRINTF2("MOV\t[%04x],AX\n", offset);
Jason Jina63ce952007-07-06 08:34:56 +08002504 }
2505 TRACE_AND_STEP();
2506 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002507 store_data_long(offset, M.x86.R_EAX);
Jason Jina63ce952007-07-06 08:34:56 +08002508 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002509 store_data_word(offset, M.x86.R_AX);
Jason Jina63ce952007-07-06 08:34:56 +08002510 }
2511 DECODE_CLEAR_SEGOVR();
2512 END_OF_INSTR();
2513}
2514
2515/****************************************************************************
2516REMARKS:
2517Handles opcode 0xa4
2518****************************************************************************/
2519void x86emuOp_movs_byte(u8 X86EMU_UNUSED(op1))
2520{
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002521 u8 val;
Jason Jina63ce952007-07-06 08:34:56 +08002522 u32 count;
2523 int inc;
2524
2525 START_OF_INSTR();
2526 DECODE_PRINTF("MOVS\tBYTE\n");
2527 if (ACCESS_FLAG(F_DF)) /* down */
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002528 inc = -1;
Jason Jina63ce952007-07-06 08:34:56 +08002529 else
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002530 inc = 1;
Jason Jina63ce952007-07-06 08:34:56 +08002531 TRACE_AND_STEP();
2532 count = 1;
2533 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002534 /* dont care whether REPE or REPNE */
2535 /* move them until CX is ZERO. */
2536 count = M.x86.R_CX;
2537 M.x86.R_CX = 0;
2538 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
Jason Jina63ce952007-07-06 08:34:56 +08002539 }
2540 while (count--) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002541 val = fetch_data_byte(M.x86.R_SI);
2542 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, val);
2543 M.x86.R_SI += inc;
2544 M.x86.R_DI += inc;
Jason Jina63ce952007-07-06 08:34:56 +08002545 }
2546 DECODE_CLEAR_SEGOVR();
2547 END_OF_INSTR();
2548}
2549
2550/****************************************************************************
2551REMARKS:
2552Handles opcode 0xa5
2553****************************************************************************/
2554void x86emuOp_movs_word(u8 X86EMU_UNUSED(op1))
2555{
2556 u32 val;
2557 int inc;
2558 u32 count;
2559
2560 START_OF_INSTR();
2561 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002562 DECODE_PRINTF("MOVS\tDWORD\n");
2563 if (ACCESS_FLAG(F_DF)) /* down */
2564 inc = -4;
2565 else
2566 inc = 4;
Jason Jina63ce952007-07-06 08:34:56 +08002567 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002568 DECODE_PRINTF("MOVS\tWORD\n");
2569 if (ACCESS_FLAG(F_DF)) /* down */
2570 inc = -2;
2571 else
2572 inc = 2;
Jason Jina63ce952007-07-06 08:34:56 +08002573 }
2574 TRACE_AND_STEP();
2575 count = 1;
2576 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002577 /* dont care whether REPE or REPNE */
2578 /* move them until CX is ZERO. */
2579 count = M.x86.R_CX;
2580 M.x86.R_CX = 0;
2581 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
Jason Jina63ce952007-07-06 08:34:56 +08002582 }
2583 while (count--) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002584 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2585 val = fetch_data_long(M.x86.R_SI);
2586 store_data_long_abs(M.x86.R_ES, M.x86.R_DI, val);
2587 } else {
2588 val = fetch_data_word(M.x86.R_SI);
2589 store_data_word_abs(M.x86.R_ES, M.x86.R_DI, (u16)val);
2590 }
2591 M.x86.R_SI += inc;
2592 M.x86.R_DI += inc;
Jason Jina63ce952007-07-06 08:34:56 +08002593 }
2594 DECODE_CLEAR_SEGOVR();
2595 END_OF_INSTR();
2596}
2597
2598/****************************************************************************
2599REMARKS:
2600Handles opcode 0xa6
2601****************************************************************************/
2602void x86emuOp_cmps_byte(u8 X86EMU_UNUSED(op1))
2603{
2604 s8 val1, val2;
2605 int inc;
2606
2607 START_OF_INSTR();
2608 DECODE_PRINTF("CMPS\tBYTE\n");
2609 TRACE_AND_STEP();
2610 if (ACCESS_FLAG(F_DF)) /* down */
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002611 inc = -1;
Jason Jina63ce952007-07-06 08:34:56 +08002612 else
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002613 inc = 1;
Jason Jina63ce952007-07-06 08:34:56 +08002614
2615 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002616 /* REPE */
2617 /* move them until CX is ZERO. */
2618 while (M.x86.R_CX != 0) {
2619 val1 = fetch_data_byte(M.x86.R_SI);
2620 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2621 cmp_byte(val1, val2);
2622 M.x86.R_CX -= 1;
2623 M.x86.R_SI += inc;
2624 M.x86.R_DI += inc;
2625 if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && (ACCESS_FLAG(F_ZF) == 0) ) break;
2626 if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2627 }
2628 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
Jason Jina63ce952007-07-06 08:34:56 +08002629 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002630 val1 = fetch_data_byte(M.x86.R_SI);
2631 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2632 cmp_byte(val1, val2);
2633 M.x86.R_SI += inc;
2634 M.x86.R_DI += inc;
Jason Jina63ce952007-07-06 08:34:56 +08002635 }
2636 DECODE_CLEAR_SEGOVR();
2637 END_OF_INSTR();
2638}
2639
2640/****************************************************************************
2641REMARKS:
2642Handles opcode 0xa7
2643****************************************************************************/
2644void x86emuOp_cmps_word(u8 X86EMU_UNUSED(op1))
2645{
2646 u32 val1,val2;
2647 int inc;
2648
2649 START_OF_INSTR();
2650 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002651 DECODE_PRINTF("CMPS\tDWORD\n");
2652 inc = 4;
Jason Jina63ce952007-07-06 08:34:56 +08002653 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002654 DECODE_PRINTF("CMPS\tWORD\n");
2655 inc = 2;
Jason Jina63ce952007-07-06 08:34:56 +08002656 }
2657 if (ACCESS_FLAG(F_DF)) /* down */
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002658 inc = -inc;
Jason Jina63ce952007-07-06 08:34:56 +08002659
2660 TRACE_AND_STEP();
2661 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002662 /* REPE */
2663 /* move them until CX is ZERO. */
2664 while (M.x86.R_CX != 0) {
2665 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2666 val1 = fetch_data_long(M.x86.R_SI);
2667 val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2668 cmp_long(val1, val2);
2669 } else {
2670 val1 = fetch_data_word(M.x86.R_SI);
2671 val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2672 cmp_word((u16)val1, (u16)val2);
2673 }
2674 M.x86.R_CX -= 1;
2675 M.x86.R_SI += inc;
2676 M.x86.R_DI += inc;
2677 if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && ACCESS_FLAG(F_ZF) == 0 ) break;
2678 if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2679 }
2680 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
Jason Jina63ce952007-07-06 08:34:56 +08002681 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002682 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2683 val1 = fetch_data_long(M.x86.R_SI);
2684 val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2685 cmp_long(val1, val2);
2686 } else {
2687 val1 = fetch_data_word(M.x86.R_SI);
2688 val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2689 cmp_word((u16)val1, (u16)val2);
2690 }
2691 M.x86.R_SI += inc;
2692 M.x86.R_DI += inc;
Jason Jina63ce952007-07-06 08:34:56 +08002693 }
2694 DECODE_CLEAR_SEGOVR();
2695 END_OF_INSTR();
2696}
2697
2698/****************************************************************************
2699REMARKS:
2700Handles opcode 0xa8
2701****************************************************************************/
2702void x86emuOp_test_AL_IMM(u8 X86EMU_UNUSED(op1))
2703{
2704 int imm;
2705
2706 START_OF_INSTR();
2707 DECODE_PRINTF("TEST\tAL,");
2708 imm = fetch_byte_imm();
2709 DECODE_PRINTF2("%04x\n", imm);
2710 TRACE_AND_STEP();
2711 test_byte(M.x86.R_AL, (u8)imm);
2712 DECODE_CLEAR_SEGOVR();
2713 END_OF_INSTR();
2714}
2715
2716/****************************************************************************
2717REMARKS:
2718Handles opcode 0xa9
2719****************************************************************************/
2720void x86emuOp_test_AX_IMM(u8 X86EMU_UNUSED(op1))
2721{
2722 u32 srcval;
2723
2724 START_OF_INSTR();
2725 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002726 DECODE_PRINTF("TEST\tEAX,");
2727 srcval = fetch_long_imm();
Jason Jina63ce952007-07-06 08:34:56 +08002728 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002729 DECODE_PRINTF("TEST\tAX,");
2730 srcval = fetch_word_imm();
Jason Jina63ce952007-07-06 08:34:56 +08002731 }
2732 DECODE_PRINTF2("%x\n", srcval);
2733 TRACE_AND_STEP();
2734 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002735 test_long(M.x86.R_EAX, srcval);
Jason Jina63ce952007-07-06 08:34:56 +08002736 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002737 test_word(M.x86.R_AX, (u16)srcval);
Jason Jina63ce952007-07-06 08:34:56 +08002738 }
2739 DECODE_CLEAR_SEGOVR();
2740 END_OF_INSTR();
2741}
2742
2743/****************************************************************************
2744REMARKS:
2745Handles opcode 0xaa
2746****************************************************************************/
2747void x86emuOp_stos_byte(u8 X86EMU_UNUSED(op1))
2748{
2749 int inc;
2750
2751 START_OF_INSTR();
2752 DECODE_PRINTF("STOS\tBYTE\n");
2753 if (ACCESS_FLAG(F_DF)) /* down */
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002754 inc = -1;
Jason Jina63ce952007-07-06 08:34:56 +08002755 else
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002756 inc = 1;
Jason Jina63ce952007-07-06 08:34:56 +08002757 TRACE_AND_STEP();
2758 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002759 /* dont care whether REPE or REPNE */
2760 /* move them until CX is ZERO. */
2761 while (M.x86.R_CX != 0) {
2762 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
2763 M.x86.R_CX -= 1;
2764 M.x86.R_DI += inc;
2765 }
2766 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
Jason Jina63ce952007-07-06 08:34:56 +08002767 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002768 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
2769 M.x86.R_DI += inc;
Jason Jina63ce952007-07-06 08:34:56 +08002770 }
2771 DECODE_CLEAR_SEGOVR();
2772 END_OF_INSTR();
2773}
2774
2775/****************************************************************************
2776REMARKS:
2777Handles opcode 0xab
2778****************************************************************************/
2779void x86emuOp_stos_word(u8 X86EMU_UNUSED(op1))
2780{
2781 int inc;
2782 u32 count;
2783
2784 START_OF_INSTR();
2785 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002786 DECODE_PRINTF("STOS\tDWORD\n");
2787 if (ACCESS_FLAG(F_DF)) /* down */
2788 inc = -4;
2789 else
2790 inc = 4;
Jason Jina63ce952007-07-06 08:34:56 +08002791 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002792 DECODE_PRINTF("STOS\tWORD\n");
2793 if (ACCESS_FLAG(F_DF)) /* down */
2794 inc = -2;
2795 else
2796 inc = 2;
Jason Jina63ce952007-07-06 08:34:56 +08002797 }
2798 TRACE_AND_STEP();
2799 count = 1;
2800 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002801 /* dont care whether REPE or REPNE */
2802 /* move them until CX is ZERO. */
2803 count = M.x86.R_CX;
2804 M.x86.R_CX = 0;
2805 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
Jason Jina63ce952007-07-06 08:34:56 +08002806 }
2807 while (count--) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002808 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2809 store_data_long_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_EAX);
2810 } else {
2811 store_data_word_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AX);
2812 }
2813 M.x86.R_DI += inc;
Jason Jina63ce952007-07-06 08:34:56 +08002814 }
2815 DECODE_CLEAR_SEGOVR();
2816 END_OF_INSTR();
2817}
2818
2819/****************************************************************************
2820REMARKS:
2821Handles opcode 0xac
2822****************************************************************************/
2823void x86emuOp_lods_byte(u8 X86EMU_UNUSED(op1))
2824{
2825 int inc;
2826
2827 START_OF_INSTR();
2828 DECODE_PRINTF("LODS\tBYTE\n");
2829 TRACE_AND_STEP();
2830 if (ACCESS_FLAG(F_DF)) /* down */
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002831 inc = -1;
Jason Jina63ce952007-07-06 08:34:56 +08002832 else
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002833 inc = 1;
Jason Jina63ce952007-07-06 08:34:56 +08002834 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002835 /* dont care whether REPE or REPNE */
2836 /* move them until CX is ZERO. */
2837 while (M.x86.R_CX != 0) {
2838 M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
2839 M.x86.R_CX -= 1;
2840 M.x86.R_SI += inc;
2841 }
2842 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
Jason Jina63ce952007-07-06 08:34:56 +08002843 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002844 M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
2845 M.x86.R_SI += inc;
Jason Jina63ce952007-07-06 08:34:56 +08002846 }
2847 DECODE_CLEAR_SEGOVR();
2848 END_OF_INSTR();
2849}
2850
2851/****************************************************************************
2852REMARKS:
2853Handles opcode 0xad
2854****************************************************************************/
2855void x86emuOp_lods_word(u8 X86EMU_UNUSED(op1))
2856{
2857 int inc;
2858 u32 count;
2859
2860 START_OF_INSTR();
2861 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002862 DECODE_PRINTF("LODS\tDWORD\n");
2863 if (ACCESS_FLAG(F_DF)) /* down */
2864 inc = -4;
2865 else
2866 inc = 4;
Jason Jina63ce952007-07-06 08:34:56 +08002867 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002868 DECODE_PRINTF("LODS\tWORD\n");
2869 if (ACCESS_FLAG(F_DF)) /* down */
2870 inc = -2;
2871 else
2872 inc = 2;
Jason Jina63ce952007-07-06 08:34:56 +08002873 }
2874 TRACE_AND_STEP();
2875 count = 1;
2876 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002877 /* dont care whether REPE or REPNE */
2878 /* move them until CX is ZERO. */
2879 count = M.x86.R_CX;
2880 M.x86.R_CX = 0;
2881 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
Jason Jina63ce952007-07-06 08:34:56 +08002882 }
2883 while (count--) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002884 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2885 M.x86.R_EAX = fetch_data_long(M.x86.R_SI);
2886 } else {
2887 M.x86.R_AX = fetch_data_word(M.x86.R_SI);
2888 }
2889 M.x86.R_SI += inc;
Jason Jina63ce952007-07-06 08:34:56 +08002890 }
2891 DECODE_CLEAR_SEGOVR();
2892 END_OF_INSTR();
2893}
2894
2895/****************************************************************************
2896REMARKS:
2897Handles opcode 0xae
2898****************************************************************************/
2899void x86emuOp_scas_byte(u8 X86EMU_UNUSED(op1))
2900{
2901 s8 val2;
2902 int inc;
2903
2904 START_OF_INSTR();
2905 DECODE_PRINTF("SCAS\tBYTE\n");
2906 TRACE_AND_STEP();
2907 if (ACCESS_FLAG(F_DF)) /* down */
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002908 inc = -1;
Jason Jina63ce952007-07-06 08:34:56 +08002909 else
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002910 inc = 1;
Jason Jina63ce952007-07-06 08:34:56 +08002911 if (M.x86.mode & SYSMODE_PREFIX_REPE) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002912 /* REPE */
2913 /* move them until CX is ZERO. */
2914 while (M.x86.R_CX != 0) {
2915 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2916 cmp_byte(M.x86.R_AL, val2);
2917 M.x86.R_CX -= 1;
2918 M.x86.R_DI += inc;
2919 if (ACCESS_FLAG(F_ZF) == 0)
2920 break;
2921 }
2922 M.x86.mode &= ~SYSMODE_PREFIX_REPE;
Jason Jina63ce952007-07-06 08:34:56 +08002923 } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002924 /* REPNE */
2925 /* move them until CX is ZERO. */
2926 while (M.x86.R_CX != 0) {
2927 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2928 cmp_byte(M.x86.R_AL, val2);
2929 M.x86.R_CX -= 1;
2930 M.x86.R_DI += inc;
2931 if (ACCESS_FLAG(F_ZF))
2932 break; /* zero flag set means equal */
2933 }
2934 M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
Jason Jina63ce952007-07-06 08:34:56 +08002935 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002936 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2937 cmp_byte(M.x86.R_AL, val2);
2938 M.x86.R_DI += inc;
Jason Jina63ce952007-07-06 08:34:56 +08002939 }
2940 DECODE_CLEAR_SEGOVR();
2941 END_OF_INSTR();
2942}
2943
2944/****************************************************************************
2945REMARKS:
2946Handles opcode 0xaf
2947****************************************************************************/
2948void x86emuOp_scas_word(u8 X86EMU_UNUSED(op1))
2949{
2950 int inc;
2951 u32 val;
2952
2953 START_OF_INSTR();
2954 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002955 DECODE_PRINTF("SCAS\tDWORD\n");
2956 if (ACCESS_FLAG(F_DF)) /* down */
2957 inc = -4;
2958 else
2959 inc = 4;
Jason Jina63ce952007-07-06 08:34:56 +08002960 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002961 DECODE_PRINTF("SCAS\tWORD\n");
2962 if (ACCESS_FLAG(F_DF)) /* down */
2963 inc = -2;
2964 else
2965 inc = 2;
Jason Jina63ce952007-07-06 08:34:56 +08002966 }
2967 TRACE_AND_STEP();
2968 if (M.x86.mode & SYSMODE_PREFIX_REPE) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002969 /* REPE */
2970 /* move them until CX is ZERO. */
2971 while (M.x86.R_CX != 0) {
2972 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2973 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2974 cmp_long(M.x86.R_EAX, val);
2975 } else {
2976 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2977 cmp_word(M.x86.R_AX, (u16)val);
2978 }
2979 M.x86.R_CX -= 1;
2980 M.x86.R_DI += inc;
2981 if (ACCESS_FLAG(F_ZF) == 0)
2982 break;
2983 }
2984 M.x86.mode &= ~SYSMODE_PREFIX_REPE;
Jason Jina63ce952007-07-06 08:34:56 +08002985 } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02002986 /* REPNE */
2987 /* move them until CX is ZERO. */
2988 while (M.x86.R_CX != 0) {
2989 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2990 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2991 cmp_long(M.x86.R_EAX, val);
2992 } else {
2993 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2994 cmp_word(M.x86.R_AX, (u16)val);
2995 }
2996 M.x86.R_CX -= 1;
2997 M.x86.R_DI += inc;
2998 if (ACCESS_FLAG(F_ZF))
2999 break; /* zero flag set means equal */
3000 }
3001 M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
Jason Jina63ce952007-07-06 08:34:56 +08003002 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003003 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3004 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
3005 cmp_long(M.x86.R_EAX, val);
3006 } else {
3007 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
3008 cmp_word(M.x86.R_AX, (u16)val);
3009 }
3010 M.x86.R_DI += inc;
Jason Jina63ce952007-07-06 08:34:56 +08003011 }
3012 DECODE_CLEAR_SEGOVR();
3013 END_OF_INSTR();
3014}
3015
3016/****************************************************************************
3017REMARKS:
3018Handles opcode 0xb0 - 0xb7
3019****************************************************************************/
3020void x86emuOp_mov_byte_register_IMM(u8 op1)
3021{
3022 u8 imm, *ptr;
3023
3024 START_OF_INSTR();
3025 DECODE_PRINTF("MOV\t");
3026 ptr = DECODE_RM_BYTE_REGISTER(op1 & 0x7);
3027 DECODE_PRINTF(",");
3028 imm = fetch_byte_imm();
3029 DECODE_PRINTF2("%x\n", imm);
3030 TRACE_AND_STEP();
3031 *ptr = imm;
3032 DECODE_CLEAR_SEGOVR();
3033 END_OF_INSTR();
3034}
3035
3036/****************************************************************************
3037REMARKS:
3038Handles opcode 0xb8 - 0xbf
3039****************************************************************************/
3040void x86emuOp_mov_word_register_IMM(u8 X86EMU_UNUSED(op1))
3041{
3042 u32 srcval;
3043
3044 op1 &= 0x7;
3045
3046 START_OF_INSTR();
3047 DECODE_PRINTF("MOV\t");
3048 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003049 u32 *reg32;
3050 reg32 = DECODE_RM_LONG_REGISTER(op1);
3051 srcval = fetch_long_imm();
3052 DECODE_PRINTF2(",%x\n", srcval);
3053 TRACE_AND_STEP();
3054 *reg32 = srcval;
Jason Jina63ce952007-07-06 08:34:56 +08003055 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003056 u16 *reg16;
3057 reg16 = DECODE_RM_WORD_REGISTER(op1);
3058 srcval = fetch_word_imm();
3059 DECODE_PRINTF2(",%x\n", srcval);
3060 TRACE_AND_STEP();
3061 *reg16 = (u16)srcval;
Jason Jina63ce952007-07-06 08:34:56 +08003062 }
3063 DECODE_CLEAR_SEGOVR();
3064 END_OF_INSTR();
3065}
3066
3067/****************************************************************************
3068REMARKS:
3069Handles opcode 0xc0
3070****************************************************************************/
3071void x86emuOp_opcC0_byte_RM_MEM(u8 X86EMU_UNUSED(op1))
3072{
3073 int mod, rl, rh;
3074 u8 *destreg;
3075 uint destoffset;
3076 u8 destval;
3077 u8 amt;
3078
3079 /*
3080 * Yet another weirdo special case instruction format. Part of
3081 * the opcode held below in "RH". Doubly nested case would
3082 * result, except that the decoded instruction
3083 */
3084 START_OF_INSTR();
3085 FETCH_DECODE_MODRM(mod, rh, rl);
3086#ifdef DEBUG
3087 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003088 /* XXX DECODE_PRINTF may be changed to something more
3089 general, so that it is important to leave the strings
3090 in the same format, even though the result is that the
3091 above test is done twice. */
Jason Jina63ce952007-07-06 08:34:56 +08003092
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003093 switch (rh) {
3094 case 0:
3095 DECODE_PRINTF("ROL\t");
3096 break;
3097 case 1:
3098 DECODE_PRINTF("ROR\t");
3099 break;
3100 case 2:
3101 DECODE_PRINTF("RCL\t");
3102 break;
3103 case 3:
3104 DECODE_PRINTF("RCR\t");
3105 break;
3106 case 4:
3107 DECODE_PRINTF("SHL\t");
3108 break;
3109 case 5:
3110 DECODE_PRINTF("SHR\t");
3111 break;
3112 case 6:
3113 DECODE_PRINTF("SAL\t");
3114 break;
3115 case 7:
3116 DECODE_PRINTF("SAR\t");
3117 break;
3118 }
Jason Jina63ce952007-07-06 08:34:56 +08003119 }
3120#endif
3121 /* know operation, decode the mod byte to find the addressing
3122 mode. */
3123 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003124 DECODE_PRINTF("BYTE PTR ");
3125 destoffset = decode_rmXX_address(mod, rl);
3126 amt = fetch_byte_imm();
3127 DECODE_PRINTF2(",%x\n", amt);
3128 destval = fetch_data_byte(destoffset);
3129 TRACE_AND_STEP();
3130 destval = (*opcD0_byte_operation[rh]) (destval, amt);
3131 store_data_byte(destoffset, destval);
3132 } else { /* register to register */
3133 destreg = DECODE_RM_BYTE_REGISTER(rl);
3134 amt = fetch_byte_imm();
3135 DECODE_PRINTF2(",%x\n", amt);
3136 TRACE_AND_STEP();
3137 destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3138 *destreg = destval;
Jason Jina63ce952007-07-06 08:34:56 +08003139 }
3140 DECODE_CLEAR_SEGOVR();
3141 END_OF_INSTR();
3142}
3143
3144/****************************************************************************
3145REMARKS:
3146Handles opcode 0xc1
3147****************************************************************************/
3148void x86emuOp_opcC1_word_RM_MEM(u8 X86EMU_UNUSED(op1))
3149{
3150 int mod, rl, rh;
3151 uint destoffset;
3152 u8 amt;
3153
3154 /*
3155 * Yet another weirdo special case instruction format. Part of
3156 * the opcode held below in "RH". Doubly nested case would
3157 * result, except that the decoded instruction
3158 */
3159 START_OF_INSTR();
3160 FETCH_DECODE_MODRM(mod, rh, rl);
3161#ifdef DEBUG
3162 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003163 /* XXX DECODE_PRINTF may be changed to something more
3164 general, so that it is important to leave the strings
3165 in the same format, even though the result is that the
3166 above test is done twice. */
Jason Jina63ce952007-07-06 08:34:56 +08003167
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003168 switch (rh) {
3169 case 0:
3170 DECODE_PRINTF("ROL\t");
3171 break;
3172 case 1:
3173 DECODE_PRINTF("ROR\t");
3174 break;
3175 case 2:
3176 DECODE_PRINTF("RCL\t");
3177 break;
3178 case 3:
3179 DECODE_PRINTF("RCR\t");
3180 break;
3181 case 4:
3182 DECODE_PRINTF("SHL\t");
3183 break;
3184 case 5:
3185 DECODE_PRINTF("SHR\t");
3186 break;
3187 case 6:
3188 DECODE_PRINTF("SAL\t");
3189 break;
3190 case 7:
3191 DECODE_PRINTF("SAR\t");
3192 break;
3193 }
Jason Jina63ce952007-07-06 08:34:56 +08003194 }
3195#endif
3196 /* know operation, decode the mod byte to find the addressing
3197 mode. */
3198 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003199 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3200 u32 destval;
Jason Jina63ce952007-07-06 08:34:56 +08003201
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003202 DECODE_PRINTF("DWORD PTR ");
3203 destoffset = decode_rmXX_address(mod, rl);
3204 amt = fetch_byte_imm();
3205 DECODE_PRINTF2(",%x\n", amt);
3206 destval = fetch_data_long(destoffset);
3207 TRACE_AND_STEP();
3208 destval = (*opcD1_long_operation[rh]) (destval, amt);
3209 store_data_long(destoffset, destval);
3210 } else {
3211 u16 destval;
Jason Jina63ce952007-07-06 08:34:56 +08003212
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003213 DECODE_PRINTF("WORD PTR ");
3214 destoffset = decode_rmXX_address(mod, rl);
3215 amt = fetch_byte_imm();
3216 DECODE_PRINTF2(",%x\n", amt);
3217 destval = fetch_data_word(destoffset);
3218 TRACE_AND_STEP();
3219 destval = (*opcD1_word_operation[rh]) (destval, amt);
3220 store_data_word(destoffset, destval);
3221 }
3222 } else { /* register to register */
3223 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3224 u32 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08003225
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003226 destreg = DECODE_RM_LONG_REGISTER(rl);
3227 amt = fetch_byte_imm();
3228 DECODE_PRINTF2(",%x\n", amt);
3229 TRACE_AND_STEP();
3230 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3231 } else {
3232 u16 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08003233
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003234 destreg = DECODE_RM_WORD_REGISTER(rl);
3235 amt = fetch_byte_imm();
3236 DECODE_PRINTF2(",%x\n", amt);
3237 TRACE_AND_STEP();
3238 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
3239 }
Jason Jina63ce952007-07-06 08:34:56 +08003240 }
3241 DECODE_CLEAR_SEGOVR();
3242 END_OF_INSTR();
3243}
3244
3245/****************************************************************************
3246REMARKS:
3247Handles opcode 0xc2
3248****************************************************************************/
3249void x86emuOp_ret_near_IMM(u8 X86EMU_UNUSED(op1))
3250{
3251 u16 imm;
3252
3253 START_OF_INSTR();
3254 DECODE_PRINTF("RET\t");
3255 imm = fetch_word_imm();
3256 DECODE_PRINTF2("%x\n", imm);
3257 RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
3258 TRACE_AND_STEP();
3259 M.x86.R_IP = pop_word();
3260 M.x86.R_SP += imm;
3261 DECODE_CLEAR_SEGOVR();
3262 END_OF_INSTR();
3263}
3264
3265/****************************************************************************
3266REMARKS:
3267Handles opcode 0xc3
3268****************************************************************************/
3269void x86emuOp_ret_near(u8 X86EMU_UNUSED(op1))
3270{
3271 START_OF_INSTR();
3272 DECODE_PRINTF("RET\n");
3273 RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
3274 TRACE_AND_STEP();
3275 M.x86.R_IP = pop_word();
3276 DECODE_CLEAR_SEGOVR();
3277 END_OF_INSTR();
3278}
3279
3280/****************************************************************************
3281REMARKS:
3282Handles opcode 0xc4
3283****************************************************************************/
3284void x86emuOp_les_R_IMM(u8 X86EMU_UNUSED(op1))
3285{
3286 int mod, rh, rl;
3287 u16 *dstreg;
3288 uint srcoffset;
3289
3290 START_OF_INSTR();
3291 DECODE_PRINTF("LES\t");
3292 FETCH_DECODE_MODRM(mod, rh, rl);
3293 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003294 dstreg = DECODE_RM_WORD_REGISTER(rh);
3295 DECODE_PRINTF(",");
3296 srcoffset = decode_rmXX_address(mod, rl);
3297 DECODE_PRINTF("\n");
3298 TRACE_AND_STEP();
3299 *dstreg = fetch_data_word(srcoffset);
3300 M.x86.R_ES = fetch_data_word(srcoffset + 2);
Jason Jina63ce952007-07-06 08:34:56 +08003301 }
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003302 /* else UNDEFINED! register to register */
Jason Jina63ce952007-07-06 08:34:56 +08003303
3304 DECODE_CLEAR_SEGOVR();
3305 END_OF_INSTR();
3306}
3307
3308/****************************************************************************
3309REMARKS:
3310Handles opcode 0xc5
3311****************************************************************************/
3312void x86emuOp_lds_R_IMM(u8 X86EMU_UNUSED(op1))
3313{
3314 int mod, rh, rl;
3315 u16 *dstreg;
3316 uint srcoffset;
3317
3318 START_OF_INSTR();
3319 DECODE_PRINTF("LDS\t");
3320 FETCH_DECODE_MODRM(mod, rh, rl);
3321 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003322 dstreg = DECODE_RM_WORD_REGISTER(rh);
3323 DECODE_PRINTF(",");
3324 srcoffset = decode_rmXX_address(mod, rl);
3325 DECODE_PRINTF("\n");
3326 TRACE_AND_STEP();
3327 *dstreg = fetch_data_word(srcoffset);
3328 M.x86.R_DS = fetch_data_word(srcoffset + 2);
Jason Jina63ce952007-07-06 08:34:56 +08003329 }
3330 /* else UNDEFINED! */
3331 DECODE_CLEAR_SEGOVR();
3332 END_OF_INSTR();
3333}
3334
3335/****************************************************************************
3336REMARKS:
3337Handles opcode 0xc6
3338****************************************************************************/
3339void x86emuOp_mov_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
3340{
3341 int mod, rl, rh;
3342 u8 *destreg;
3343 uint destoffset;
3344 u8 imm;
3345
3346 START_OF_INSTR();
3347 DECODE_PRINTF("MOV\t");
3348 FETCH_DECODE_MODRM(mod, rh, rl);
3349 if (rh != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003350 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE c6\n");
3351 HALT_SYS();
Jason Jina63ce952007-07-06 08:34:56 +08003352 }
3353 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003354 DECODE_PRINTF("BYTE PTR ");
3355 destoffset = decode_rmXX_address(mod, rl);
3356 imm = fetch_byte_imm();
3357 DECODE_PRINTF2(",%2x\n", imm);
3358 TRACE_AND_STEP();
3359 store_data_byte(destoffset, imm);
3360 } else { /* register to register */
3361 destreg = DECODE_RM_BYTE_REGISTER(rl);
3362 imm = fetch_byte_imm();
3363 DECODE_PRINTF2(",%2x\n", imm);
3364 TRACE_AND_STEP();
3365 *destreg = imm;
Jason Jina63ce952007-07-06 08:34:56 +08003366 }
3367 DECODE_CLEAR_SEGOVR();
3368 END_OF_INSTR();
3369}
3370
3371/****************************************************************************
3372REMARKS:
3373Handles opcode 0xc7
3374****************************************************************************/
3375void x86emuOp_mov_word_RM_IMM(u8 X86EMU_UNUSED(op1))
3376{
3377 int mod, rl, rh;
3378 uint destoffset;
3379
3380 START_OF_INSTR();
3381 DECODE_PRINTF("MOV\t");
3382 FETCH_DECODE_MODRM(mod, rh, rl);
3383 if (rh != 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003384 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
3385 HALT_SYS();
Jason Jina63ce952007-07-06 08:34:56 +08003386 }
3387 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003388 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3389 u32 imm;
Jason Jina63ce952007-07-06 08:34:56 +08003390
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003391 DECODE_PRINTF("DWORD PTR ");
3392 destoffset = decode_rmXX_address(mod, rl);
3393 imm = fetch_long_imm();
3394 DECODE_PRINTF2(",%x\n", imm);
3395 TRACE_AND_STEP();
3396 store_data_long(destoffset, imm);
3397 } else {
3398 u16 imm;
Jason Jina63ce952007-07-06 08:34:56 +08003399
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003400 DECODE_PRINTF("WORD PTR ");
3401 destoffset = decode_rmXX_address(mod, rl);
3402 imm = fetch_word_imm();
3403 DECODE_PRINTF2(",%x\n", imm);
3404 TRACE_AND_STEP();
3405 store_data_word(destoffset, imm);
3406 }
3407 } else { /* register to register */
3408 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Jason Jina63ce952007-07-06 08:34:56 +08003409 u32 *destreg;
3410 u32 imm;
3411
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003412 destreg = DECODE_RM_LONG_REGISTER(rl);
3413 imm = fetch_long_imm();
3414 DECODE_PRINTF2(",%x\n", imm);
3415 TRACE_AND_STEP();
3416 *destreg = imm;
3417 } else {
Jason Jina63ce952007-07-06 08:34:56 +08003418 u16 *destreg;
3419 u16 imm;
3420
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003421 destreg = DECODE_RM_WORD_REGISTER(rl);
3422 imm = fetch_word_imm();
3423 DECODE_PRINTF2(",%x\n", imm);
3424 TRACE_AND_STEP();
3425 *destreg = imm;
3426 }
Jason Jina63ce952007-07-06 08:34:56 +08003427 }
3428 DECODE_CLEAR_SEGOVR();
3429 END_OF_INSTR();
3430}
3431
3432/****************************************************************************
3433REMARKS:
3434Handles opcode 0xc8
3435****************************************************************************/
3436void x86emuOp_enter(u8 X86EMU_UNUSED(op1))
3437{
3438 u16 local,frame_pointer;
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003439 u8 nesting;
Jason Jina63ce952007-07-06 08:34:56 +08003440 int i;
3441
3442 START_OF_INSTR();
3443 local = fetch_word_imm();
3444 nesting = fetch_byte_imm();
3445 DECODE_PRINTF2("ENTER %x\n", local);
3446 DECODE_PRINTF2(",%x\n", nesting);
3447 TRACE_AND_STEP();
3448 push_word(M.x86.R_BP);
3449 frame_pointer = M.x86.R_SP;
3450 if (nesting > 0) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003451 for (i = 1; i < nesting; i++) {
3452 M.x86.R_BP -= 2;
3453 push_word(fetch_data_word_abs(M.x86.R_SS, M.x86.R_BP));
3454 }
3455 push_word(frame_pointer);
3456 }
Jason Jina63ce952007-07-06 08:34:56 +08003457 M.x86.R_BP = frame_pointer;
3458 M.x86.R_SP = (u16)(M.x86.R_SP - local);
3459 DECODE_CLEAR_SEGOVR();
3460 END_OF_INSTR();
3461}
3462
3463/****************************************************************************
3464REMARKS:
3465Handles opcode 0xc9
3466****************************************************************************/
3467void x86emuOp_leave(u8 X86EMU_UNUSED(op1))
3468{
3469 START_OF_INSTR();
3470 DECODE_PRINTF("LEAVE\n");
3471 TRACE_AND_STEP();
3472 M.x86.R_SP = M.x86.R_BP;
3473 M.x86.R_BP = pop_word();
3474 DECODE_CLEAR_SEGOVR();
3475 END_OF_INSTR();
3476}
3477
3478/****************************************************************************
3479REMARKS:
3480Handles opcode 0xca
3481****************************************************************************/
3482void x86emuOp_ret_far_IMM(u8 X86EMU_UNUSED(op1))
3483{
3484 u16 imm;
3485
3486 START_OF_INSTR();
3487 DECODE_PRINTF("RETF\t");
3488 imm = fetch_word_imm();
3489 DECODE_PRINTF2("%x\n", imm);
3490 RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
3491 TRACE_AND_STEP();
3492 M.x86.R_IP = pop_word();
3493 M.x86.R_CS = pop_word();
3494 M.x86.R_SP += imm;
3495 DECODE_CLEAR_SEGOVR();
3496 END_OF_INSTR();
3497}
3498
3499/****************************************************************************
3500REMARKS:
3501Handles opcode 0xcb
3502****************************************************************************/
3503void x86emuOp_ret_far(u8 X86EMU_UNUSED(op1))
3504{
3505 START_OF_INSTR();
3506 DECODE_PRINTF("RETF\n");
3507 RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
3508 TRACE_AND_STEP();
3509 M.x86.R_IP = pop_word();
3510 M.x86.R_CS = pop_word();
3511 DECODE_CLEAR_SEGOVR();
3512 END_OF_INSTR();
3513}
3514
3515/****************************************************************************
3516REMARKS:
3517Handles opcode 0xcc
3518****************************************************************************/
3519void x86emuOp_int3(u8 X86EMU_UNUSED(op1))
3520{
Jason Jina63ce952007-07-06 08:34:56 +08003521 START_OF_INSTR();
3522 DECODE_PRINTF("INT 3\n");
Kumar Galacac607a2011-11-09 06:21:09 +00003523 (void)mem_access_word(3 * 4 + 2);
Jason Jina63ce952007-07-06 08:34:56 +08003524 /* access the segment register */
3525 TRACE_AND_STEP();
3526 if (_X86EMU_intrTab[3]) {
3527 (*_X86EMU_intrTab[3])(3);
3528 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003529 push_word((u16)M.x86.R_FLG);
3530 CLEAR_FLAG(F_IF);
3531 CLEAR_FLAG(F_TF);
3532 push_word(M.x86.R_CS);
3533 M.x86.R_CS = mem_access_word(3 * 4 + 2);
3534 push_word(M.x86.R_IP);
3535 M.x86.R_IP = mem_access_word(3 * 4);
Jason Jina63ce952007-07-06 08:34:56 +08003536 }
3537 DECODE_CLEAR_SEGOVR();
3538 END_OF_INSTR();
3539}
3540
3541/****************************************************************************
3542REMARKS:
3543Handles opcode 0xcd
3544****************************************************************************/
3545void x86emuOp_int_IMM(u8 X86EMU_UNUSED(op1))
3546{
Jason Jina63ce952007-07-06 08:34:56 +08003547 u8 intnum;
3548
3549 START_OF_INSTR();
3550 DECODE_PRINTF("INT\t");
3551 intnum = fetch_byte_imm();
3552 DECODE_PRINTF2("%x\n", intnum);
Kumar Galacac607a2011-11-09 06:21:09 +00003553 (void)mem_access_word(intnum * 4 + 2);
Jason Jina63ce952007-07-06 08:34:56 +08003554 TRACE_AND_STEP();
3555 if (_X86EMU_intrTab[intnum]) {
3556 (*_X86EMU_intrTab[intnum])(intnum);
3557 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003558 push_word((u16)M.x86.R_FLG);
3559 CLEAR_FLAG(F_IF);
3560 CLEAR_FLAG(F_TF);
3561 push_word(M.x86.R_CS);
3562 M.x86.R_CS = mem_access_word(intnum * 4 + 2);
3563 push_word(M.x86.R_IP);
3564 M.x86.R_IP = mem_access_word(intnum * 4);
Jason Jina63ce952007-07-06 08:34:56 +08003565 }
3566 DECODE_CLEAR_SEGOVR();
3567 END_OF_INSTR();
3568}
3569
3570/****************************************************************************
3571REMARKS:
3572Handles opcode 0xce
3573****************************************************************************/
3574void x86emuOp_into(u8 X86EMU_UNUSED(op1))
3575{
Jason Jina63ce952007-07-06 08:34:56 +08003576 START_OF_INSTR();
3577 DECODE_PRINTF("INTO\n");
3578 TRACE_AND_STEP();
3579 if (ACCESS_FLAG(F_OF)) {
Kumar Galacac607a2011-11-09 06:21:09 +00003580 (void)mem_access_word(4 * 4 + 2);
Jason Jina63ce952007-07-06 08:34:56 +08003581 if (_X86EMU_intrTab[4]) {
3582 (*_X86EMU_intrTab[4])(4);
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003583 } else {
3584 push_word((u16)M.x86.R_FLG);
3585 CLEAR_FLAG(F_IF);
3586 CLEAR_FLAG(F_TF);
3587 push_word(M.x86.R_CS);
3588 M.x86.R_CS = mem_access_word(4 * 4 + 2);
3589 push_word(M.x86.R_IP);
3590 M.x86.R_IP = mem_access_word(4 * 4);
3591 }
Jason Jina63ce952007-07-06 08:34:56 +08003592 }
3593 DECODE_CLEAR_SEGOVR();
3594 END_OF_INSTR();
3595}
3596
3597/****************************************************************************
3598REMARKS:
3599Handles opcode 0xcf
3600****************************************************************************/
3601void x86emuOp_iret(u8 X86EMU_UNUSED(op1))
3602{
3603 START_OF_INSTR();
3604 DECODE_PRINTF("IRET\n");
3605
3606 TRACE_AND_STEP();
3607
3608 M.x86.R_IP = pop_word();
3609 M.x86.R_CS = pop_word();
3610 M.x86.R_FLG = pop_word();
3611 DECODE_CLEAR_SEGOVR();
3612 END_OF_INSTR();
3613}
3614
3615/****************************************************************************
3616REMARKS:
3617Handles opcode 0xd0
3618****************************************************************************/
3619void x86emuOp_opcD0_byte_RM_1(u8 X86EMU_UNUSED(op1))
3620{
3621 int mod, rl, rh;
3622 u8 *destreg;
3623 uint destoffset;
3624 u8 destval;
3625
3626 /*
3627 * Yet another weirdo special case instruction format. Part of
3628 * the opcode held below in "RH". Doubly nested case would
3629 * result, except that the decoded instruction
3630 */
3631 START_OF_INSTR();
3632 FETCH_DECODE_MODRM(mod, rh, rl);
3633#ifdef DEBUG
3634 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003635 /* XXX DECODE_PRINTF may be changed to something more
3636 general, so that it is important to leave the strings
3637 in the same format, even though the result is that the
3638 above test is done twice. */
3639 switch (rh) {
3640 case 0:
3641 DECODE_PRINTF("ROL\t");
3642 break;
3643 case 1:
3644 DECODE_PRINTF("ROR\t");
3645 break;
3646 case 2:
3647 DECODE_PRINTF("RCL\t");
3648 break;
3649 case 3:
3650 DECODE_PRINTF("RCR\t");
3651 break;
3652 case 4:
3653 DECODE_PRINTF("SHL\t");
3654 break;
3655 case 5:
3656 DECODE_PRINTF("SHR\t");
3657 break;
3658 case 6:
3659 DECODE_PRINTF("SAL\t");
3660 break;
3661 case 7:
3662 DECODE_PRINTF("SAR\t");
3663 break;
3664 }
Jason Jina63ce952007-07-06 08:34:56 +08003665 }
3666#endif
3667 /* know operation, decode the mod byte to find the addressing
3668 mode. */
3669 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003670 DECODE_PRINTF("BYTE PTR ");
3671 destoffset = decode_rmXX_address(mod, rl);
3672 DECODE_PRINTF(",1\n");
3673 destval = fetch_data_byte(destoffset);
3674 TRACE_AND_STEP();
3675 destval = (*opcD0_byte_operation[rh]) (destval, 1);
3676 store_data_byte(destoffset, destval);
3677 } else { /* register to register */
3678 destreg = DECODE_RM_BYTE_REGISTER(rl);
3679 DECODE_PRINTF(",1\n");
3680 TRACE_AND_STEP();
3681 destval = (*opcD0_byte_operation[rh]) (*destreg, 1);
3682 *destreg = destval;
Jason Jina63ce952007-07-06 08:34:56 +08003683 }
3684 DECODE_CLEAR_SEGOVR();
3685 END_OF_INSTR();
3686}
3687
3688/****************************************************************************
3689REMARKS:
3690Handles opcode 0xd1
3691****************************************************************************/
3692void x86emuOp_opcD1_word_RM_1(u8 X86EMU_UNUSED(op1))
3693{
3694 int mod, rl, rh;
3695 uint destoffset;
3696
3697 /*
3698 * Yet another weirdo special case instruction format. Part of
3699 * the opcode held below in "RH". Doubly nested case would
3700 * result, except that the decoded instruction
3701 */
3702 START_OF_INSTR();
3703 FETCH_DECODE_MODRM(mod, rh, rl);
3704#ifdef DEBUG
3705 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003706 /* XXX DECODE_PRINTF may be changed to something more
3707 general, so that it is important to leave the strings
3708 in the same format, even though the result is that the
3709 above test is done twice. */
3710 switch (rh) {
3711 case 0:
3712 DECODE_PRINTF("ROL\t");
3713 break;
3714 case 1:
3715 DECODE_PRINTF("ROR\t");
3716 break;
3717 case 2:
3718 DECODE_PRINTF("RCL\t");
3719 break;
3720 case 3:
3721 DECODE_PRINTF("RCR\t");
3722 break;
3723 case 4:
3724 DECODE_PRINTF("SHL\t");
3725 break;
3726 case 5:
3727 DECODE_PRINTF("SHR\t");
3728 break;
3729 case 6:
3730 DECODE_PRINTF("SAL\t");
3731 break;
3732 case 7:
3733 DECODE_PRINTF("SAR\t");
3734 break;
3735 }
Jason Jina63ce952007-07-06 08:34:56 +08003736 }
3737#endif
3738 /* know operation, decode the mod byte to find the addressing
3739 mode. */
3740 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003741 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3742 u32 destval;
Jason Jina63ce952007-07-06 08:34:56 +08003743
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003744 DECODE_PRINTF("DWORD PTR ");
3745 destoffset = decode_rmXX_address(mod, rl);
3746 DECODE_PRINTF(",1\n");
3747 destval = fetch_data_long(destoffset);
3748 TRACE_AND_STEP();
3749 destval = (*opcD1_long_operation[rh]) (destval, 1);
3750 store_data_long(destoffset, destval);
3751 } else {
3752 u16 destval;
Jason Jina63ce952007-07-06 08:34:56 +08003753
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003754 DECODE_PRINTF("WORD PTR ");
3755 destoffset = decode_rmXX_address(mod, rl);
3756 DECODE_PRINTF(",1\n");
3757 destval = fetch_data_word(destoffset);
3758 TRACE_AND_STEP();
3759 destval = (*opcD1_word_operation[rh]) (destval, 1);
3760 store_data_word(destoffset, destval);
3761 }
3762 } else { /* register to register */
3763 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Jason Jina63ce952007-07-06 08:34:56 +08003764 u32 destval;
3765 u32 *destreg;
3766
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003767 destreg = DECODE_RM_LONG_REGISTER(rl);
3768 DECODE_PRINTF(",1\n");
3769 TRACE_AND_STEP();
3770 destval = (*opcD1_long_operation[rh]) (*destreg, 1);
3771 *destreg = destval;
3772 } else {
Jason Jina63ce952007-07-06 08:34:56 +08003773 u16 destval;
3774 u16 *destreg;
3775
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003776 destreg = DECODE_RM_WORD_REGISTER(rl);
3777 DECODE_PRINTF(",1\n");
3778 TRACE_AND_STEP();
3779 destval = (*opcD1_word_operation[rh]) (*destreg, 1);
3780 *destreg = destval;
3781 }
Jason Jina63ce952007-07-06 08:34:56 +08003782 }
3783 DECODE_CLEAR_SEGOVR();
3784 END_OF_INSTR();
3785}
3786
3787/****************************************************************************
3788REMARKS:
3789Handles opcode 0xd2
3790****************************************************************************/
3791void x86emuOp_opcD2_byte_RM_CL(u8 X86EMU_UNUSED(op1))
3792{
3793 int mod, rl, rh;
3794 u8 *destreg;
3795 uint destoffset;
3796 u8 destval;
3797 u8 amt;
3798
3799 /*
3800 * Yet another weirdo special case instruction format. Part of
3801 * the opcode held below in "RH". Doubly nested case would
3802 * result, except that the decoded instruction
3803 */
3804 START_OF_INSTR();
3805 FETCH_DECODE_MODRM(mod, rh, rl);
3806#ifdef DEBUG
3807 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003808 /* XXX DECODE_PRINTF may be changed to something more
3809 general, so that it is important to leave the strings
3810 in the same format, even though the result is that the
3811 above test is done twice. */
3812 switch (rh) {
3813 case 0:
3814 DECODE_PRINTF("ROL\t");
3815 break;
3816 case 1:
3817 DECODE_PRINTF("ROR\t");
3818 break;
3819 case 2:
3820 DECODE_PRINTF("RCL\t");
3821 break;
3822 case 3:
3823 DECODE_PRINTF("RCR\t");
3824 break;
3825 case 4:
3826 DECODE_PRINTF("SHL\t");
3827 break;
3828 case 5:
3829 DECODE_PRINTF("SHR\t");
3830 break;
3831 case 6:
3832 DECODE_PRINTF("SAL\t");
3833 break;
3834 case 7:
3835 DECODE_PRINTF("SAR\t");
3836 break;
3837 }
Jason Jina63ce952007-07-06 08:34:56 +08003838 }
3839#endif
3840 /* know operation, decode the mod byte to find the addressing
3841 mode. */
3842 amt = M.x86.R_CL;
3843 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003844 DECODE_PRINTF("BYTE PTR ");
3845 destoffset = decode_rmXX_address(mod, rl);
3846 DECODE_PRINTF(",CL\n");
3847 destval = fetch_data_byte(destoffset);
3848 TRACE_AND_STEP();
3849 destval = (*opcD0_byte_operation[rh]) (destval, amt);
3850 store_data_byte(destoffset, destval);
3851 } else { /* register to register */
3852 destreg = DECODE_RM_BYTE_REGISTER(rl);
3853 DECODE_PRINTF(",CL\n");
3854 TRACE_AND_STEP();
3855 destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3856 *destreg = destval;
Jason Jina63ce952007-07-06 08:34:56 +08003857 }
3858 DECODE_CLEAR_SEGOVR();
3859 END_OF_INSTR();
3860}
3861
3862/****************************************************************************
3863REMARKS:
3864Handles opcode 0xd3
3865****************************************************************************/
3866void x86emuOp_opcD3_word_RM_CL(u8 X86EMU_UNUSED(op1))
3867{
3868 int mod, rl, rh;
3869 uint destoffset;
3870 u8 amt;
3871
3872 /*
3873 * Yet another weirdo special case instruction format. Part of
3874 * the opcode held below in "RH". Doubly nested case would
3875 * result, except that the decoded instruction
3876 */
3877 START_OF_INSTR();
3878 FETCH_DECODE_MODRM(mod, rh, rl);
3879#ifdef DEBUG
3880 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003881 /* XXX DECODE_PRINTF may be changed to something more
3882 general, so that it is important to leave the strings
3883 in the same format, even though the result is that the
3884 above test is done twice. */
3885 switch (rh) {
3886 case 0:
3887 DECODE_PRINTF("ROL\t");
3888 break;
3889 case 1:
3890 DECODE_PRINTF("ROR\t");
3891 break;
3892 case 2:
3893 DECODE_PRINTF("RCL\t");
3894 break;
3895 case 3:
3896 DECODE_PRINTF("RCR\t");
3897 break;
3898 case 4:
3899 DECODE_PRINTF("SHL\t");
3900 break;
3901 case 5:
3902 DECODE_PRINTF("SHR\t");
3903 break;
3904 case 6:
3905 DECODE_PRINTF("SAL\t");
3906 break;
3907 case 7:
3908 DECODE_PRINTF("SAR\t");
3909 break;
3910 }
Jason Jina63ce952007-07-06 08:34:56 +08003911 }
3912#endif
3913 /* know operation, decode the mod byte to find the addressing
3914 mode. */
3915 amt = M.x86.R_CL;
3916 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003917 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3918 u32 destval;
Jason Jina63ce952007-07-06 08:34:56 +08003919
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003920 DECODE_PRINTF("DWORD PTR ");
3921 destoffset = decode_rmXX_address(mod, rl);
3922 DECODE_PRINTF(",CL\n");
3923 destval = fetch_data_long(destoffset);
3924 TRACE_AND_STEP();
3925 destval = (*opcD1_long_operation[rh]) (destval, amt);
3926 store_data_long(destoffset, destval);
3927 } else {
3928 u16 destval;
Jason Jina63ce952007-07-06 08:34:56 +08003929
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003930 DECODE_PRINTF("WORD PTR ");
3931 destoffset = decode_rmXX_address(mod, rl);
3932 DECODE_PRINTF(",CL\n");
3933 destval = fetch_data_word(destoffset);
3934 TRACE_AND_STEP();
3935 destval = (*opcD1_word_operation[rh]) (destval, amt);
3936 store_data_word(destoffset, destval);
3937 }
3938 } else { /* register to register */
3939 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3940 u32 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08003941
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003942 destreg = DECODE_RM_LONG_REGISTER(rl);
3943 DECODE_PRINTF(",CL\n");
3944 TRACE_AND_STEP();
3945 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3946 } else {
3947 u16 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08003948
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003949 destreg = DECODE_RM_WORD_REGISTER(rl);
3950 DECODE_PRINTF(",CL\n");
3951 TRACE_AND_STEP();
3952 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
3953 }
Jason Jina63ce952007-07-06 08:34:56 +08003954 }
3955 DECODE_CLEAR_SEGOVR();
3956 END_OF_INSTR();
3957}
3958
3959/****************************************************************************
3960REMARKS:
3961Handles opcode 0xd4
3962****************************************************************************/
3963void x86emuOp_aam(u8 X86EMU_UNUSED(op1))
3964{
3965 u8 a;
3966
3967 START_OF_INSTR();
3968 DECODE_PRINTF("AAM\n");
3969 a = fetch_byte_imm(); /* this is a stupid encoding. */
3970 if (a != 10) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003971 DECODE_PRINTF("ERROR DECODING AAM\n");
3972 TRACE_REGS();
3973 HALT_SYS();
Jason Jina63ce952007-07-06 08:34:56 +08003974 }
3975 TRACE_AND_STEP();
3976 /* note the type change here --- returning AL and AH in AX. */
3977 M.x86.R_AX = aam_word(M.x86.R_AL);
3978 DECODE_CLEAR_SEGOVR();
3979 END_OF_INSTR();
3980}
3981
3982/****************************************************************************
3983REMARKS:
3984Handles opcode 0xd5
3985****************************************************************************/
3986void x86emuOp_aad(u8 X86EMU_UNUSED(op1))
3987{
Jason Jina63ce952007-07-06 08:34:56 +08003988 START_OF_INSTR();
3989 DECODE_PRINTF("AAD\n");
Kumar Galacac607a2011-11-09 06:21:09 +00003990 (void)fetch_byte_imm();
Jason Jina63ce952007-07-06 08:34:56 +08003991 TRACE_AND_STEP();
3992 M.x86.R_AX = aad_word(M.x86.R_AX);
3993 DECODE_CLEAR_SEGOVR();
3994 END_OF_INSTR();
3995}
3996
3997/* opcode 0xd6 ILLEGAL OPCODE */
3998
3999/****************************************************************************
4000REMARKS:
4001Handles opcode 0xd7
4002****************************************************************************/
4003void x86emuOp_xlat(u8 X86EMU_UNUSED(op1))
4004{
4005 u16 addr;
4006
4007 START_OF_INSTR();
4008 DECODE_PRINTF("XLAT\n");
4009 TRACE_AND_STEP();
4010 addr = (u16)(M.x86.R_BX + (u8)M.x86.R_AL);
4011 M.x86.R_AL = fetch_data_byte(addr);
4012 DECODE_CLEAR_SEGOVR();
4013 END_OF_INSTR();
4014}
4015
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004016/* instuctions D8 .. DF are in i87_ops.c */
Jason Jina63ce952007-07-06 08:34:56 +08004017
4018/****************************************************************************
4019REMARKS:
4020Handles opcode 0xe0
4021****************************************************************************/
4022void x86emuOp_loopne(u8 X86EMU_UNUSED(op1))
4023{
4024 s16 ip;
4025
4026 START_OF_INSTR();
4027 DECODE_PRINTF("LOOPNE\t");
4028 ip = (s8) fetch_byte_imm();
4029 ip += (s16) M.x86.R_IP;
4030 DECODE_PRINTF2("%04x\n", ip);
4031 TRACE_AND_STEP();
4032 M.x86.R_CX -= 1;
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004033 if (M.x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */
4034 M.x86.R_IP = ip;
Jason Jina63ce952007-07-06 08:34:56 +08004035 DECODE_CLEAR_SEGOVR();
4036 END_OF_INSTR();
4037}
4038
4039/****************************************************************************
4040REMARKS:
4041Handles opcode 0xe1
4042****************************************************************************/
4043void x86emuOp_loope(u8 X86EMU_UNUSED(op1))
4044{
4045 s16 ip;
4046
4047 START_OF_INSTR();
4048 DECODE_PRINTF("LOOPE\t");
4049 ip = (s8) fetch_byte_imm();
4050 ip += (s16) M.x86.R_IP;
4051 DECODE_PRINTF2("%04x\n", ip);
4052 TRACE_AND_STEP();
4053 M.x86.R_CX -= 1;
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004054 if (M.x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */
4055 M.x86.R_IP = ip;
Jason Jina63ce952007-07-06 08:34:56 +08004056 DECODE_CLEAR_SEGOVR();
4057 END_OF_INSTR();
4058}
4059
4060/****************************************************************************
4061REMARKS:
4062Handles opcode 0xe2
4063****************************************************************************/
4064void x86emuOp_loop(u8 X86EMU_UNUSED(op1))
4065{
4066 s16 ip;
4067
4068 START_OF_INSTR();
4069 DECODE_PRINTF("LOOP\t");
4070 ip = (s8) fetch_byte_imm();
4071 ip += (s16) M.x86.R_IP;
4072 DECODE_PRINTF2("%04x\n", ip);
4073 TRACE_AND_STEP();
4074 M.x86.R_CX -= 1;
4075 if (M.x86.R_CX != 0)
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004076 M.x86.R_IP = ip;
Jason Jina63ce952007-07-06 08:34:56 +08004077 DECODE_CLEAR_SEGOVR();
4078 END_OF_INSTR();
4079}
4080
4081/****************************************************************************
4082REMARKS:
4083Handles opcode 0xe3
4084****************************************************************************/
4085void x86emuOp_jcxz(u8 X86EMU_UNUSED(op1))
4086{
4087 u16 target;
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004088 s8 offset;
Jason Jina63ce952007-07-06 08:34:56 +08004089
4090 /* jump to byte offset if overflow flag is set */
4091 START_OF_INSTR();
4092 DECODE_PRINTF("JCXZ\t");
4093 offset = (s8)fetch_byte_imm();
4094 target = (u16)(M.x86.R_IP + offset);
4095 DECODE_PRINTF2("%x\n", target);
4096 TRACE_AND_STEP();
4097 if (M.x86.R_CX == 0)
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004098 M.x86.R_IP = target;
Jason Jina63ce952007-07-06 08:34:56 +08004099 DECODE_CLEAR_SEGOVR();
4100 END_OF_INSTR();
4101}
4102
4103/****************************************************************************
4104REMARKS:
4105Handles opcode 0xe4
4106****************************************************************************/
4107void x86emuOp_in_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
4108{
4109 u8 port;
4110
4111 START_OF_INSTR();
4112 DECODE_PRINTF("IN\t");
4113 port = (u8) fetch_byte_imm();
4114 DECODE_PRINTF2("%x,AL\n", port);
4115 TRACE_AND_STEP();
4116 M.x86.R_AL = (*sys_inb)(port);
4117 DECODE_CLEAR_SEGOVR();
4118 END_OF_INSTR();
4119}
4120
4121/****************************************************************************
4122REMARKS:
4123Handles opcode 0xe5
4124****************************************************************************/
4125void x86emuOp_in_word_AX_IMM(u8 X86EMU_UNUSED(op1))
4126{
4127 u8 port;
4128
4129 START_OF_INSTR();
4130 DECODE_PRINTF("IN\t");
4131 port = (u8) fetch_byte_imm();
4132 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004133 DECODE_PRINTF2("EAX,%x\n", port);
Jason Jina63ce952007-07-06 08:34:56 +08004134 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004135 DECODE_PRINTF2("AX,%x\n", port);
Jason Jina63ce952007-07-06 08:34:56 +08004136 }
4137 TRACE_AND_STEP();
4138 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004139 M.x86.R_EAX = (*sys_inl)(port);
Jason Jina63ce952007-07-06 08:34:56 +08004140 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004141 M.x86.R_AX = (*sys_inw)(port);
Jason Jina63ce952007-07-06 08:34:56 +08004142 }
4143 DECODE_CLEAR_SEGOVR();
4144 END_OF_INSTR();
4145}
4146
4147/****************************************************************************
4148REMARKS:
4149Handles opcode 0xe6
4150****************************************************************************/
4151void x86emuOp_out_byte_IMM_AL(u8 X86EMU_UNUSED(op1))
4152{
4153 u8 port;
4154
4155 START_OF_INSTR();
4156 DECODE_PRINTF("OUT\t");
4157 port = (u8) fetch_byte_imm();
4158 DECODE_PRINTF2("%x,AL\n", port);
4159 TRACE_AND_STEP();
4160 (*sys_outb)(port, M.x86.R_AL);
4161 DECODE_CLEAR_SEGOVR();
4162 END_OF_INSTR();
4163}
4164
4165/****************************************************************************
4166REMARKS:
4167Handles opcode 0xe7
4168****************************************************************************/
4169void x86emuOp_out_word_IMM_AX(u8 X86EMU_UNUSED(op1))
4170{
4171 u8 port;
4172
4173 START_OF_INSTR();
4174 DECODE_PRINTF("OUT\t");
4175 port = (u8) fetch_byte_imm();
4176 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004177 DECODE_PRINTF2("%x,EAX\n", port);
Jason Jina63ce952007-07-06 08:34:56 +08004178 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004179 DECODE_PRINTF2("%x,AX\n", port);
Jason Jina63ce952007-07-06 08:34:56 +08004180 }
4181 TRACE_AND_STEP();
4182 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004183 (*sys_outl)(port, M.x86.R_EAX);
Jason Jina63ce952007-07-06 08:34:56 +08004184 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004185 (*sys_outw)(port, M.x86.R_AX);
Jason Jina63ce952007-07-06 08:34:56 +08004186 }
4187 DECODE_CLEAR_SEGOVR();
4188 END_OF_INSTR();
4189}
4190
4191/****************************************************************************
4192REMARKS:
4193Handles opcode 0xe8
4194****************************************************************************/
4195void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1))
4196{
4197 s16 ip;
4198
4199 START_OF_INSTR();
4200 DECODE_PRINTF("CALL\t");
4201 ip = (s16) fetch_word_imm();
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004202 ip += (s16) M.x86.R_IP; /* CHECK SIGN */
Jason Jina63ce952007-07-06 08:34:56 +08004203 DECODE_PRINTF2("%04x\n", ip);
4204 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, "");
4205 TRACE_AND_STEP();
4206 push_word(M.x86.R_IP);
4207 M.x86.R_IP = ip;
4208 DECODE_CLEAR_SEGOVR();
4209 END_OF_INSTR();
4210}
4211
4212/****************************************************************************
4213REMARKS:
4214Handles opcode 0xe9
4215****************************************************************************/
4216void x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1))
4217{
4218 int ip;
4219
4220 START_OF_INSTR();
4221 DECODE_PRINTF("JMP\t");
4222 ip = (s16)fetch_word_imm();
4223 ip += (s16)M.x86.R_IP;
4224 DECODE_PRINTF2("%04x\n", ip);
4225 TRACE_AND_STEP();
4226 M.x86.R_IP = (u16)ip;
4227 DECODE_CLEAR_SEGOVR();
4228 END_OF_INSTR();
4229}
4230
4231/****************************************************************************
4232REMARKS:
4233Handles opcode 0xea
4234****************************************************************************/
4235void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1))
4236{
4237 u16 cs, ip;
4238
4239 START_OF_INSTR();
4240 DECODE_PRINTF("JMP\tFAR ");
4241 ip = fetch_word_imm();
4242 cs = fetch_word_imm();
4243 DECODE_PRINTF2("%04x:", cs);
4244 DECODE_PRINTF2("%04x\n", ip);
4245 TRACE_AND_STEP();
4246 M.x86.R_IP = ip;
4247 M.x86.R_CS = cs;
4248 DECODE_CLEAR_SEGOVR();
4249 END_OF_INSTR();
4250}
4251
4252/****************************************************************************
4253REMARKS:
4254Handles opcode 0xeb
4255****************************************************************************/
4256void x86emuOp_jump_byte_IMM(u8 X86EMU_UNUSED(op1))
4257{
4258 u16 target;
4259 s8 offset;
4260
4261 START_OF_INSTR();
4262 DECODE_PRINTF("JMP\t");
4263 offset = (s8)fetch_byte_imm();
4264 target = (u16)(M.x86.R_IP + offset);
4265 DECODE_PRINTF2("%x\n", target);
4266 TRACE_AND_STEP();
4267 M.x86.R_IP = target;
4268 DECODE_CLEAR_SEGOVR();
4269 END_OF_INSTR();
4270}
4271
4272/****************************************************************************
4273REMARKS:
4274Handles opcode 0xec
4275****************************************************************************/
4276void x86emuOp_in_byte_AL_DX(u8 X86EMU_UNUSED(op1))
4277{
4278 START_OF_INSTR();
4279 DECODE_PRINTF("IN\tAL,DX\n");
4280 TRACE_AND_STEP();
4281 M.x86.R_AL = (*sys_inb)(M.x86.R_DX);
4282 DECODE_CLEAR_SEGOVR();
4283 END_OF_INSTR();
4284}
4285
4286/****************************************************************************
4287REMARKS:
4288Handles opcode 0xed
4289****************************************************************************/
4290void x86emuOp_in_word_AX_DX(u8 X86EMU_UNUSED(op1))
4291{
4292 START_OF_INSTR();
4293 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004294 DECODE_PRINTF("IN\tEAX,DX\n");
Jason Jina63ce952007-07-06 08:34:56 +08004295 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004296 DECODE_PRINTF("IN\tAX,DX\n");
Jason Jina63ce952007-07-06 08:34:56 +08004297 }
4298 TRACE_AND_STEP();
4299 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004300 M.x86.R_EAX = (*sys_inl)(M.x86.R_DX);
Jason Jina63ce952007-07-06 08:34:56 +08004301 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004302 M.x86.R_AX = (*sys_inw)(M.x86.R_DX);
Jason Jina63ce952007-07-06 08:34:56 +08004303 }
4304 DECODE_CLEAR_SEGOVR();
4305 END_OF_INSTR();
4306}
4307
4308/****************************************************************************
4309REMARKS:
4310Handles opcode 0xee
4311****************************************************************************/
4312void x86emuOp_out_byte_DX_AL(u8 X86EMU_UNUSED(op1))
4313{
4314 START_OF_INSTR();
4315 DECODE_PRINTF("OUT\tDX,AL\n");
4316 TRACE_AND_STEP();
4317 (*sys_outb)(M.x86.R_DX, M.x86.R_AL);
4318 DECODE_CLEAR_SEGOVR();
4319 END_OF_INSTR();
4320}
4321
4322/****************************************************************************
4323REMARKS:
4324Handles opcode 0xef
4325****************************************************************************/
4326void x86emuOp_out_word_DX_AX(u8 X86EMU_UNUSED(op1))
4327{
4328 START_OF_INSTR();
4329 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004330 DECODE_PRINTF("OUT\tDX,EAX\n");
Jason Jina63ce952007-07-06 08:34:56 +08004331 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004332 DECODE_PRINTF("OUT\tDX,AX\n");
Jason Jina63ce952007-07-06 08:34:56 +08004333 }
4334 TRACE_AND_STEP();
4335 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004336 (*sys_outl)(M.x86.R_DX, M.x86.R_EAX);
Jason Jina63ce952007-07-06 08:34:56 +08004337 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004338 (*sys_outw)(M.x86.R_DX, M.x86.R_AX);
Jason Jina63ce952007-07-06 08:34:56 +08004339 }
4340 DECODE_CLEAR_SEGOVR();
4341 END_OF_INSTR();
4342}
4343
4344/****************************************************************************
4345REMARKS:
4346Handles opcode 0xf0
4347****************************************************************************/
4348void x86emuOp_lock(u8 X86EMU_UNUSED(op1))
4349{
4350 START_OF_INSTR();
4351 DECODE_PRINTF("LOCK:\n");
4352 TRACE_AND_STEP();
4353 DECODE_CLEAR_SEGOVR();
4354 END_OF_INSTR();
4355}
4356
4357/*opcode 0xf1 ILLEGAL OPERATION */
4358
4359/****************************************************************************
4360REMARKS:
4361Handles opcode 0xf2
4362****************************************************************************/
4363void x86emuOp_repne(u8 X86EMU_UNUSED(op1))
4364{
4365 START_OF_INSTR();
4366 DECODE_PRINTF("REPNE\n");
4367 TRACE_AND_STEP();
4368 M.x86.mode |= SYSMODE_PREFIX_REPNE;
4369 DECODE_CLEAR_SEGOVR();
4370 END_OF_INSTR();
4371}
4372
4373/****************************************************************************
4374REMARKS:
4375Handles opcode 0xf3
4376****************************************************************************/
4377void x86emuOp_repe(u8 X86EMU_UNUSED(op1))
4378{
4379 START_OF_INSTR();
4380 DECODE_PRINTF("REPE\n");
4381 TRACE_AND_STEP();
4382 M.x86.mode |= SYSMODE_PREFIX_REPE;
4383 DECODE_CLEAR_SEGOVR();
4384 END_OF_INSTR();
4385}
4386
4387/****************************************************************************
4388REMARKS:
4389Handles opcode 0xf4
4390****************************************************************************/
4391void x86emuOp_halt(u8 X86EMU_UNUSED(op1))
4392{
4393 START_OF_INSTR();
4394 DECODE_PRINTF("HALT\n");
4395 TRACE_AND_STEP();
4396 HALT_SYS();
4397 DECODE_CLEAR_SEGOVR();
4398 END_OF_INSTR();
4399}
4400
4401/****************************************************************************
4402REMARKS:
4403Handles opcode 0xf5
4404****************************************************************************/
4405void x86emuOp_cmc(u8 X86EMU_UNUSED(op1))
4406{
4407 /* complement the carry flag. */
4408 START_OF_INSTR();
4409 DECODE_PRINTF("CMC\n");
4410 TRACE_AND_STEP();
4411 TOGGLE_FLAG(F_CF);
4412 DECODE_CLEAR_SEGOVR();
4413 END_OF_INSTR();
4414}
4415
4416/****************************************************************************
4417REMARKS:
4418Handles opcode 0xf6
4419****************************************************************************/
4420void x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1))
4421{
4422 int mod, rl, rh;
4423 u8 *destreg;
4424 uint destoffset;
4425 u8 destval, srcval;
4426
4427 /* long, drawn out code follows. Double switch for a total
4428 of 32 cases. */
4429 START_OF_INSTR();
4430 FETCH_DECODE_MODRM(mod, rh, rl);
4431 DECODE_PRINTF(opF6_names[rh]);
4432 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004433 DECODE_PRINTF("BYTE PTR ");
4434 destoffset = decode_rmXX_address(mod, rl);
4435 destval = fetch_data_byte(destoffset);
Jason Jina63ce952007-07-06 08:34:56 +08004436
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004437 switch (rh) {
4438 case 0: /* test byte imm */
4439 DECODE_PRINTF(",");
4440 srcval = fetch_byte_imm();
4441 DECODE_PRINTF2("%02x\n", srcval);
4442 TRACE_AND_STEP();
4443 test_byte(destval, srcval);
4444 break;
4445 case 1:
4446 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4447 HALT_SYS();
4448 break;
4449 case 2:
4450 DECODE_PRINTF("\n");
4451 TRACE_AND_STEP();
4452 destval = not_byte(destval);
4453 store_data_byte(destoffset, destval);
4454 break;
4455 case 3:
4456 DECODE_PRINTF("\n");
4457 TRACE_AND_STEP();
4458 destval = neg_byte(destval);
4459 store_data_byte(destoffset, destval);
4460 break;
4461 case 4:
4462 DECODE_PRINTF("\n");
4463 TRACE_AND_STEP();
4464 mul_byte(destval);
4465 break;
4466 case 5:
4467 DECODE_PRINTF("\n");
4468 TRACE_AND_STEP();
4469 imul_byte(destval);
4470 break;
4471 case 6:
4472 DECODE_PRINTF("\n");
4473 TRACE_AND_STEP();
4474 div_byte(destval);
4475 break;
4476 default:
4477 DECODE_PRINTF("\n");
4478 TRACE_AND_STEP();
4479 idiv_byte(destval);
4480 break;
4481 }
4482 } else { /* mod=11 */
4483 destreg = DECODE_RM_BYTE_REGISTER(rl);
4484 switch (rh) {
4485 case 0: /* test byte imm */
4486 DECODE_PRINTF(",");
4487 srcval = fetch_byte_imm();
4488 DECODE_PRINTF2("%02x\n", srcval);
4489 TRACE_AND_STEP();
4490 test_byte(*destreg, srcval);
4491 break;
4492 case 1:
4493 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4494 HALT_SYS();
4495 break;
4496 case 2:
4497 DECODE_PRINTF("\n");
4498 TRACE_AND_STEP();
4499 *destreg = not_byte(*destreg);
4500 break;
4501 case 3:
4502 DECODE_PRINTF("\n");
4503 TRACE_AND_STEP();
4504 *destreg = neg_byte(*destreg);
4505 break;
4506 case 4:
4507 DECODE_PRINTF("\n");
4508 TRACE_AND_STEP();
4509 mul_byte(*destreg); /*!!! */
4510 break;
4511 case 5:
4512 DECODE_PRINTF("\n");
4513 TRACE_AND_STEP();
4514 imul_byte(*destreg);
4515 break;
4516 case 6:
4517 DECODE_PRINTF("\n");
4518 TRACE_AND_STEP();
4519 div_byte(*destreg);
4520 break;
4521 default:
4522 DECODE_PRINTF("\n");
4523 TRACE_AND_STEP();
4524 idiv_byte(*destreg);
4525 break;
4526 }
Jason Jina63ce952007-07-06 08:34:56 +08004527 }
4528 DECODE_CLEAR_SEGOVR();
4529 END_OF_INSTR();
4530}
4531
4532/****************************************************************************
4533REMARKS:
4534Handles opcode 0xf7
4535****************************************************************************/
4536void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1))
4537{
4538 int mod, rl, rh;
4539 uint destoffset;
4540
4541 START_OF_INSTR();
4542 FETCH_DECODE_MODRM(mod, rh, rl);
4543 DECODE_PRINTF(opF6_names[rh]);
4544 if (mod < 3) {
4545
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004546 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4547 u32 destval, srcval;
Jason Jina63ce952007-07-06 08:34:56 +08004548
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004549 DECODE_PRINTF("DWORD PTR ");
4550 destoffset = decode_rmXX_address(mod, rl);
4551 destval = fetch_data_long(destoffset);
Jason Jina63ce952007-07-06 08:34:56 +08004552
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004553 switch (rh) {
4554 case 0:
4555 DECODE_PRINTF(",");
4556 srcval = fetch_long_imm();
4557 DECODE_PRINTF2("%x\n", srcval);
4558 TRACE_AND_STEP();
4559 test_long(destval, srcval);
4560 break;
4561 case 1:
4562 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4563 HALT_SYS();
4564 break;
4565 case 2:
4566 DECODE_PRINTF("\n");
4567 TRACE_AND_STEP();
4568 destval = not_long(destval);
4569 store_data_long(destoffset, destval);
4570 break;
4571 case 3:
4572 DECODE_PRINTF("\n");
4573 TRACE_AND_STEP();
4574 destval = neg_long(destval);
4575 store_data_long(destoffset, destval);
4576 break;
4577 case 4:
4578 DECODE_PRINTF("\n");
4579 TRACE_AND_STEP();
4580 mul_long(destval);
4581 break;
4582 case 5:
4583 DECODE_PRINTF("\n");
4584 TRACE_AND_STEP();
4585 imul_long(destval);
4586 break;
4587 case 6:
4588 DECODE_PRINTF("\n");
4589 TRACE_AND_STEP();
4590 div_long(destval);
4591 break;
4592 case 7:
4593 DECODE_PRINTF("\n");
4594 TRACE_AND_STEP();
4595 idiv_long(destval);
4596 break;
4597 }
4598 } else {
4599 u16 destval, srcval;
Jason Jina63ce952007-07-06 08:34:56 +08004600
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004601 DECODE_PRINTF("WORD PTR ");
4602 destoffset = decode_rmXX_address(mod, rl);
4603 destval = fetch_data_word(destoffset);
Jason Jina63ce952007-07-06 08:34:56 +08004604
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004605 switch (rh) {
4606 case 0: /* test word imm */
4607 DECODE_PRINTF(",");
4608 srcval = fetch_word_imm();
4609 DECODE_PRINTF2("%x\n", srcval);
4610 TRACE_AND_STEP();
4611 test_word(destval, srcval);
4612 break;
4613 case 1:
4614 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4615 HALT_SYS();
4616 break;
4617 case 2:
4618 DECODE_PRINTF("\n");
4619 TRACE_AND_STEP();
4620 destval = not_word(destval);
4621 store_data_word(destoffset, destval);
4622 break;
4623 case 3:
4624 DECODE_PRINTF("\n");
4625 TRACE_AND_STEP();
4626 destval = neg_word(destval);
4627 store_data_word(destoffset, destval);
4628 break;
4629 case 4:
4630 DECODE_PRINTF("\n");
4631 TRACE_AND_STEP();
4632 mul_word(destval);
4633 break;
4634 case 5:
4635 DECODE_PRINTF("\n");
4636 TRACE_AND_STEP();
4637 imul_word(destval);
4638 break;
4639 case 6:
4640 DECODE_PRINTF("\n");
4641 TRACE_AND_STEP();
4642 div_word(destval);
4643 break;
4644 case 7:
4645 DECODE_PRINTF("\n");
4646 TRACE_AND_STEP();
4647 idiv_word(destval);
4648 break;
4649 }
4650 }
Jason Jina63ce952007-07-06 08:34:56 +08004651
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004652 } else { /* mod=11 */
Jason Jina63ce952007-07-06 08:34:56 +08004653
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004654 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4655 u32 *destreg;
4656 u32 srcval;
Jason Jina63ce952007-07-06 08:34:56 +08004657
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004658 destreg = DECODE_RM_LONG_REGISTER(rl);
Jason Jina63ce952007-07-06 08:34:56 +08004659
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004660 switch (rh) {
4661 case 0: /* test word imm */
4662 DECODE_PRINTF(",");
4663 srcval = fetch_long_imm();
4664 DECODE_PRINTF2("%x\n", srcval);
4665 TRACE_AND_STEP();
4666 test_long(*destreg, srcval);
4667 break;
4668 case 1:
4669 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4670 HALT_SYS();
4671 break;
4672 case 2:
4673 DECODE_PRINTF("\n");
4674 TRACE_AND_STEP();
4675 *destreg = not_long(*destreg);
4676 break;
4677 case 3:
4678 DECODE_PRINTF("\n");
4679 TRACE_AND_STEP();
4680 *destreg = neg_long(*destreg);
4681 break;
4682 case 4:
4683 DECODE_PRINTF("\n");
4684 TRACE_AND_STEP();
4685 mul_long(*destreg); /*!!! */
4686 break;
4687 case 5:
4688 DECODE_PRINTF("\n");
4689 TRACE_AND_STEP();
4690 imul_long(*destreg);
4691 break;
4692 case 6:
4693 DECODE_PRINTF("\n");
4694 TRACE_AND_STEP();
4695 div_long(*destreg);
4696 break;
4697 case 7:
4698 DECODE_PRINTF("\n");
4699 TRACE_AND_STEP();
4700 idiv_long(*destreg);
4701 break;
4702 }
4703 } else {
4704 u16 *destreg;
4705 u16 srcval;
Jason Jina63ce952007-07-06 08:34:56 +08004706
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004707 destreg = DECODE_RM_WORD_REGISTER(rl);
Jason Jina63ce952007-07-06 08:34:56 +08004708
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004709 switch (rh) {
4710 case 0: /* test word imm */
4711 DECODE_PRINTF(",");
4712 srcval = fetch_word_imm();
4713 DECODE_PRINTF2("%x\n", srcval);
4714 TRACE_AND_STEP();
4715 test_word(*destreg, srcval);
4716 break;
4717 case 1:
4718 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4719 HALT_SYS();
4720 break;
4721 case 2:
4722 DECODE_PRINTF("\n");
4723 TRACE_AND_STEP();
4724 *destreg = not_word(*destreg);
4725 break;
4726 case 3:
4727 DECODE_PRINTF("\n");
4728 TRACE_AND_STEP();
4729 *destreg = neg_word(*destreg);
4730 break;
4731 case 4:
4732 DECODE_PRINTF("\n");
4733 TRACE_AND_STEP();
4734 mul_word(*destreg); /*!!! */
4735 break;
4736 case 5:
4737 DECODE_PRINTF("\n");
4738 TRACE_AND_STEP();
4739 imul_word(*destreg);
4740 break;
4741 case 6:
4742 DECODE_PRINTF("\n");
4743 TRACE_AND_STEP();
4744 div_word(*destreg);
4745 break;
4746 case 7:
4747 DECODE_PRINTF("\n");
4748 TRACE_AND_STEP();
4749 idiv_word(*destreg);
4750 break;
4751 }
4752 }
Jason Jina63ce952007-07-06 08:34:56 +08004753 }
4754 DECODE_CLEAR_SEGOVR();
4755 END_OF_INSTR();
4756}
4757
4758/****************************************************************************
4759REMARKS:
4760Handles opcode 0xf8
4761****************************************************************************/
4762void x86emuOp_clc(u8 X86EMU_UNUSED(op1))
4763{
4764 /* clear the carry flag. */
4765 START_OF_INSTR();
4766 DECODE_PRINTF("CLC\n");
4767 TRACE_AND_STEP();
4768 CLEAR_FLAG(F_CF);
4769 DECODE_CLEAR_SEGOVR();
4770 END_OF_INSTR();
4771}
4772
4773/****************************************************************************
4774REMARKS:
4775Handles opcode 0xf9
4776****************************************************************************/
4777void x86emuOp_stc(u8 X86EMU_UNUSED(op1))
4778{
4779 /* set the carry flag. */
4780 START_OF_INSTR();
4781 DECODE_PRINTF("STC\n");
4782 TRACE_AND_STEP();
4783 SET_FLAG(F_CF);
4784 DECODE_CLEAR_SEGOVR();
4785 END_OF_INSTR();
4786}
4787
4788/****************************************************************************
4789REMARKS:
4790Handles opcode 0xfa
4791****************************************************************************/
4792void x86emuOp_cli(u8 X86EMU_UNUSED(op1))
4793{
4794 /* clear interrupts. */
4795 START_OF_INSTR();
4796 DECODE_PRINTF("CLI\n");
4797 TRACE_AND_STEP();
4798 CLEAR_FLAG(F_IF);
4799 DECODE_CLEAR_SEGOVR();
4800 END_OF_INSTR();
4801}
4802
4803/****************************************************************************
4804REMARKS:
4805Handles opcode 0xfb
4806****************************************************************************/
4807void x86emuOp_sti(u8 X86EMU_UNUSED(op1))
4808{
4809 /* enable interrupts. */
4810 START_OF_INSTR();
4811 DECODE_PRINTF("STI\n");
4812 TRACE_AND_STEP();
4813 SET_FLAG(F_IF);
4814 DECODE_CLEAR_SEGOVR();
4815 END_OF_INSTR();
4816}
4817
4818/****************************************************************************
4819REMARKS:
4820Handles opcode 0xfc
4821****************************************************************************/
4822void x86emuOp_cld(u8 X86EMU_UNUSED(op1))
4823{
4824 /* clear interrupts. */
4825 START_OF_INSTR();
4826 DECODE_PRINTF("CLD\n");
4827 TRACE_AND_STEP();
4828 CLEAR_FLAG(F_DF);
4829 DECODE_CLEAR_SEGOVR();
4830 END_OF_INSTR();
4831}
4832
4833/****************************************************************************
4834REMARKS:
4835Handles opcode 0xfd
4836****************************************************************************/
4837void x86emuOp_std(u8 X86EMU_UNUSED(op1))
4838{
4839 /* clear interrupts. */
4840 START_OF_INSTR();
4841 DECODE_PRINTF("STD\n");
4842 TRACE_AND_STEP();
4843 SET_FLAG(F_DF);
4844 DECODE_CLEAR_SEGOVR();
4845 END_OF_INSTR();
4846}
4847
4848/****************************************************************************
4849REMARKS:
4850Handles opcode 0xfe
4851****************************************************************************/
4852void x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1))
4853{
4854 int mod, rh, rl;
4855 u8 destval;
4856 uint destoffset;
4857 u8 *destreg;
4858
4859 /* Yet another special case instruction. */
4860 START_OF_INSTR();
4861 FETCH_DECODE_MODRM(mod, rh, rl);
4862#ifdef DEBUG
4863 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004864 /* XXX DECODE_PRINTF may be changed to something more
4865 general, so that it is important to leave the strings
4866 in the same format, even though the result is that the
4867 above test is done twice. */
Jason Jina63ce952007-07-06 08:34:56 +08004868
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004869 switch (rh) {
4870 case 0:
4871 DECODE_PRINTF("INC\t");
4872 break;
4873 case 1:
4874 DECODE_PRINTF("DEC\t");
4875 break;
4876 case 2:
4877 case 3:
4878 case 4:
4879 case 5:
4880 case 6:
4881 case 7:
4882 DECODE_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x \n", mod);
4883 HALT_SYS();
4884 break;
4885 }
Jason Jina63ce952007-07-06 08:34:56 +08004886 }
4887#endif
4888 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004889 DECODE_PRINTF("BYTE PTR ");
4890 destoffset = decode_rmXX_address(mod, rl);
4891 DECODE_PRINTF("\n");
4892 destval = fetch_data_byte(destoffset);
4893 TRACE_AND_STEP();
4894 if (rh == 0)
4895 destval = inc_byte(destval);
4896 else
4897 destval = dec_byte(destval);
4898 store_data_byte(destoffset, destval);
Jason Jina63ce952007-07-06 08:34:56 +08004899 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004900 destreg = DECODE_RM_BYTE_REGISTER(rl);
4901 DECODE_PRINTF("\n");
4902 TRACE_AND_STEP();
4903 if (rh == 0)
4904 *destreg = inc_byte(*destreg);
4905 else
4906 *destreg = dec_byte(*destreg);
Jason Jina63ce952007-07-06 08:34:56 +08004907 }
4908 DECODE_CLEAR_SEGOVR();
4909 END_OF_INSTR();
4910}
4911
4912/****************************************************************************
4913REMARKS:
4914Handles opcode 0xff
4915****************************************************************************/
4916void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1))
4917{
4918 int mod, rh, rl;
4919 uint destoffset = 0;
4920 u16 *destreg;
4921 u16 destval,destval2;
4922
4923 /* Yet another special case instruction. */
4924 START_OF_INSTR();
4925 FETCH_DECODE_MODRM(mod, rh, rl);
4926#ifdef DEBUG
4927 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004928 /* XXX DECODE_PRINTF may be changed to something more
4929 general, so that it is important to leave the strings
4930 in the same format, even though the result is that the
4931 above test is done twice. */
Jason Jina63ce952007-07-06 08:34:56 +08004932
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004933 switch (rh) {
4934 case 0:
4935 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4936 DECODE_PRINTF("INC\tDWORD PTR ");
4937 } else {
4938 DECODE_PRINTF("INC\tWORD PTR ");
4939 }
4940 break;
4941 case 1:
4942 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4943 DECODE_PRINTF("DEC\tDWORD PTR ");
4944 } else {
4945 DECODE_PRINTF("DEC\tWORD PTR ");
4946 }
4947 break;
4948 case 2:
4949 DECODE_PRINTF("CALL\t ");
4950 break;
4951 case 3:
4952 DECODE_PRINTF("CALL\tFAR ");
4953 break;
4954 case 4:
4955 DECODE_PRINTF("JMP\t");
4956 break;
4957 case 5:
4958 DECODE_PRINTF("JMP\tFAR ");
4959 break;
4960 case 6:
4961 DECODE_PRINTF("PUSH\t");
4962 break;
4963 case 7:
4964 DECODE_PRINTF("ILLEGAL DECODING OF OPCODE FF\t");
4965 HALT_SYS();
4966 break;
4967 }
Jason Jina63ce952007-07-06 08:34:56 +08004968 }
4969#endif
4970 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004971 destoffset = decode_rmXX_address(mod, rl);
4972 DECODE_PRINTF("\n");
4973 switch (rh) {
4974 case 0: /* inc word ptr ... */
4975 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4976 u32 destval;
Jason Jina63ce952007-07-06 08:34:56 +08004977
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004978 destval = fetch_data_long(destoffset);
4979 TRACE_AND_STEP();
4980 destval = inc_long(destval);
4981 store_data_long(destoffset, destval);
4982 } else {
4983 u16 destval;
Jason Jina63ce952007-07-06 08:34:56 +08004984
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004985 destval = fetch_data_word(destoffset);
4986 TRACE_AND_STEP();
4987 destval = inc_word(destval);
4988 store_data_word(destoffset, destval);
4989 }
4990 break;
4991 case 1: /* dec word ptr ... */
4992 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4993 u32 destval;
Jason Jina63ce952007-07-06 08:34:56 +08004994
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004995 destval = fetch_data_long(destoffset);
4996 TRACE_AND_STEP();
4997 destval = dec_long(destval);
4998 store_data_long(destoffset, destval);
4999 } else {
5000 u16 destval;
Jason Jina63ce952007-07-06 08:34:56 +08005001
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005002 destval = fetch_data_word(destoffset);
5003 TRACE_AND_STEP();
5004 destval = dec_word(destval);
5005 store_data_word(destoffset, destval);
5006 }
5007 break;
5008 case 2: /* call word ptr ... */
5009 destval = fetch_data_word(destoffset);
5010 TRACE_AND_STEP();
5011 push_word(M.x86.R_IP);
5012 M.x86.R_IP = destval;
5013 break;
5014 case 3: /* call far ptr ... */
5015 destval = fetch_data_word(destoffset);
5016 destval2 = fetch_data_word(destoffset + 2);
5017 TRACE_AND_STEP();
5018 push_word(M.x86.R_CS);
5019 M.x86.R_CS = destval2;
5020 push_word(M.x86.R_IP);
5021 M.x86.R_IP = destval;
5022 break;
5023 case 4: /* jmp word ptr ... */
5024 destval = fetch_data_word(destoffset);
5025 TRACE_AND_STEP();
5026 M.x86.R_IP = destval;
5027 break;
5028 case 5: /* jmp far ptr ... */
5029 destval = fetch_data_word(destoffset);
5030 destval2 = fetch_data_word(destoffset + 2);
5031 TRACE_AND_STEP();
5032 M.x86.R_IP = destval;
5033 M.x86.R_CS = destval2;
5034 break;
5035 case 6: /* push word ptr ... */
5036 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5037 u32 destval;
Jason Jina63ce952007-07-06 08:34:56 +08005038
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005039 destval = fetch_data_long(destoffset);
5040 TRACE_AND_STEP();
5041 push_long(destval);
5042 } else {
5043 u16 destval;
Jason Jina63ce952007-07-06 08:34:56 +08005044
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005045 destval = fetch_data_word(destoffset);
5046 TRACE_AND_STEP();
5047 push_word(destval);
5048 }
5049 break;
5050 }
Jason Jina63ce952007-07-06 08:34:56 +08005051 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005052 switch (rh) {
5053 case 0:
5054 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5055 u32 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08005056
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005057 destreg = DECODE_RM_LONG_REGISTER(rl);
5058 DECODE_PRINTF("\n");
5059 TRACE_AND_STEP();
5060 *destreg = inc_long(*destreg);
5061 } else {
5062 u16 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08005063
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005064 destreg = DECODE_RM_WORD_REGISTER(rl);
5065 DECODE_PRINTF("\n");
5066 TRACE_AND_STEP();
5067 *destreg = inc_word(*destreg);
5068 }
5069 break;
5070 case 1:
5071 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5072 u32 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08005073
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005074 destreg = DECODE_RM_LONG_REGISTER(rl);
5075 DECODE_PRINTF("\n");
5076 TRACE_AND_STEP();
5077 *destreg = dec_long(*destreg);
5078 } else {
5079 u16 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08005080
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005081 destreg = DECODE_RM_WORD_REGISTER(rl);
5082 DECODE_PRINTF("\n");
5083 TRACE_AND_STEP();
5084 *destreg = dec_word(*destreg);
5085 }
5086 break;
5087 case 2: /* call word ptr ... */
5088 destreg = DECODE_RM_WORD_REGISTER(rl);
5089 DECODE_PRINTF("\n");
5090 TRACE_AND_STEP();
5091 push_word(M.x86.R_IP);
5092 M.x86.R_IP = *destreg;
5093 break;
5094 case 3: /* jmp far ptr ... */
5095 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5096 TRACE_AND_STEP();
5097 HALT_SYS();
5098 break;
Jason Jina63ce952007-07-06 08:34:56 +08005099
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005100 case 4: /* jmp ... */
5101 destreg = DECODE_RM_WORD_REGISTER(rl);
5102 DECODE_PRINTF("\n");
5103 TRACE_AND_STEP();
5104 M.x86.R_IP = (u16) (*destreg);
5105 break;
5106 case 5: /* jmp far ptr ... */
5107 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5108 TRACE_AND_STEP();
5109 HALT_SYS();
5110 break;
5111 case 6:
5112 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5113 u32 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08005114
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005115 destreg = DECODE_RM_LONG_REGISTER(rl);
5116 DECODE_PRINTF("\n");
5117 TRACE_AND_STEP();
5118 push_long(*destreg);
5119 } else {
5120 u16 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08005121
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005122 destreg = DECODE_RM_WORD_REGISTER(rl);
5123 DECODE_PRINTF("\n");
5124 TRACE_AND_STEP();
5125 push_word(*destreg);
5126 }
5127 break;
5128 }
Jason Jina63ce952007-07-06 08:34:56 +08005129 }
5130 DECODE_CLEAR_SEGOVR();
5131 END_OF_INSTR();
5132}
5133
5134/***************************************************************************
5135 * Single byte operation code table:
5136 **************************************************************************/
Ed Swarthout1cffcde2008-10-09 01:27:18 -05005137void (*x86emu_optab[256])(u8) =
Jason Jina63ce952007-07-06 08:34:56 +08005138{
5139/* 0x00 */ x86emuOp_genop_byte_RM_R,
5140/* 0x01 */ x86emuOp_genop_word_RM_R,
5141/* 0x02 */ x86emuOp_genop_byte_R_RM,
5142/* 0x03 */ x86emuOp_genop_word_R_RM,
5143/* 0x04 */ x86emuOp_genop_byte_AL_IMM,
5144/* 0x05 */ x86emuOp_genop_word_AX_IMM,
5145/* 0x06 */ x86emuOp_push_ES,
5146/* 0x07 */ x86emuOp_pop_ES,
5147
5148/* 0x08 */ x86emuOp_genop_byte_RM_R,
5149/* 0x09 */ x86emuOp_genop_word_RM_R,
5150/* 0x0a */ x86emuOp_genop_byte_R_RM,
5151/* 0x0b */ x86emuOp_genop_word_R_RM,
5152/* 0x0c */ x86emuOp_genop_byte_AL_IMM,
5153/* 0x0d */ x86emuOp_genop_word_AX_IMM,
5154/* 0x0e */ x86emuOp_push_CS,
5155/* 0x0f */ x86emuOp_two_byte,
5156
5157/* 0x10 */ x86emuOp_genop_byte_RM_R,
5158/* 0x11 */ x86emuOp_genop_word_RM_R,
5159/* 0x12 */ x86emuOp_genop_byte_R_RM,
5160/* 0x13 */ x86emuOp_genop_word_R_RM,
5161/* 0x14 */ x86emuOp_genop_byte_AL_IMM,
5162/* 0x15 */ x86emuOp_genop_word_AX_IMM,
5163/* 0x16 */ x86emuOp_push_SS,
5164/* 0x17 */ x86emuOp_pop_SS,
5165
5166/* 0x18 */ x86emuOp_genop_byte_RM_R,
5167/* 0x19 */ x86emuOp_genop_word_RM_R,
5168/* 0x1a */ x86emuOp_genop_byte_R_RM,
5169/* 0x1b */ x86emuOp_genop_word_R_RM,
5170/* 0x1c */ x86emuOp_genop_byte_AL_IMM,
5171/* 0x1d */ x86emuOp_genop_word_AX_IMM,
5172/* 0x1e */ x86emuOp_push_DS,
5173/* 0x1f */ x86emuOp_pop_DS,
5174
5175/* 0x20 */ x86emuOp_genop_byte_RM_R,
5176/* 0x21 */ x86emuOp_genop_word_RM_R,
5177/* 0x22 */ x86emuOp_genop_byte_R_RM,
5178/* 0x23 */ x86emuOp_genop_word_R_RM,
5179/* 0x24 */ x86emuOp_genop_byte_AL_IMM,
5180/* 0x25 */ x86emuOp_genop_word_AX_IMM,
5181/* 0x26 */ x86emuOp_segovr_ES,
5182/* 0x27 */ x86emuOp_daa,
5183
5184/* 0x28 */ x86emuOp_genop_byte_RM_R,
5185/* 0x29 */ x86emuOp_genop_word_RM_R,
5186/* 0x2a */ x86emuOp_genop_byte_R_RM,
5187/* 0x2b */ x86emuOp_genop_word_R_RM,
5188/* 0x2c */ x86emuOp_genop_byte_AL_IMM,
5189/* 0x2d */ x86emuOp_genop_word_AX_IMM,
5190/* 0x2e */ x86emuOp_segovr_CS,
5191/* 0x2f */ x86emuOp_das,
5192
5193/* 0x30 */ x86emuOp_genop_byte_RM_R,
5194/* 0x31 */ x86emuOp_genop_word_RM_R,
5195/* 0x32 */ x86emuOp_genop_byte_R_RM,
5196/* 0x33 */ x86emuOp_genop_word_R_RM,
5197/* 0x34 */ x86emuOp_genop_byte_AL_IMM,
5198/* 0x35 */ x86emuOp_genop_word_AX_IMM,
5199/* 0x36 */ x86emuOp_segovr_SS,
5200/* 0x37 */ x86emuOp_aaa,
5201
5202/* 0x38 */ x86emuOp_genop_byte_RM_R,
5203/* 0x39 */ x86emuOp_genop_word_RM_R,
5204/* 0x3a */ x86emuOp_genop_byte_R_RM,
5205/* 0x3b */ x86emuOp_genop_word_R_RM,
5206/* 0x3c */ x86emuOp_genop_byte_AL_IMM,
5207/* 0x3d */ x86emuOp_genop_word_AX_IMM,
5208/* 0x3e */ x86emuOp_segovr_DS,
5209/* 0x3f */ x86emuOp_aas,
5210
5211/* 0x40 */ x86emuOp_inc_register,
5212/* 0x41 */ x86emuOp_inc_register,
5213/* 0x42 */ x86emuOp_inc_register,
5214/* 0x43 */ x86emuOp_inc_register,
5215/* 0x44 */ x86emuOp_inc_register,
5216/* 0x45 */ x86emuOp_inc_register,
5217/* 0x46 */ x86emuOp_inc_register,
5218/* 0x47 */ x86emuOp_inc_register,
5219
5220/* 0x48 */ x86emuOp_dec_register,
5221/* 0x49 */ x86emuOp_dec_register,
5222/* 0x4a */ x86emuOp_dec_register,
5223/* 0x4b */ x86emuOp_dec_register,
5224/* 0x4c */ x86emuOp_dec_register,
5225/* 0x4d */ x86emuOp_dec_register,
5226/* 0x4e */ x86emuOp_dec_register,
5227/* 0x4f */ x86emuOp_dec_register,
5228
5229/* 0x50 */ x86emuOp_push_register,
5230/* 0x51 */ x86emuOp_push_register,
5231/* 0x52 */ x86emuOp_push_register,
5232/* 0x53 */ x86emuOp_push_register,
5233/* 0x54 */ x86emuOp_push_register,
5234/* 0x55 */ x86emuOp_push_register,
5235/* 0x56 */ x86emuOp_push_register,
5236/* 0x57 */ x86emuOp_push_register,
5237
5238/* 0x58 */ x86emuOp_pop_register,
5239/* 0x59 */ x86emuOp_pop_register,
5240/* 0x5a */ x86emuOp_pop_register,
5241/* 0x5b */ x86emuOp_pop_register,
5242/* 0x5c */ x86emuOp_pop_register,
5243/* 0x5d */ x86emuOp_pop_register,
5244/* 0x5e */ x86emuOp_pop_register,
5245/* 0x5f */ x86emuOp_pop_register,
5246
5247/* 0x60 */ x86emuOp_push_all,
5248/* 0x61 */ x86emuOp_pop_all,
5249/* 0x62 */ x86emuOp_illegal_op, /* bound */
5250/* 0x63 */ x86emuOp_illegal_op, /* arpl */
5251/* 0x64 */ x86emuOp_segovr_FS,
5252/* 0x65 */ x86emuOp_segovr_GS,
5253/* 0x66 */ x86emuOp_prefix_data,
5254/* 0x67 */ x86emuOp_prefix_addr,
5255
5256/* 0x68 */ x86emuOp_push_word_IMM,
5257/* 0x69 */ x86emuOp_imul_word_IMM,
5258/* 0x6a */ x86emuOp_push_byte_IMM,
5259/* 0x6b */ x86emuOp_imul_byte_IMM,
5260/* 0x6c */ x86emuOp_ins_byte,
5261/* 0x6d */ x86emuOp_ins_word,
5262/* 0x6e */ x86emuOp_outs_byte,
5263/* 0x6f */ x86emuOp_outs_word,
5264
5265/* 0x70 */ x86emuOp_jump_near_cond,
5266/* 0x71 */ x86emuOp_jump_near_cond,
5267/* 0x72 */ x86emuOp_jump_near_cond,
5268/* 0x73 */ x86emuOp_jump_near_cond,
5269/* 0x74 */ x86emuOp_jump_near_cond,
5270/* 0x75 */ x86emuOp_jump_near_cond,
5271/* 0x76 */ x86emuOp_jump_near_cond,
5272/* 0x77 */ x86emuOp_jump_near_cond,
5273
5274/* 0x78 */ x86emuOp_jump_near_cond,
5275/* 0x79 */ x86emuOp_jump_near_cond,
5276/* 0x7a */ x86emuOp_jump_near_cond,
5277/* 0x7b */ x86emuOp_jump_near_cond,
5278/* 0x7c */ x86emuOp_jump_near_cond,
5279/* 0x7d */ x86emuOp_jump_near_cond,
5280/* 0x7e */ x86emuOp_jump_near_cond,
5281/* 0x7f */ x86emuOp_jump_near_cond,
5282
5283/* 0x80 */ x86emuOp_opc80_byte_RM_IMM,
5284/* 0x81 */ x86emuOp_opc81_word_RM_IMM,
5285/* 0x82 */ x86emuOp_opc82_byte_RM_IMM,
5286/* 0x83 */ x86emuOp_opc83_word_RM_IMM,
5287/* 0x84 */ x86emuOp_test_byte_RM_R,
5288/* 0x85 */ x86emuOp_test_word_RM_R,
5289/* 0x86 */ x86emuOp_xchg_byte_RM_R,
5290/* 0x87 */ x86emuOp_xchg_word_RM_R,
5291
5292/* 0x88 */ x86emuOp_mov_byte_RM_R,
5293/* 0x89 */ x86emuOp_mov_word_RM_R,
5294/* 0x8a */ x86emuOp_mov_byte_R_RM,
5295/* 0x8b */ x86emuOp_mov_word_R_RM,
5296/* 0x8c */ x86emuOp_mov_word_RM_SR,
5297/* 0x8d */ x86emuOp_lea_word_R_M,
5298/* 0x8e */ x86emuOp_mov_word_SR_RM,
5299/* 0x8f */ x86emuOp_pop_RM,
5300
5301/* 0x90 */ x86emuOp_nop,
5302/* 0x91 */ x86emuOp_xchg_word_AX_register,
5303/* 0x92 */ x86emuOp_xchg_word_AX_register,
5304/* 0x93 */ x86emuOp_xchg_word_AX_register,
5305/* 0x94 */ x86emuOp_xchg_word_AX_register,
5306/* 0x95 */ x86emuOp_xchg_word_AX_register,
5307/* 0x96 */ x86emuOp_xchg_word_AX_register,
5308/* 0x97 */ x86emuOp_xchg_word_AX_register,
5309
5310/* 0x98 */ x86emuOp_cbw,
5311/* 0x99 */ x86emuOp_cwd,
5312/* 0x9a */ x86emuOp_call_far_IMM,
5313/* 0x9b */ x86emuOp_wait,
5314/* 0x9c */ x86emuOp_pushf_word,
5315/* 0x9d */ x86emuOp_popf_word,
5316/* 0x9e */ x86emuOp_sahf,
5317/* 0x9f */ x86emuOp_lahf,
5318
5319/* 0xa0 */ x86emuOp_mov_AL_M_IMM,
5320/* 0xa1 */ x86emuOp_mov_AX_M_IMM,
5321/* 0xa2 */ x86emuOp_mov_M_AL_IMM,
5322/* 0xa3 */ x86emuOp_mov_M_AX_IMM,
5323/* 0xa4 */ x86emuOp_movs_byte,
5324/* 0xa5 */ x86emuOp_movs_word,
5325/* 0xa6 */ x86emuOp_cmps_byte,
5326/* 0xa7 */ x86emuOp_cmps_word,
5327/* 0xa8 */ x86emuOp_test_AL_IMM,
5328/* 0xa9 */ x86emuOp_test_AX_IMM,
5329/* 0xaa */ x86emuOp_stos_byte,
5330/* 0xab */ x86emuOp_stos_word,
5331/* 0xac */ x86emuOp_lods_byte,
5332/* 0xad */ x86emuOp_lods_word,
5333/* 0xac */ x86emuOp_scas_byte,
5334/* 0xad */ x86emuOp_scas_word,
5335
5336/* 0xb0 */ x86emuOp_mov_byte_register_IMM,
5337/* 0xb1 */ x86emuOp_mov_byte_register_IMM,
5338/* 0xb2 */ x86emuOp_mov_byte_register_IMM,
5339/* 0xb3 */ x86emuOp_mov_byte_register_IMM,
5340/* 0xb4 */ x86emuOp_mov_byte_register_IMM,
5341/* 0xb5 */ x86emuOp_mov_byte_register_IMM,
5342/* 0xb6 */ x86emuOp_mov_byte_register_IMM,
5343/* 0xb7 */ x86emuOp_mov_byte_register_IMM,
5344
5345/* 0xb8 */ x86emuOp_mov_word_register_IMM,
5346/* 0xb9 */ x86emuOp_mov_word_register_IMM,
5347/* 0xba */ x86emuOp_mov_word_register_IMM,
5348/* 0xbb */ x86emuOp_mov_word_register_IMM,
5349/* 0xbc */ x86emuOp_mov_word_register_IMM,
5350/* 0xbd */ x86emuOp_mov_word_register_IMM,
5351/* 0xbe */ x86emuOp_mov_word_register_IMM,
5352/* 0xbf */ x86emuOp_mov_word_register_IMM,
5353
5354/* 0xc0 */ x86emuOp_opcC0_byte_RM_MEM,
5355/* 0xc1 */ x86emuOp_opcC1_word_RM_MEM,
5356/* 0xc2 */ x86emuOp_ret_near_IMM,
5357/* 0xc3 */ x86emuOp_ret_near,
5358/* 0xc4 */ x86emuOp_les_R_IMM,
5359/* 0xc5 */ x86emuOp_lds_R_IMM,
5360/* 0xc6 */ x86emuOp_mov_byte_RM_IMM,
5361/* 0xc7 */ x86emuOp_mov_word_RM_IMM,
5362/* 0xc8 */ x86emuOp_enter,
5363/* 0xc9 */ x86emuOp_leave,
5364/* 0xca */ x86emuOp_ret_far_IMM,
5365/* 0xcb */ x86emuOp_ret_far,
5366/* 0xcc */ x86emuOp_int3,
5367/* 0xcd */ x86emuOp_int_IMM,
5368/* 0xce */ x86emuOp_into,
5369/* 0xcf */ x86emuOp_iret,
5370
5371/* 0xd0 */ x86emuOp_opcD0_byte_RM_1,
5372/* 0xd1 */ x86emuOp_opcD1_word_RM_1,
5373/* 0xd2 */ x86emuOp_opcD2_byte_RM_CL,
5374/* 0xd3 */ x86emuOp_opcD3_word_RM_CL,
5375/* 0xd4 */ x86emuOp_aam,
5376/* 0xd5 */ x86emuOp_aad,
5377/* 0xd6 */ x86emuOp_illegal_op, /* Undocumented SETALC instruction */
5378/* 0xd7 */ x86emuOp_xlat,
5379/* 0xd8 */ NULL, /*x86emuOp_esc_coprocess_d8,*/
5380/* 0xd9 */ NULL, /*x86emuOp_esc_coprocess_d9,*/
5381/* 0xda */ NULL, /*x86emuOp_esc_coprocess_da,*/
5382/* 0xdb */ NULL, /*x86emuOp_esc_coprocess_db,*/
5383/* 0xdc */ NULL, /*x86emuOp_esc_coprocess_dc,*/
5384/* 0xdd */ NULL, /*x86emuOp_esc_coprocess_dd,*/
5385/* 0xde */ NULL, /*x86emuOp_esc_coprocess_de,*/
5386/* 0xdf */ NULL, /*x86emuOp_esc_coprocess_df,*/
5387
5388/* 0xe0 */ x86emuOp_loopne,
5389/* 0xe1 */ x86emuOp_loope,
5390/* 0xe2 */ x86emuOp_loop,
5391/* 0xe3 */ x86emuOp_jcxz,
5392/* 0xe4 */ x86emuOp_in_byte_AL_IMM,
5393/* 0xe5 */ x86emuOp_in_word_AX_IMM,
5394/* 0xe6 */ x86emuOp_out_byte_IMM_AL,
5395/* 0xe7 */ x86emuOp_out_word_IMM_AX,
5396
5397/* 0xe8 */ x86emuOp_call_near_IMM,
5398/* 0xe9 */ x86emuOp_jump_near_IMM,
5399/* 0xea */ x86emuOp_jump_far_IMM,
5400/* 0xeb */ x86emuOp_jump_byte_IMM,
5401/* 0xec */ x86emuOp_in_byte_AL_DX,
5402/* 0xed */ x86emuOp_in_word_AX_DX,
5403/* 0xee */ x86emuOp_out_byte_DX_AL,
5404/* 0xef */ x86emuOp_out_word_DX_AX,
5405
5406/* 0xf0 */ x86emuOp_lock,
5407/* 0xf1 */ x86emuOp_illegal_op,
5408/* 0xf2 */ x86emuOp_repne,
5409/* 0xf3 */ x86emuOp_repe,
5410/* 0xf4 */ x86emuOp_halt,
5411/* 0xf5 */ x86emuOp_cmc,
5412/* 0xf6 */ x86emuOp_opcF6_byte_RM,
5413/* 0xf7 */ x86emuOp_opcF7_word_RM,
5414
5415/* 0xf8 */ x86emuOp_clc,
5416/* 0xf9 */ x86emuOp_stc,
5417/* 0xfa */ x86emuOp_cli,
5418/* 0xfb */ x86emuOp_sti,
5419/* 0xfc */ x86emuOp_cld,
5420/* 0xfd */ x86emuOp_std,
5421/* 0xfe */ x86emuOp_opcFE_byte_RM,
5422/* 0xff */ x86emuOp_opcFF_word_RM,
5423};