blob: c836a20b15f869cf46cd58aae0bc052d8ee5e6b3 [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{
3521 u16 tmp;
3522
3523 START_OF_INSTR();
3524 DECODE_PRINTF("INT 3\n");
3525 tmp = (u16) mem_access_word(3 * 4 + 2);
3526 /* access the segment register */
3527 TRACE_AND_STEP();
3528 if (_X86EMU_intrTab[3]) {
3529 (*_X86EMU_intrTab[3])(3);
3530 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003531 push_word((u16)M.x86.R_FLG);
3532 CLEAR_FLAG(F_IF);
3533 CLEAR_FLAG(F_TF);
3534 push_word(M.x86.R_CS);
3535 M.x86.R_CS = mem_access_word(3 * 4 + 2);
3536 push_word(M.x86.R_IP);
3537 M.x86.R_IP = mem_access_word(3 * 4);
Jason Jina63ce952007-07-06 08:34:56 +08003538 }
3539 DECODE_CLEAR_SEGOVR();
3540 END_OF_INSTR();
3541}
3542
3543/****************************************************************************
3544REMARKS:
3545Handles opcode 0xcd
3546****************************************************************************/
3547void x86emuOp_int_IMM(u8 X86EMU_UNUSED(op1))
3548{
3549 u16 tmp;
3550 u8 intnum;
3551
3552 START_OF_INSTR();
3553 DECODE_PRINTF("INT\t");
3554 intnum = fetch_byte_imm();
3555 DECODE_PRINTF2("%x\n", intnum);
3556 tmp = mem_access_word(intnum * 4 + 2);
3557 TRACE_AND_STEP();
3558 if (_X86EMU_intrTab[intnum]) {
3559 (*_X86EMU_intrTab[intnum])(intnum);
3560 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003561 push_word((u16)M.x86.R_FLG);
3562 CLEAR_FLAG(F_IF);
3563 CLEAR_FLAG(F_TF);
3564 push_word(M.x86.R_CS);
3565 M.x86.R_CS = mem_access_word(intnum * 4 + 2);
3566 push_word(M.x86.R_IP);
3567 M.x86.R_IP = mem_access_word(intnum * 4);
Jason Jina63ce952007-07-06 08:34:56 +08003568 }
3569 DECODE_CLEAR_SEGOVR();
3570 END_OF_INSTR();
3571}
3572
3573/****************************************************************************
3574REMARKS:
3575Handles opcode 0xce
3576****************************************************************************/
3577void x86emuOp_into(u8 X86EMU_UNUSED(op1))
3578{
3579 u16 tmp;
3580
3581 START_OF_INSTR();
3582 DECODE_PRINTF("INTO\n");
3583 TRACE_AND_STEP();
3584 if (ACCESS_FLAG(F_OF)) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003585 tmp = mem_access_word(4 * 4 + 2);
Jason Jina63ce952007-07-06 08:34:56 +08003586 if (_X86EMU_intrTab[4]) {
3587 (*_X86EMU_intrTab[4])(4);
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003588 } else {
3589 push_word((u16)M.x86.R_FLG);
3590 CLEAR_FLAG(F_IF);
3591 CLEAR_FLAG(F_TF);
3592 push_word(M.x86.R_CS);
3593 M.x86.R_CS = mem_access_word(4 * 4 + 2);
3594 push_word(M.x86.R_IP);
3595 M.x86.R_IP = mem_access_word(4 * 4);
3596 }
Jason Jina63ce952007-07-06 08:34:56 +08003597 }
3598 DECODE_CLEAR_SEGOVR();
3599 END_OF_INSTR();
3600}
3601
3602/****************************************************************************
3603REMARKS:
3604Handles opcode 0xcf
3605****************************************************************************/
3606void x86emuOp_iret(u8 X86EMU_UNUSED(op1))
3607{
3608 START_OF_INSTR();
3609 DECODE_PRINTF("IRET\n");
3610
3611 TRACE_AND_STEP();
3612
3613 M.x86.R_IP = pop_word();
3614 M.x86.R_CS = pop_word();
3615 M.x86.R_FLG = pop_word();
3616 DECODE_CLEAR_SEGOVR();
3617 END_OF_INSTR();
3618}
3619
3620/****************************************************************************
3621REMARKS:
3622Handles opcode 0xd0
3623****************************************************************************/
3624void x86emuOp_opcD0_byte_RM_1(u8 X86EMU_UNUSED(op1))
3625{
3626 int mod, rl, rh;
3627 u8 *destreg;
3628 uint destoffset;
3629 u8 destval;
3630
3631 /*
3632 * Yet another weirdo special case instruction format. Part of
3633 * the opcode held below in "RH". Doubly nested case would
3634 * result, except that the decoded instruction
3635 */
3636 START_OF_INSTR();
3637 FETCH_DECODE_MODRM(mod, rh, rl);
3638#ifdef DEBUG
3639 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003640 /* XXX DECODE_PRINTF may be changed to something more
3641 general, so that it is important to leave the strings
3642 in the same format, even though the result is that the
3643 above test is done twice. */
3644 switch (rh) {
3645 case 0:
3646 DECODE_PRINTF("ROL\t");
3647 break;
3648 case 1:
3649 DECODE_PRINTF("ROR\t");
3650 break;
3651 case 2:
3652 DECODE_PRINTF("RCL\t");
3653 break;
3654 case 3:
3655 DECODE_PRINTF("RCR\t");
3656 break;
3657 case 4:
3658 DECODE_PRINTF("SHL\t");
3659 break;
3660 case 5:
3661 DECODE_PRINTF("SHR\t");
3662 break;
3663 case 6:
3664 DECODE_PRINTF("SAL\t");
3665 break;
3666 case 7:
3667 DECODE_PRINTF("SAR\t");
3668 break;
3669 }
Jason Jina63ce952007-07-06 08:34:56 +08003670 }
3671#endif
3672 /* know operation, decode the mod byte to find the addressing
3673 mode. */
3674 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003675 DECODE_PRINTF("BYTE PTR ");
3676 destoffset = decode_rmXX_address(mod, rl);
3677 DECODE_PRINTF(",1\n");
3678 destval = fetch_data_byte(destoffset);
3679 TRACE_AND_STEP();
3680 destval = (*opcD0_byte_operation[rh]) (destval, 1);
3681 store_data_byte(destoffset, destval);
3682 } else { /* register to register */
3683 destreg = DECODE_RM_BYTE_REGISTER(rl);
3684 DECODE_PRINTF(",1\n");
3685 TRACE_AND_STEP();
3686 destval = (*opcD0_byte_operation[rh]) (*destreg, 1);
3687 *destreg = destval;
Jason Jina63ce952007-07-06 08:34:56 +08003688 }
3689 DECODE_CLEAR_SEGOVR();
3690 END_OF_INSTR();
3691}
3692
3693/****************************************************************************
3694REMARKS:
3695Handles opcode 0xd1
3696****************************************************************************/
3697void x86emuOp_opcD1_word_RM_1(u8 X86EMU_UNUSED(op1))
3698{
3699 int mod, rl, rh;
3700 uint destoffset;
3701
3702 /*
3703 * Yet another weirdo special case instruction format. Part of
3704 * the opcode held below in "RH". Doubly nested case would
3705 * result, except that the decoded instruction
3706 */
3707 START_OF_INSTR();
3708 FETCH_DECODE_MODRM(mod, rh, rl);
3709#ifdef DEBUG
3710 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003711 /* XXX DECODE_PRINTF may be changed to something more
3712 general, so that it is important to leave the strings
3713 in the same format, even though the result is that the
3714 above test is done twice. */
3715 switch (rh) {
3716 case 0:
3717 DECODE_PRINTF("ROL\t");
3718 break;
3719 case 1:
3720 DECODE_PRINTF("ROR\t");
3721 break;
3722 case 2:
3723 DECODE_PRINTF("RCL\t");
3724 break;
3725 case 3:
3726 DECODE_PRINTF("RCR\t");
3727 break;
3728 case 4:
3729 DECODE_PRINTF("SHL\t");
3730 break;
3731 case 5:
3732 DECODE_PRINTF("SHR\t");
3733 break;
3734 case 6:
3735 DECODE_PRINTF("SAL\t");
3736 break;
3737 case 7:
3738 DECODE_PRINTF("SAR\t");
3739 break;
3740 }
Jason Jina63ce952007-07-06 08:34:56 +08003741 }
3742#endif
3743 /* know operation, decode the mod byte to find the addressing
3744 mode. */
3745 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003746 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3747 u32 destval;
Jason Jina63ce952007-07-06 08:34:56 +08003748
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003749 DECODE_PRINTF("DWORD PTR ");
3750 destoffset = decode_rmXX_address(mod, rl);
3751 DECODE_PRINTF(",1\n");
3752 destval = fetch_data_long(destoffset);
3753 TRACE_AND_STEP();
3754 destval = (*opcD1_long_operation[rh]) (destval, 1);
3755 store_data_long(destoffset, destval);
3756 } else {
3757 u16 destval;
Jason Jina63ce952007-07-06 08:34:56 +08003758
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003759 DECODE_PRINTF("WORD PTR ");
3760 destoffset = decode_rmXX_address(mod, rl);
3761 DECODE_PRINTF(",1\n");
3762 destval = fetch_data_word(destoffset);
3763 TRACE_AND_STEP();
3764 destval = (*opcD1_word_operation[rh]) (destval, 1);
3765 store_data_word(destoffset, destval);
3766 }
3767 } else { /* register to register */
3768 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Jason Jina63ce952007-07-06 08:34:56 +08003769 u32 destval;
3770 u32 *destreg;
3771
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003772 destreg = DECODE_RM_LONG_REGISTER(rl);
3773 DECODE_PRINTF(",1\n");
3774 TRACE_AND_STEP();
3775 destval = (*opcD1_long_operation[rh]) (*destreg, 1);
3776 *destreg = destval;
3777 } else {
Jason Jina63ce952007-07-06 08:34:56 +08003778 u16 destval;
3779 u16 *destreg;
3780
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003781 destreg = DECODE_RM_WORD_REGISTER(rl);
3782 DECODE_PRINTF(",1\n");
3783 TRACE_AND_STEP();
3784 destval = (*opcD1_word_operation[rh]) (*destreg, 1);
3785 *destreg = destval;
3786 }
Jason Jina63ce952007-07-06 08:34:56 +08003787 }
3788 DECODE_CLEAR_SEGOVR();
3789 END_OF_INSTR();
3790}
3791
3792/****************************************************************************
3793REMARKS:
3794Handles opcode 0xd2
3795****************************************************************************/
3796void x86emuOp_opcD2_byte_RM_CL(u8 X86EMU_UNUSED(op1))
3797{
3798 int mod, rl, rh;
3799 u8 *destreg;
3800 uint destoffset;
3801 u8 destval;
3802 u8 amt;
3803
3804 /*
3805 * Yet another weirdo special case instruction format. Part of
3806 * the opcode held below in "RH". Doubly nested case would
3807 * result, except that the decoded instruction
3808 */
3809 START_OF_INSTR();
3810 FETCH_DECODE_MODRM(mod, rh, rl);
3811#ifdef DEBUG
3812 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003813 /* XXX DECODE_PRINTF may be changed to something more
3814 general, so that it is important to leave the strings
3815 in the same format, even though the result is that the
3816 above test is done twice. */
3817 switch (rh) {
3818 case 0:
3819 DECODE_PRINTF("ROL\t");
3820 break;
3821 case 1:
3822 DECODE_PRINTF("ROR\t");
3823 break;
3824 case 2:
3825 DECODE_PRINTF("RCL\t");
3826 break;
3827 case 3:
3828 DECODE_PRINTF("RCR\t");
3829 break;
3830 case 4:
3831 DECODE_PRINTF("SHL\t");
3832 break;
3833 case 5:
3834 DECODE_PRINTF("SHR\t");
3835 break;
3836 case 6:
3837 DECODE_PRINTF("SAL\t");
3838 break;
3839 case 7:
3840 DECODE_PRINTF("SAR\t");
3841 break;
3842 }
Jason Jina63ce952007-07-06 08:34:56 +08003843 }
3844#endif
3845 /* know operation, decode the mod byte to find the addressing
3846 mode. */
3847 amt = M.x86.R_CL;
3848 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003849 DECODE_PRINTF("BYTE PTR ");
3850 destoffset = decode_rmXX_address(mod, rl);
3851 DECODE_PRINTF(",CL\n");
3852 destval = fetch_data_byte(destoffset);
3853 TRACE_AND_STEP();
3854 destval = (*opcD0_byte_operation[rh]) (destval, amt);
3855 store_data_byte(destoffset, destval);
3856 } else { /* register to register */
3857 destreg = DECODE_RM_BYTE_REGISTER(rl);
3858 DECODE_PRINTF(",CL\n");
3859 TRACE_AND_STEP();
3860 destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3861 *destreg = destval;
Jason Jina63ce952007-07-06 08:34:56 +08003862 }
3863 DECODE_CLEAR_SEGOVR();
3864 END_OF_INSTR();
3865}
3866
3867/****************************************************************************
3868REMARKS:
3869Handles opcode 0xd3
3870****************************************************************************/
3871void x86emuOp_opcD3_word_RM_CL(u8 X86EMU_UNUSED(op1))
3872{
3873 int mod, rl, rh;
3874 uint destoffset;
3875 u8 amt;
3876
3877 /*
3878 * Yet another weirdo special case instruction format. Part of
3879 * the opcode held below in "RH". Doubly nested case would
3880 * result, except that the decoded instruction
3881 */
3882 START_OF_INSTR();
3883 FETCH_DECODE_MODRM(mod, rh, rl);
3884#ifdef DEBUG
3885 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003886 /* XXX DECODE_PRINTF may be changed to something more
3887 general, so that it is important to leave the strings
3888 in the same format, even though the result is that the
3889 above test is done twice. */
3890 switch (rh) {
3891 case 0:
3892 DECODE_PRINTF("ROL\t");
3893 break;
3894 case 1:
3895 DECODE_PRINTF("ROR\t");
3896 break;
3897 case 2:
3898 DECODE_PRINTF("RCL\t");
3899 break;
3900 case 3:
3901 DECODE_PRINTF("RCR\t");
3902 break;
3903 case 4:
3904 DECODE_PRINTF("SHL\t");
3905 break;
3906 case 5:
3907 DECODE_PRINTF("SHR\t");
3908 break;
3909 case 6:
3910 DECODE_PRINTF("SAL\t");
3911 break;
3912 case 7:
3913 DECODE_PRINTF("SAR\t");
3914 break;
3915 }
Jason Jina63ce952007-07-06 08:34:56 +08003916 }
3917#endif
3918 /* know operation, decode the mod byte to find the addressing
3919 mode. */
3920 amt = M.x86.R_CL;
3921 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003922 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3923 u32 destval;
Jason Jina63ce952007-07-06 08:34:56 +08003924
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003925 DECODE_PRINTF("DWORD PTR ");
3926 destoffset = decode_rmXX_address(mod, rl);
3927 DECODE_PRINTF(",CL\n");
3928 destval = fetch_data_long(destoffset);
3929 TRACE_AND_STEP();
3930 destval = (*opcD1_long_operation[rh]) (destval, amt);
3931 store_data_long(destoffset, destval);
3932 } else {
3933 u16 destval;
Jason Jina63ce952007-07-06 08:34:56 +08003934
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003935 DECODE_PRINTF("WORD PTR ");
3936 destoffset = decode_rmXX_address(mod, rl);
3937 DECODE_PRINTF(",CL\n");
3938 destval = fetch_data_word(destoffset);
3939 TRACE_AND_STEP();
3940 destval = (*opcD1_word_operation[rh]) (destval, amt);
3941 store_data_word(destoffset, destval);
3942 }
3943 } else { /* register to register */
3944 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3945 u32 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08003946
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003947 destreg = DECODE_RM_LONG_REGISTER(rl);
3948 DECODE_PRINTF(",CL\n");
3949 TRACE_AND_STEP();
3950 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3951 } else {
3952 u16 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08003953
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003954 destreg = DECODE_RM_WORD_REGISTER(rl);
3955 DECODE_PRINTF(",CL\n");
3956 TRACE_AND_STEP();
3957 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
3958 }
Jason Jina63ce952007-07-06 08:34:56 +08003959 }
3960 DECODE_CLEAR_SEGOVR();
3961 END_OF_INSTR();
3962}
3963
3964/****************************************************************************
3965REMARKS:
3966Handles opcode 0xd4
3967****************************************************************************/
3968void x86emuOp_aam(u8 X86EMU_UNUSED(op1))
3969{
3970 u8 a;
3971
3972 START_OF_INSTR();
3973 DECODE_PRINTF("AAM\n");
3974 a = fetch_byte_imm(); /* this is a stupid encoding. */
3975 if (a != 10) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003976 DECODE_PRINTF("ERROR DECODING AAM\n");
3977 TRACE_REGS();
3978 HALT_SYS();
Jason Jina63ce952007-07-06 08:34:56 +08003979 }
3980 TRACE_AND_STEP();
3981 /* note the type change here --- returning AL and AH in AX. */
3982 M.x86.R_AX = aam_word(M.x86.R_AL);
3983 DECODE_CLEAR_SEGOVR();
3984 END_OF_INSTR();
3985}
3986
3987/****************************************************************************
3988REMARKS:
3989Handles opcode 0xd5
3990****************************************************************************/
3991void x86emuOp_aad(u8 X86EMU_UNUSED(op1))
3992{
3993 u8 a;
3994
3995 START_OF_INSTR();
3996 DECODE_PRINTF("AAD\n");
3997 a = fetch_byte_imm();
3998 TRACE_AND_STEP();
3999 M.x86.R_AX = aad_word(M.x86.R_AX);
4000 DECODE_CLEAR_SEGOVR();
4001 END_OF_INSTR();
4002}
4003
4004/* opcode 0xd6 ILLEGAL OPCODE */
4005
4006/****************************************************************************
4007REMARKS:
4008Handles opcode 0xd7
4009****************************************************************************/
4010void x86emuOp_xlat(u8 X86EMU_UNUSED(op1))
4011{
4012 u16 addr;
4013
4014 START_OF_INSTR();
4015 DECODE_PRINTF("XLAT\n");
4016 TRACE_AND_STEP();
4017 addr = (u16)(M.x86.R_BX + (u8)M.x86.R_AL);
4018 M.x86.R_AL = fetch_data_byte(addr);
4019 DECODE_CLEAR_SEGOVR();
4020 END_OF_INSTR();
4021}
4022
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004023/* instuctions D8 .. DF are in i87_ops.c */
Jason Jina63ce952007-07-06 08:34:56 +08004024
4025/****************************************************************************
4026REMARKS:
4027Handles opcode 0xe0
4028****************************************************************************/
4029void x86emuOp_loopne(u8 X86EMU_UNUSED(op1))
4030{
4031 s16 ip;
4032
4033 START_OF_INSTR();
4034 DECODE_PRINTF("LOOPNE\t");
4035 ip = (s8) fetch_byte_imm();
4036 ip += (s16) M.x86.R_IP;
4037 DECODE_PRINTF2("%04x\n", ip);
4038 TRACE_AND_STEP();
4039 M.x86.R_CX -= 1;
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004040 if (M.x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */
4041 M.x86.R_IP = ip;
Jason Jina63ce952007-07-06 08:34:56 +08004042 DECODE_CLEAR_SEGOVR();
4043 END_OF_INSTR();
4044}
4045
4046/****************************************************************************
4047REMARKS:
4048Handles opcode 0xe1
4049****************************************************************************/
4050void x86emuOp_loope(u8 X86EMU_UNUSED(op1))
4051{
4052 s16 ip;
4053
4054 START_OF_INSTR();
4055 DECODE_PRINTF("LOOPE\t");
4056 ip = (s8) fetch_byte_imm();
4057 ip += (s16) M.x86.R_IP;
4058 DECODE_PRINTF2("%04x\n", ip);
4059 TRACE_AND_STEP();
4060 M.x86.R_CX -= 1;
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004061 if (M.x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */
4062 M.x86.R_IP = ip;
Jason Jina63ce952007-07-06 08:34:56 +08004063 DECODE_CLEAR_SEGOVR();
4064 END_OF_INSTR();
4065}
4066
4067/****************************************************************************
4068REMARKS:
4069Handles opcode 0xe2
4070****************************************************************************/
4071void x86emuOp_loop(u8 X86EMU_UNUSED(op1))
4072{
4073 s16 ip;
4074
4075 START_OF_INSTR();
4076 DECODE_PRINTF("LOOP\t");
4077 ip = (s8) fetch_byte_imm();
4078 ip += (s16) M.x86.R_IP;
4079 DECODE_PRINTF2("%04x\n", ip);
4080 TRACE_AND_STEP();
4081 M.x86.R_CX -= 1;
4082 if (M.x86.R_CX != 0)
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004083 M.x86.R_IP = ip;
Jason Jina63ce952007-07-06 08:34:56 +08004084 DECODE_CLEAR_SEGOVR();
4085 END_OF_INSTR();
4086}
4087
4088/****************************************************************************
4089REMARKS:
4090Handles opcode 0xe3
4091****************************************************************************/
4092void x86emuOp_jcxz(u8 X86EMU_UNUSED(op1))
4093{
4094 u16 target;
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004095 s8 offset;
Jason Jina63ce952007-07-06 08:34:56 +08004096
4097 /* jump to byte offset if overflow flag is set */
4098 START_OF_INSTR();
4099 DECODE_PRINTF("JCXZ\t");
4100 offset = (s8)fetch_byte_imm();
4101 target = (u16)(M.x86.R_IP + offset);
4102 DECODE_PRINTF2("%x\n", target);
4103 TRACE_AND_STEP();
4104 if (M.x86.R_CX == 0)
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004105 M.x86.R_IP = target;
Jason Jina63ce952007-07-06 08:34:56 +08004106 DECODE_CLEAR_SEGOVR();
4107 END_OF_INSTR();
4108}
4109
4110/****************************************************************************
4111REMARKS:
4112Handles opcode 0xe4
4113****************************************************************************/
4114void x86emuOp_in_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
4115{
4116 u8 port;
4117
4118 START_OF_INSTR();
4119 DECODE_PRINTF("IN\t");
4120 port = (u8) fetch_byte_imm();
4121 DECODE_PRINTF2("%x,AL\n", port);
4122 TRACE_AND_STEP();
4123 M.x86.R_AL = (*sys_inb)(port);
4124 DECODE_CLEAR_SEGOVR();
4125 END_OF_INSTR();
4126}
4127
4128/****************************************************************************
4129REMARKS:
4130Handles opcode 0xe5
4131****************************************************************************/
4132void x86emuOp_in_word_AX_IMM(u8 X86EMU_UNUSED(op1))
4133{
4134 u8 port;
4135
4136 START_OF_INSTR();
4137 DECODE_PRINTF("IN\t");
4138 port = (u8) fetch_byte_imm();
4139 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004140 DECODE_PRINTF2("EAX,%x\n", port);
Jason Jina63ce952007-07-06 08:34:56 +08004141 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004142 DECODE_PRINTF2("AX,%x\n", port);
Jason Jina63ce952007-07-06 08:34:56 +08004143 }
4144 TRACE_AND_STEP();
4145 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004146 M.x86.R_EAX = (*sys_inl)(port);
Jason Jina63ce952007-07-06 08:34:56 +08004147 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004148 M.x86.R_AX = (*sys_inw)(port);
Jason Jina63ce952007-07-06 08:34:56 +08004149 }
4150 DECODE_CLEAR_SEGOVR();
4151 END_OF_INSTR();
4152}
4153
4154/****************************************************************************
4155REMARKS:
4156Handles opcode 0xe6
4157****************************************************************************/
4158void x86emuOp_out_byte_IMM_AL(u8 X86EMU_UNUSED(op1))
4159{
4160 u8 port;
4161
4162 START_OF_INSTR();
4163 DECODE_PRINTF("OUT\t");
4164 port = (u8) fetch_byte_imm();
4165 DECODE_PRINTF2("%x,AL\n", port);
4166 TRACE_AND_STEP();
4167 (*sys_outb)(port, M.x86.R_AL);
4168 DECODE_CLEAR_SEGOVR();
4169 END_OF_INSTR();
4170}
4171
4172/****************************************************************************
4173REMARKS:
4174Handles opcode 0xe7
4175****************************************************************************/
4176void x86emuOp_out_word_IMM_AX(u8 X86EMU_UNUSED(op1))
4177{
4178 u8 port;
4179
4180 START_OF_INSTR();
4181 DECODE_PRINTF("OUT\t");
4182 port = (u8) fetch_byte_imm();
4183 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004184 DECODE_PRINTF2("%x,EAX\n", port);
Jason Jina63ce952007-07-06 08:34:56 +08004185 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004186 DECODE_PRINTF2("%x,AX\n", port);
Jason Jina63ce952007-07-06 08:34:56 +08004187 }
4188 TRACE_AND_STEP();
4189 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004190 (*sys_outl)(port, M.x86.R_EAX);
Jason Jina63ce952007-07-06 08:34:56 +08004191 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004192 (*sys_outw)(port, M.x86.R_AX);
Jason Jina63ce952007-07-06 08:34:56 +08004193 }
4194 DECODE_CLEAR_SEGOVR();
4195 END_OF_INSTR();
4196}
4197
4198/****************************************************************************
4199REMARKS:
4200Handles opcode 0xe8
4201****************************************************************************/
4202void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1))
4203{
4204 s16 ip;
4205
4206 START_OF_INSTR();
4207 DECODE_PRINTF("CALL\t");
4208 ip = (s16) fetch_word_imm();
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004209 ip += (s16) M.x86.R_IP; /* CHECK SIGN */
Jason Jina63ce952007-07-06 08:34:56 +08004210 DECODE_PRINTF2("%04x\n", ip);
4211 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, "");
4212 TRACE_AND_STEP();
4213 push_word(M.x86.R_IP);
4214 M.x86.R_IP = ip;
4215 DECODE_CLEAR_SEGOVR();
4216 END_OF_INSTR();
4217}
4218
4219/****************************************************************************
4220REMARKS:
4221Handles opcode 0xe9
4222****************************************************************************/
4223void x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1))
4224{
4225 int ip;
4226
4227 START_OF_INSTR();
4228 DECODE_PRINTF("JMP\t");
4229 ip = (s16)fetch_word_imm();
4230 ip += (s16)M.x86.R_IP;
4231 DECODE_PRINTF2("%04x\n", ip);
4232 TRACE_AND_STEP();
4233 M.x86.R_IP = (u16)ip;
4234 DECODE_CLEAR_SEGOVR();
4235 END_OF_INSTR();
4236}
4237
4238/****************************************************************************
4239REMARKS:
4240Handles opcode 0xea
4241****************************************************************************/
4242void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1))
4243{
4244 u16 cs, ip;
4245
4246 START_OF_INSTR();
4247 DECODE_PRINTF("JMP\tFAR ");
4248 ip = fetch_word_imm();
4249 cs = fetch_word_imm();
4250 DECODE_PRINTF2("%04x:", cs);
4251 DECODE_PRINTF2("%04x\n", ip);
4252 TRACE_AND_STEP();
4253 M.x86.R_IP = ip;
4254 M.x86.R_CS = cs;
4255 DECODE_CLEAR_SEGOVR();
4256 END_OF_INSTR();
4257}
4258
4259/****************************************************************************
4260REMARKS:
4261Handles opcode 0xeb
4262****************************************************************************/
4263void x86emuOp_jump_byte_IMM(u8 X86EMU_UNUSED(op1))
4264{
4265 u16 target;
4266 s8 offset;
4267
4268 START_OF_INSTR();
4269 DECODE_PRINTF("JMP\t");
4270 offset = (s8)fetch_byte_imm();
4271 target = (u16)(M.x86.R_IP + offset);
4272 DECODE_PRINTF2("%x\n", target);
4273 TRACE_AND_STEP();
4274 M.x86.R_IP = target;
4275 DECODE_CLEAR_SEGOVR();
4276 END_OF_INSTR();
4277}
4278
4279/****************************************************************************
4280REMARKS:
4281Handles opcode 0xec
4282****************************************************************************/
4283void x86emuOp_in_byte_AL_DX(u8 X86EMU_UNUSED(op1))
4284{
4285 START_OF_INSTR();
4286 DECODE_PRINTF("IN\tAL,DX\n");
4287 TRACE_AND_STEP();
4288 M.x86.R_AL = (*sys_inb)(M.x86.R_DX);
4289 DECODE_CLEAR_SEGOVR();
4290 END_OF_INSTR();
4291}
4292
4293/****************************************************************************
4294REMARKS:
4295Handles opcode 0xed
4296****************************************************************************/
4297void x86emuOp_in_word_AX_DX(u8 X86EMU_UNUSED(op1))
4298{
4299 START_OF_INSTR();
4300 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004301 DECODE_PRINTF("IN\tEAX,DX\n");
Jason Jina63ce952007-07-06 08:34:56 +08004302 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004303 DECODE_PRINTF("IN\tAX,DX\n");
Jason Jina63ce952007-07-06 08:34:56 +08004304 }
4305 TRACE_AND_STEP();
4306 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004307 M.x86.R_EAX = (*sys_inl)(M.x86.R_DX);
Jason Jina63ce952007-07-06 08:34:56 +08004308 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004309 M.x86.R_AX = (*sys_inw)(M.x86.R_DX);
Jason Jina63ce952007-07-06 08:34:56 +08004310 }
4311 DECODE_CLEAR_SEGOVR();
4312 END_OF_INSTR();
4313}
4314
4315/****************************************************************************
4316REMARKS:
4317Handles opcode 0xee
4318****************************************************************************/
4319void x86emuOp_out_byte_DX_AL(u8 X86EMU_UNUSED(op1))
4320{
4321 START_OF_INSTR();
4322 DECODE_PRINTF("OUT\tDX,AL\n");
4323 TRACE_AND_STEP();
4324 (*sys_outb)(M.x86.R_DX, M.x86.R_AL);
4325 DECODE_CLEAR_SEGOVR();
4326 END_OF_INSTR();
4327}
4328
4329/****************************************************************************
4330REMARKS:
4331Handles opcode 0xef
4332****************************************************************************/
4333void x86emuOp_out_word_DX_AX(u8 X86EMU_UNUSED(op1))
4334{
4335 START_OF_INSTR();
4336 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004337 DECODE_PRINTF("OUT\tDX,EAX\n");
Jason Jina63ce952007-07-06 08:34:56 +08004338 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004339 DECODE_PRINTF("OUT\tDX,AX\n");
Jason Jina63ce952007-07-06 08:34:56 +08004340 }
4341 TRACE_AND_STEP();
4342 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004343 (*sys_outl)(M.x86.R_DX, M.x86.R_EAX);
Jason Jina63ce952007-07-06 08:34:56 +08004344 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004345 (*sys_outw)(M.x86.R_DX, M.x86.R_AX);
Jason Jina63ce952007-07-06 08:34:56 +08004346 }
4347 DECODE_CLEAR_SEGOVR();
4348 END_OF_INSTR();
4349}
4350
4351/****************************************************************************
4352REMARKS:
4353Handles opcode 0xf0
4354****************************************************************************/
4355void x86emuOp_lock(u8 X86EMU_UNUSED(op1))
4356{
4357 START_OF_INSTR();
4358 DECODE_PRINTF("LOCK:\n");
4359 TRACE_AND_STEP();
4360 DECODE_CLEAR_SEGOVR();
4361 END_OF_INSTR();
4362}
4363
4364/*opcode 0xf1 ILLEGAL OPERATION */
4365
4366/****************************************************************************
4367REMARKS:
4368Handles opcode 0xf2
4369****************************************************************************/
4370void x86emuOp_repne(u8 X86EMU_UNUSED(op1))
4371{
4372 START_OF_INSTR();
4373 DECODE_PRINTF("REPNE\n");
4374 TRACE_AND_STEP();
4375 M.x86.mode |= SYSMODE_PREFIX_REPNE;
4376 DECODE_CLEAR_SEGOVR();
4377 END_OF_INSTR();
4378}
4379
4380/****************************************************************************
4381REMARKS:
4382Handles opcode 0xf3
4383****************************************************************************/
4384void x86emuOp_repe(u8 X86EMU_UNUSED(op1))
4385{
4386 START_OF_INSTR();
4387 DECODE_PRINTF("REPE\n");
4388 TRACE_AND_STEP();
4389 M.x86.mode |= SYSMODE_PREFIX_REPE;
4390 DECODE_CLEAR_SEGOVR();
4391 END_OF_INSTR();
4392}
4393
4394/****************************************************************************
4395REMARKS:
4396Handles opcode 0xf4
4397****************************************************************************/
4398void x86emuOp_halt(u8 X86EMU_UNUSED(op1))
4399{
4400 START_OF_INSTR();
4401 DECODE_PRINTF("HALT\n");
4402 TRACE_AND_STEP();
4403 HALT_SYS();
4404 DECODE_CLEAR_SEGOVR();
4405 END_OF_INSTR();
4406}
4407
4408/****************************************************************************
4409REMARKS:
4410Handles opcode 0xf5
4411****************************************************************************/
4412void x86emuOp_cmc(u8 X86EMU_UNUSED(op1))
4413{
4414 /* complement the carry flag. */
4415 START_OF_INSTR();
4416 DECODE_PRINTF("CMC\n");
4417 TRACE_AND_STEP();
4418 TOGGLE_FLAG(F_CF);
4419 DECODE_CLEAR_SEGOVR();
4420 END_OF_INSTR();
4421}
4422
4423/****************************************************************************
4424REMARKS:
4425Handles opcode 0xf6
4426****************************************************************************/
4427void x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1))
4428{
4429 int mod, rl, rh;
4430 u8 *destreg;
4431 uint destoffset;
4432 u8 destval, srcval;
4433
4434 /* long, drawn out code follows. Double switch for a total
4435 of 32 cases. */
4436 START_OF_INSTR();
4437 FETCH_DECODE_MODRM(mod, rh, rl);
4438 DECODE_PRINTF(opF6_names[rh]);
4439 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004440 DECODE_PRINTF("BYTE PTR ");
4441 destoffset = decode_rmXX_address(mod, rl);
4442 destval = fetch_data_byte(destoffset);
Jason Jina63ce952007-07-06 08:34:56 +08004443
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004444 switch (rh) {
4445 case 0: /* test byte imm */
4446 DECODE_PRINTF(",");
4447 srcval = fetch_byte_imm();
4448 DECODE_PRINTF2("%02x\n", srcval);
4449 TRACE_AND_STEP();
4450 test_byte(destval, srcval);
4451 break;
4452 case 1:
4453 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4454 HALT_SYS();
4455 break;
4456 case 2:
4457 DECODE_PRINTF("\n");
4458 TRACE_AND_STEP();
4459 destval = not_byte(destval);
4460 store_data_byte(destoffset, destval);
4461 break;
4462 case 3:
4463 DECODE_PRINTF("\n");
4464 TRACE_AND_STEP();
4465 destval = neg_byte(destval);
4466 store_data_byte(destoffset, destval);
4467 break;
4468 case 4:
4469 DECODE_PRINTF("\n");
4470 TRACE_AND_STEP();
4471 mul_byte(destval);
4472 break;
4473 case 5:
4474 DECODE_PRINTF("\n");
4475 TRACE_AND_STEP();
4476 imul_byte(destval);
4477 break;
4478 case 6:
4479 DECODE_PRINTF("\n");
4480 TRACE_AND_STEP();
4481 div_byte(destval);
4482 break;
4483 default:
4484 DECODE_PRINTF("\n");
4485 TRACE_AND_STEP();
4486 idiv_byte(destval);
4487 break;
4488 }
4489 } else { /* mod=11 */
4490 destreg = DECODE_RM_BYTE_REGISTER(rl);
4491 switch (rh) {
4492 case 0: /* test byte imm */
4493 DECODE_PRINTF(",");
4494 srcval = fetch_byte_imm();
4495 DECODE_PRINTF2("%02x\n", srcval);
4496 TRACE_AND_STEP();
4497 test_byte(*destreg, srcval);
4498 break;
4499 case 1:
4500 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4501 HALT_SYS();
4502 break;
4503 case 2:
4504 DECODE_PRINTF("\n");
4505 TRACE_AND_STEP();
4506 *destreg = not_byte(*destreg);
4507 break;
4508 case 3:
4509 DECODE_PRINTF("\n");
4510 TRACE_AND_STEP();
4511 *destreg = neg_byte(*destreg);
4512 break;
4513 case 4:
4514 DECODE_PRINTF("\n");
4515 TRACE_AND_STEP();
4516 mul_byte(*destreg); /*!!! */
4517 break;
4518 case 5:
4519 DECODE_PRINTF("\n");
4520 TRACE_AND_STEP();
4521 imul_byte(*destreg);
4522 break;
4523 case 6:
4524 DECODE_PRINTF("\n");
4525 TRACE_AND_STEP();
4526 div_byte(*destreg);
4527 break;
4528 default:
4529 DECODE_PRINTF("\n");
4530 TRACE_AND_STEP();
4531 idiv_byte(*destreg);
4532 break;
4533 }
Jason Jina63ce952007-07-06 08:34:56 +08004534 }
4535 DECODE_CLEAR_SEGOVR();
4536 END_OF_INSTR();
4537}
4538
4539/****************************************************************************
4540REMARKS:
4541Handles opcode 0xf7
4542****************************************************************************/
4543void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1))
4544{
4545 int mod, rl, rh;
4546 uint destoffset;
4547
4548 START_OF_INSTR();
4549 FETCH_DECODE_MODRM(mod, rh, rl);
4550 DECODE_PRINTF(opF6_names[rh]);
4551 if (mod < 3) {
4552
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004553 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4554 u32 destval, srcval;
Jason Jina63ce952007-07-06 08:34:56 +08004555
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004556 DECODE_PRINTF("DWORD PTR ");
4557 destoffset = decode_rmXX_address(mod, rl);
4558 destval = fetch_data_long(destoffset);
Jason Jina63ce952007-07-06 08:34:56 +08004559
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004560 switch (rh) {
4561 case 0:
4562 DECODE_PRINTF(",");
4563 srcval = fetch_long_imm();
4564 DECODE_PRINTF2("%x\n", srcval);
4565 TRACE_AND_STEP();
4566 test_long(destval, srcval);
4567 break;
4568 case 1:
4569 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4570 HALT_SYS();
4571 break;
4572 case 2:
4573 DECODE_PRINTF("\n");
4574 TRACE_AND_STEP();
4575 destval = not_long(destval);
4576 store_data_long(destoffset, destval);
4577 break;
4578 case 3:
4579 DECODE_PRINTF("\n");
4580 TRACE_AND_STEP();
4581 destval = neg_long(destval);
4582 store_data_long(destoffset, destval);
4583 break;
4584 case 4:
4585 DECODE_PRINTF("\n");
4586 TRACE_AND_STEP();
4587 mul_long(destval);
4588 break;
4589 case 5:
4590 DECODE_PRINTF("\n");
4591 TRACE_AND_STEP();
4592 imul_long(destval);
4593 break;
4594 case 6:
4595 DECODE_PRINTF("\n");
4596 TRACE_AND_STEP();
4597 div_long(destval);
4598 break;
4599 case 7:
4600 DECODE_PRINTF("\n");
4601 TRACE_AND_STEP();
4602 idiv_long(destval);
4603 break;
4604 }
4605 } else {
4606 u16 destval, srcval;
Jason Jina63ce952007-07-06 08:34:56 +08004607
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004608 DECODE_PRINTF("WORD PTR ");
4609 destoffset = decode_rmXX_address(mod, rl);
4610 destval = fetch_data_word(destoffset);
Jason Jina63ce952007-07-06 08:34:56 +08004611
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004612 switch (rh) {
4613 case 0: /* test word imm */
4614 DECODE_PRINTF(",");
4615 srcval = fetch_word_imm();
4616 DECODE_PRINTF2("%x\n", srcval);
4617 TRACE_AND_STEP();
4618 test_word(destval, srcval);
4619 break;
4620 case 1:
4621 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4622 HALT_SYS();
4623 break;
4624 case 2:
4625 DECODE_PRINTF("\n");
4626 TRACE_AND_STEP();
4627 destval = not_word(destval);
4628 store_data_word(destoffset, destval);
4629 break;
4630 case 3:
4631 DECODE_PRINTF("\n");
4632 TRACE_AND_STEP();
4633 destval = neg_word(destval);
4634 store_data_word(destoffset, destval);
4635 break;
4636 case 4:
4637 DECODE_PRINTF("\n");
4638 TRACE_AND_STEP();
4639 mul_word(destval);
4640 break;
4641 case 5:
4642 DECODE_PRINTF("\n");
4643 TRACE_AND_STEP();
4644 imul_word(destval);
4645 break;
4646 case 6:
4647 DECODE_PRINTF("\n");
4648 TRACE_AND_STEP();
4649 div_word(destval);
4650 break;
4651 case 7:
4652 DECODE_PRINTF("\n");
4653 TRACE_AND_STEP();
4654 idiv_word(destval);
4655 break;
4656 }
4657 }
Jason Jina63ce952007-07-06 08:34:56 +08004658
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004659 } else { /* mod=11 */
Jason Jina63ce952007-07-06 08:34:56 +08004660
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004661 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4662 u32 *destreg;
4663 u32 srcval;
Jason Jina63ce952007-07-06 08:34:56 +08004664
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004665 destreg = DECODE_RM_LONG_REGISTER(rl);
Jason Jina63ce952007-07-06 08:34:56 +08004666
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004667 switch (rh) {
4668 case 0: /* test word imm */
4669 DECODE_PRINTF(",");
4670 srcval = fetch_long_imm();
4671 DECODE_PRINTF2("%x\n", srcval);
4672 TRACE_AND_STEP();
4673 test_long(*destreg, srcval);
4674 break;
4675 case 1:
4676 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4677 HALT_SYS();
4678 break;
4679 case 2:
4680 DECODE_PRINTF("\n");
4681 TRACE_AND_STEP();
4682 *destreg = not_long(*destreg);
4683 break;
4684 case 3:
4685 DECODE_PRINTF("\n");
4686 TRACE_AND_STEP();
4687 *destreg = neg_long(*destreg);
4688 break;
4689 case 4:
4690 DECODE_PRINTF("\n");
4691 TRACE_AND_STEP();
4692 mul_long(*destreg); /*!!! */
4693 break;
4694 case 5:
4695 DECODE_PRINTF("\n");
4696 TRACE_AND_STEP();
4697 imul_long(*destreg);
4698 break;
4699 case 6:
4700 DECODE_PRINTF("\n");
4701 TRACE_AND_STEP();
4702 div_long(*destreg);
4703 break;
4704 case 7:
4705 DECODE_PRINTF("\n");
4706 TRACE_AND_STEP();
4707 idiv_long(*destreg);
4708 break;
4709 }
4710 } else {
4711 u16 *destreg;
4712 u16 srcval;
Jason Jina63ce952007-07-06 08:34:56 +08004713
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004714 destreg = DECODE_RM_WORD_REGISTER(rl);
Jason Jina63ce952007-07-06 08:34:56 +08004715
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004716 switch (rh) {
4717 case 0: /* test word imm */
4718 DECODE_PRINTF(",");
4719 srcval = fetch_word_imm();
4720 DECODE_PRINTF2("%x\n", srcval);
4721 TRACE_AND_STEP();
4722 test_word(*destreg, srcval);
4723 break;
4724 case 1:
4725 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4726 HALT_SYS();
4727 break;
4728 case 2:
4729 DECODE_PRINTF("\n");
4730 TRACE_AND_STEP();
4731 *destreg = not_word(*destreg);
4732 break;
4733 case 3:
4734 DECODE_PRINTF("\n");
4735 TRACE_AND_STEP();
4736 *destreg = neg_word(*destreg);
4737 break;
4738 case 4:
4739 DECODE_PRINTF("\n");
4740 TRACE_AND_STEP();
4741 mul_word(*destreg); /*!!! */
4742 break;
4743 case 5:
4744 DECODE_PRINTF("\n");
4745 TRACE_AND_STEP();
4746 imul_word(*destreg);
4747 break;
4748 case 6:
4749 DECODE_PRINTF("\n");
4750 TRACE_AND_STEP();
4751 div_word(*destreg);
4752 break;
4753 case 7:
4754 DECODE_PRINTF("\n");
4755 TRACE_AND_STEP();
4756 idiv_word(*destreg);
4757 break;
4758 }
4759 }
Jason Jina63ce952007-07-06 08:34:56 +08004760 }
4761 DECODE_CLEAR_SEGOVR();
4762 END_OF_INSTR();
4763}
4764
4765/****************************************************************************
4766REMARKS:
4767Handles opcode 0xf8
4768****************************************************************************/
4769void x86emuOp_clc(u8 X86EMU_UNUSED(op1))
4770{
4771 /* clear the carry flag. */
4772 START_OF_INSTR();
4773 DECODE_PRINTF("CLC\n");
4774 TRACE_AND_STEP();
4775 CLEAR_FLAG(F_CF);
4776 DECODE_CLEAR_SEGOVR();
4777 END_OF_INSTR();
4778}
4779
4780/****************************************************************************
4781REMARKS:
4782Handles opcode 0xf9
4783****************************************************************************/
4784void x86emuOp_stc(u8 X86EMU_UNUSED(op1))
4785{
4786 /* set the carry flag. */
4787 START_OF_INSTR();
4788 DECODE_PRINTF("STC\n");
4789 TRACE_AND_STEP();
4790 SET_FLAG(F_CF);
4791 DECODE_CLEAR_SEGOVR();
4792 END_OF_INSTR();
4793}
4794
4795/****************************************************************************
4796REMARKS:
4797Handles opcode 0xfa
4798****************************************************************************/
4799void x86emuOp_cli(u8 X86EMU_UNUSED(op1))
4800{
4801 /* clear interrupts. */
4802 START_OF_INSTR();
4803 DECODE_PRINTF("CLI\n");
4804 TRACE_AND_STEP();
4805 CLEAR_FLAG(F_IF);
4806 DECODE_CLEAR_SEGOVR();
4807 END_OF_INSTR();
4808}
4809
4810/****************************************************************************
4811REMARKS:
4812Handles opcode 0xfb
4813****************************************************************************/
4814void x86emuOp_sti(u8 X86EMU_UNUSED(op1))
4815{
4816 /* enable interrupts. */
4817 START_OF_INSTR();
4818 DECODE_PRINTF("STI\n");
4819 TRACE_AND_STEP();
4820 SET_FLAG(F_IF);
4821 DECODE_CLEAR_SEGOVR();
4822 END_OF_INSTR();
4823}
4824
4825/****************************************************************************
4826REMARKS:
4827Handles opcode 0xfc
4828****************************************************************************/
4829void x86emuOp_cld(u8 X86EMU_UNUSED(op1))
4830{
4831 /* clear interrupts. */
4832 START_OF_INSTR();
4833 DECODE_PRINTF("CLD\n");
4834 TRACE_AND_STEP();
4835 CLEAR_FLAG(F_DF);
4836 DECODE_CLEAR_SEGOVR();
4837 END_OF_INSTR();
4838}
4839
4840/****************************************************************************
4841REMARKS:
4842Handles opcode 0xfd
4843****************************************************************************/
4844void x86emuOp_std(u8 X86EMU_UNUSED(op1))
4845{
4846 /* clear interrupts. */
4847 START_OF_INSTR();
4848 DECODE_PRINTF("STD\n");
4849 TRACE_AND_STEP();
4850 SET_FLAG(F_DF);
4851 DECODE_CLEAR_SEGOVR();
4852 END_OF_INSTR();
4853}
4854
4855/****************************************************************************
4856REMARKS:
4857Handles opcode 0xfe
4858****************************************************************************/
4859void x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1))
4860{
4861 int mod, rh, rl;
4862 u8 destval;
4863 uint destoffset;
4864 u8 *destreg;
4865
4866 /* Yet another special case instruction. */
4867 START_OF_INSTR();
4868 FETCH_DECODE_MODRM(mod, rh, rl);
4869#ifdef DEBUG
4870 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004871 /* XXX DECODE_PRINTF may be changed to something more
4872 general, so that it is important to leave the strings
4873 in the same format, even though the result is that the
4874 above test is done twice. */
Jason Jina63ce952007-07-06 08:34:56 +08004875
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004876 switch (rh) {
4877 case 0:
4878 DECODE_PRINTF("INC\t");
4879 break;
4880 case 1:
4881 DECODE_PRINTF("DEC\t");
4882 break;
4883 case 2:
4884 case 3:
4885 case 4:
4886 case 5:
4887 case 6:
4888 case 7:
4889 DECODE_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x \n", mod);
4890 HALT_SYS();
4891 break;
4892 }
Jason Jina63ce952007-07-06 08:34:56 +08004893 }
4894#endif
4895 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004896 DECODE_PRINTF("BYTE PTR ");
4897 destoffset = decode_rmXX_address(mod, rl);
4898 DECODE_PRINTF("\n");
4899 destval = fetch_data_byte(destoffset);
4900 TRACE_AND_STEP();
4901 if (rh == 0)
4902 destval = inc_byte(destval);
4903 else
4904 destval = dec_byte(destval);
4905 store_data_byte(destoffset, destval);
Jason Jina63ce952007-07-06 08:34:56 +08004906 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004907 destreg = DECODE_RM_BYTE_REGISTER(rl);
4908 DECODE_PRINTF("\n");
4909 TRACE_AND_STEP();
4910 if (rh == 0)
4911 *destreg = inc_byte(*destreg);
4912 else
4913 *destreg = dec_byte(*destreg);
Jason Jina63ce952007-07-06 08:34:56 +08004914 }
4915 DECODE_CLEAR_SEGOVR();
4916 END_OF_INSTR();
4917}
4918
4919/****************************************************************************
4920REMARKS:
4921Handles opcode 0xff
4922****************************************************************************/
4923void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1))
4924{
4925 int mod, rh, rl;
4926 uint destoffset = 0;
4927 u16 *destreg;
4928 u16 destval,destval2;
4929
4930 /* Yet another special case instruction. */
4931 START_OF_INSTR();
4932 FETCH_DECODE_MODRM(mod, rh, rl);
4933#ifdef DEBUG
4934 if (DEBUG_DECODE()) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004935 /* XXX DECODE_PRINTF may be changed to something more
4936 general, so that it is important to leave the strings
4937 in the same format, even though the result is that the
4938 above test is done twice. */
Jason Jina63ce952007-07-06 08:34:56 +08004939
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004940 switch (rh) {
4941 case 0:
4942 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4943 DECODE_PRINTF("INC\tDWORD PTR ");
4944 } else {
4945 DECODE_PRINTF("INC\tWORD PTR ");
4946 }
4947 break;
4948 case 1:
4949 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4950 DECODE_PRINTF("DEC\tDWORD PTR ");
4951 } else {
4952 DECODE_PRINTF("DEC\tWORD PTR ");
4953 }
4954 break;
4955 case 2:
4956 DECODE_PRINTF("CALL\t ");
4957 break;
4958 case 3:
4959 DECODE_PRINTF("CALL\tFAR ");
4960 break;
4961 case 4:
4962 DECODE_PRINTF("JMP\t");
4963 break;
4964 case 5:
4965 DECODE_PRINTF("JMP\tFAR ");
4966 break;
4967 case 6:
4968 DECODE_PRINTF("PUSH\t");
4969 break;
4970 case 7:
4971 DECODE_PRINTF("ILLEGAL DECODING OF OPCODE FF\t");
4972 HALT_SYS();
4973 break;
4974 }
Jason Jina63ce952007-07-06 08:34:56 +08004975 }
4976#endif
4977 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004978 destoffset = decode_rmXX_address(mod, rl);
4979 DECODE_PRINTF("\n");
4980 switch (rh) {
4981 case 0: /* inc word ptr ... */
4982 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4983 u32 destval;
Jason Jina63ce952007-07-06 08:34:56 +08004984
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004985 destval = fetch_data_long(destoffset);
4986 TRACE_AND_STEP();
4987 destval = inc_long(destval);
4988 store_data_long(destoffset, destval);
4989 } else {
4990 u16 destval;
Jason Jina63ce952007-07-06 08:34:56 +08004991
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02004992 destval = fetch_data_word(destoffset);
4993 TRACE_AND_STEP();
4994 destval = inc_word(destval);
4995 store_data_word(destoffset, destval);
4996 }
4997 break;
4998 case 1: /* dec word ptr ... */
4999 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5000 u32 destval;
Jason Jina63ce952007-07-06 08:34:56 +08005001
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005002 destval = fetch_data_long(destoffset);
5003 TRACE_AND_STEP();
5004 destval = dec_long(destval);
5005 store_data_long(destoffset, destval);
5006 } else {
5007 u16 destval;
Jason Jina63ce952007-07-06 08:34:56 +08005008
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005009 destval = fetch_data_word(destoffset);
5010 TRACE_AND_STEP();
5011 destval = dec_word(destval);
5012 store_data_word(destoffset, destval);
5013 }
5014 break;
5015 case 2: /* call word ptr ... */
5016 destval = fetch_data_word(destoffset);
5017 TRACE_AND_STEP();
5018 push_word(M.x86.R_IP);
5019 M.x86.R_IP = destval;
5020 break;
5021 case 3: /* call far ptr ... */
5022 destval = fetch_data_word(destoffset);
5023 destval2 = fetch_data_word(destoffset + 2);
5024 TRACE_AND_STEP();
5025 push_word(M.x86.R_CS);
5026 M.x86.R_CS = destval2;
5027 push_word(M.x86.R_IP);
5028 M.x86.R_IP = destval;
5029 break;
5030 case 4: /* jmp word ptr ... */
5031 destval = fetch_data_word(destoffset);
5032 TRACE_AND_STEP();
5033 M.x86.R_IP = destval;
5034 break;
5035 case 5: /* jmp far ptr ... */
5036 destval = fetch_data_word(destoffset);
5037 destval2 = fetch_data_word(destoffset + 2);
5038 TRACE_AND_STEP();
5039 M.x86.R_IP = destval;
5040 M.x86.R_CS = destval2;
5041 break;
5042 case 6: /* push word ptr ... */
5043 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5044 u32 destval;
Jason Jina63ce952007-07-06 08:34:56 +08005045
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005046 destval = fetch_data_long(destoffset);
5047 TRACE_AND_STEP();
5048 push_long(destval);
5049 } else {
5050 u16 destval;
Jason Jina63ce952007-07-06 08:34:56 +08005051
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005052 destval = fetch_data_word(destoffset);
5053 TRACE_AND_STEP();
5054 push_word(destval);
5055 }
5056 break;
5057 }
Jason Jina63ce952007-07-06 08:34:56 +08005058 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005059 switch (rh) {
5060 case 0:
5061 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5062 u32 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08005063
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005064 destreg = DECODE_RM_LONG_REGISTER(rl);
5065 DECODE_PRINTF("\n");
5066 TRACE_AND_STEP();
5067 *destreg = inc_long(*destreg);
5068 } else {
5069 u16 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08005070
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005071 destreg = DECODE_RM_WORD_REGISTER(rl);
5072 DECODE_PRINTF("\n");
5073 TRACE_AND_STEP();
5074 *destreg = inc_word(*destreg);
5075 }
5076 break;
5077 case 1:
5078 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5079 u32 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08005080
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005081 destreg = DECODE_RM_LONG_REGISTER(rl);
5082 DECODE_PRINTF("\n");
5083 TRACE_AND_STEP();
5084 *destreg = dec_long(*destreg);
5085 } else {
5086 u16 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08005087
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005088 destreg = DECODE_RM_WORD_REGISTER(rl);
5089 DECODE_PRINTF("\n");
5090 TRACE_AND_STEP();
5091 *destreg = dec_word(*destreg);
5092 }
5093 break;
5094 case 2: /* call word ptr ... */
5095 destreg = DECODE_RM_WORD_REGISTER(rl);
5096 DECODE_PRINTF("\n");
5097 TRACE_AND_STEP();
5098 push_word(M.x86.R_IP);
5099 M.x86.R_IP = *destreg;
5100 break;
5101 case 3: /* jmp far ptr ... */
5102 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5103 TRACE_AND_STEP();
5104 HALT_SYS();
5105 break;
Jason Jina63ce952007-07-06 08:34:56 +08005106
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005107 case 4: /* jmp ... */
5108 destreg = DECODE_RM_WORD_REGISTER(rl);
5109 DECODE_PRINTF("\n");
5110 TRACE_AND_STEP();
5111 M.x86.R_IP = (u16) (*destreg);
5112 break;
5113 case 5: /* jmp far ptr ... */
5114 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5115 TRACE_AND_STEP();
5116 HALT_SYS();
5117 break;
5118 case 6:
5119 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5120 u32 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08005121
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005122 destreg = DECODE_RM_LONG_REGISTER(rl);
5123 DECODE_PRINTF("\n");
5124 TRACE_AND_STEP();
5125 push_long(*destreg);
5126 } else {
5127 u16 *destreg;
Jason Jina63ce952007-07-06 08:34:56 +08005128
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005129 destreg = DECODE_RM_WORD_REGISTER(rl);
5130 DECODE_PRINTF("\n");
5131 TRACE_AND_STEP();
5132 push_word(*destreg);
5133 }
5134 break;
5135 }
Jason Jina63ce952007-07-06 08:34:56 +08005136 }
5137 DECODE_CLEAR_SEGOVR();
5138 END_OF_INSTR();
5139}
5140
5141/***************************************************************************
5142 * Single byte operation code table:
5143 **************************************************************************/
Ed Swarthout1cffcde2008-10-09 01:27:18 -05005144void (*x86emu_optab[256])(u8) =
Jason Jina63ce952007-07-06 08:34:56 +08005145{
5146/* 0x00 */ x86emuOp_genop_byte_RM_R,
5147/* 0x01 */ x86emuOp_genop_word_RM_R,
5148/* 0x02 */ x86emuOp_genop_byte_R_RM,
5149/* 0x03 */ x86emuOp_genop_word_R_RM,
5150/* 0x04 */ x86emuOp_genop_byte_AL_IMM,
5151/* 0x05 */ x86emuOp_genop_word_AX_IMM,
5152/* 0x06 */ x86emuOp_push_ES,
5153/* 0x07 */ x86emuOp_pop_ES,
5154
5155/* 0x08 */ x86emuOp_genop_byte_RM_R,
5156/* 0x09 */ x86emuOp_genop_word_RM_R,
5157/* 0x0a */ x86emuOp_genop_byte_R_RM,
5158/* 0x0b */ x86emuOp_genop_word_R_RM,
5159/* 0x0c */ x86emuOp_genop_byte_AL_IMM,
5160/* 0x0d */ x86emuOp_genop_word_AX_IMM,
5161/* 0x0e */ x86emuOp_push_CS,
5162/* 0x0f */ x86emuOp_two_byte,
5163
5164/* 0x10 */ x86emuOp_genop_byte_RM_R,
5165/* 0x11 */ x86emuOp_genop_word_RM_R,
5166/* 0x12 */ x86emuOp_genop_byte_R_RM,
5167/* 0x13 */ x86emuOp_genop_word_R_RM,
5168/* 0x14 */ x86emuOp_genop_byte_AL_IMM,
5169/* 0x15 */ x86emuOp_genop_word_AX_IMM,
5170/* 0x16 */ x86emuOp_push_SS,
5171/* 0x17 */ x86emuOp_pop_SS,
5172
5173/* 0x18 */ x86emuOp_genop_byte_RM_R,
5174/* 0x19 */ x86emuOp_genop_word_RM_R,
5175/* 0x1a */ x86emuOp_genop_byte_R_RM,
5176/* 0x1b */ x86emuOp_genop_word_R_RM,
5177/* 0x1c */ x86emuOp_genop_byte_AL_IMM,
5178/* 0x1d */ x86emuOp_genop_word_AX_IMM,
5179/* 0x1e */ x86emuOp_push_DS,
5180/* 0x1f */ x86emuOp_pop_DS,
5181
5182/* 0x20 */ x86emuOp_genop_byte_RM_R,
5183/* 0x21 */ x86emuOp_genop_word_RM_R,
5184/* 0x22 */ x86emuOp_genop_byte_R_RM,
5185/* 0x23 */ x86emuOp_genop_word_R_RM,
5186/* 0x24 */ x86emuOp_genop_byte_AL_IMM,
5187/* 0x25 */ x86emuOp_genop_word_AX_IMM,
5188/* 0x26 */ x86emuOp_segovr_ES,
5189/* 0x27 */ x86emuOp_daa,
5190
5191/* 0x28 */ x86emuOp_genop_byte_RM_R,
5192/* 0x29 */ x86emuOp_genop_word_RM_R,
5193/* 0x2a */ x86emuOp_genop_byte_R_RM,
5194/* 0x2b */ x86emuOp_genop_word_R_RM,
5195/* 0x2c */ x86emuOp_genop_byte_AL_IMM,
5196/* 0x2d */ x86emuOp_genop_word_AX_IMM,
5197/* 0x2e */ x86emuOp_segovr_CS,
5198/* 0x2f */ x86emuOp_das,
5199
5200/* 0x30 */ x86emuOp_genop_byte_RM_R,
5201/* 0x31 */ x86emuOp_genop_word_RM_R,
5202/* 0x32 */ x86emuOp_genop_byte_R_RM,
5203/* 0x33 */ x86emuOp_genop_word_R_RM,
5204/* 0x34 */ x86emuOp_genop_byte_AL_IMM,
5205/* 0x35 */ x86emuOp_genop_word_AX_IMM,
5206/* 0x36 */ x86emuOp_segovr_SS,
5207/* 0x37 */ x86emuOp_aaa,
5208
5209/* 0x38 */ x86emuOp_genop_byte_RM_R,
5210/* 0x39 */ x86emuOp_genop_word_RM_R,
5211/* 0x3a */ x86emuOp_genop_byte_R_RM,
5212/* 0x3b */ x86emuOp_genop_word_R_RM,
5213/* 0x3c */ x86emuOp_genop_byte_AL_IMM,
5214/* 0x3d */ x86emuOp_genop_word_AX_IMM,
5215/* 0x3e */ x86emuOp_segovr_DS,
5216/* 0x3f */ x86emuOp_aas,
5217
5218/* 0x40 */ x86emuOp_inc_register,
5219/* 0x41 */ x86emuOp_inc_register,
5220/* 0x42 */ x86emuOp_inc_register,
5221/* 0x43 */ x86emuOp_inc_register,
5222/* 0x44 */ x86emuOp_inc_register,
5223/* 0x45 */ x86emuOp_inc_register,
5224/* 0x46 */ x86emuOp_inc_register,
5225/* 0x47 */ x86emuOp_inc_register,
5226
5227/* 0x48 */ x86emuOp_dec_register,
5228/* 0x49 */ x86emuOp_dec_register,
5229/* 0x4a */ x86emuOp_dec_register,
5230/* 0x4b */ x86emuOp_dec_register,
5231/* 0x4c */ x86emuOp_dec_register,
5232/* 0x4d */ x86emuOp_dec_register,
5233/* 0x4e */ x86emuOp_dec_register,
5234/* 0x4f */ x86emuOp_dec_register,
5235
5236/* 0x50 */ x86emuOp_push_register,
5237/* 0x51 */ x86emuOp_push_register,
5238/* 0x52 */ x86emuOp_push_register,
5239/* 0x53 */ x86emuOp_push_register,
5240/* 0x54 */ x86emuOp_push_register,
5241/* 0x55 */ x86emuOp_push_register,
5242/* 0x56 */ x86emuOp_push_register,
5243/* 0x57 */ x86emuOp_push_register,
5244
5245/* 0x58 */ x86emuOp_pop_register,
5246/* 0x59 */ x86emuOp_pop_register,
5247/* 0x5a */ x86emuOp_pop_register,
5248/* 0x5b */ x86emuOp_pop_register,
5249/* 0x5c */ x86emuOp_pop_register,
5250/* 0x5d */ x86emuOp_pop_register,
5251/* 0x5e */ x86emuOp_pop_register,
5252/* 0x5f */ x86emuOp_pop_register,
5253
5254/* 0x60 */ x86emuOp_push_all,
5255/* 0x61 */ x86emuOp_pop_all,
5256/* 0x62 */ x86emuOp_illegal_op, /* bound */
5257/* 0x63 */ x86emuOp_illegal_op, /* arpl */
5258/* 0x64 */ x86emuOp_segovr_FS,
5259/* 0x65 */ x86emuOp_segovr_GS,
5260/* 0x66 */ x86emuOp_prefix_data,
5261/* 0x67 */ x86emuOp_prefix_addr,
5262
5263/* 0x68 */ x86emuOp_push_word_IMM,
5264/* 0x69 */ x86emuOp_imul_word_IMM,
5265/* 0x6a */ x86emuOp_push_byte_IMM,
5266/* 0x6b */ x86emuOp_imul_byte_IMM,
5267/* 0x6c */ x86emuOp_ins_byte,
5268/* 0x6d */ x86emuOp_ins_word,
5269/* 0x6e */ x86emuOp_outs_byte,
5270/* 0x6f */ x86emuOp_outs_word,
5271
5272/* 0x70 */ x86emuOp_jump_near_cond,
5273/* 0x71 */ x86emuOp_jump_near_cond,
5274/* 0x72 */ x86emuOp_jump_near_cond,
5275/* 0x73 */ x86emuOp_jump_near_cond,
5276/* 0x74 */ x86emuOp_jump_near_cond,
5277/* 0x75 */ x86emuOp_jump_near_cond,
5278/* 0x76 */ x86emuOp_jump_near_cond,
5279/* 0x77 */ x86emuOp_jump_near_cond,
5280
5281/* 0x78 */ x86emuOp_jump_near_cond,
5282/* 0x79 */ x86emuOp_jump_near_cond,
5283/* 0x7a */ x86emuOp_jump_near_cond,
5284/* 0x7b */ x86emuOp_jump_near_cond,
5285/* 0x7c */ x86emuOp_jump_near_cond,
5286/* 0x7d */ x86emuOp_jump_near_cond,
5287/* 0x7e */ x86emuOp_jump_near_cond,
5288/* 0x7f */ x86emuOp_jump_near_cond,
5289
5290/* 0x80 */ x86emuOp_opc80_byte_RM_IMM,
5291/* 0x81 */ x86emuOp_opc81_word_RM_IMM,
5292/* 0x82 */ x86emuOp_opc82_byte_RM_IMM,
5293/* 0x83 */ x86emuOp_opc83_word_RM_IMM,
5294/* 0x84 */ x86emuOp_test_byte_RM_R,
5295/* 0x85 */ x86emuOp_test_word_RM_R,
5296/* 0x86 */ x86emuOp_xchg_byte_RM_R,
5297/* 0x87 */ x86emuOp_xchg_word_RM_R,
5298
5299/* 0x88 */ x86emuOp_mov_byte_RM_R,
5300/* 0x89 */ x86emuOp_mov_word_RM_R,
5301/* 0x8a */ x86emuOp_mov_byte_R_RM,
5302/* 0x8b */ x86emuOp_mov_word_R_RM,
5303/* 0x8c */ x86emuOp_mov_word_RM_SR,
5304/* 0x8d */ x86emuOp_lea_word_R_M,
5305/* 0x8e */ x86emuOp_mov_word_SR_RM,
5306/* 0x8f */ x86emuOp_pop_RM,
5307
5308/* 0x90 */ x86emuOp_nop,
5309/* 0x91 */ x86emuOp_xchg_word_AX_register,
5310/* 0x92 */ x86emuOp_xchg_word_AX_register,
5311/* 0x93 */ x86emuOp_xchg_word_AX_register,
5312/* 0x94 */ x86emuOp_xchg_word_AX_register,
5313/* 0x95 */ x86emuOp_xchg_word_AX_register,
5314/* 0x96 */ x86emuOp_xchg_word_AX_register,
5315/* 0x97 */ x86emuOp_xchg_word_AX_register,
5316
5317/* 0x98 */ x86emuOp_cbw,
5318/* 0x99 */ x86emuOp_cwd,
5319/* 0x9a */ x86emuOp_call_far_IMM,
5320/* 0x9b */ x86emuOp_wait,
5321/* 0x9c */ x86emuOp_pushf_word,
5322/* 0x9d */ x86emuOp_popf_word,
5323/* 0x9e */ x86emuOp_sahf,
5324/* 0x9f */ x86emuOp_lahf,
5325
5326/* 0xa0 */ x86emuOp_mov_AL_M_IMM,
5327/* 0xa1 */ x86emuOp_mov_AX_M_IMM,
5328/* 0xa2 */ x86emuOp_mov_M_AL_IMM,
5329/* 0xa3 */ x86emuOp_mov_M_AX_IMM,
5330/* 0xa4 */ x86emuOp_movs_byte,
5331/* 0xa5 */ x86emuOp_movs_word,
5332/* 0xa6 */ x86emuOp_cmps_byte,
5333/* 0xa7 */ x86emuOp_cmps_word,
5334/* 0xa8 */ x86emuOp_test_AL_IMM,
5335/* 0xa9 */ x86emuOp_test_AX_IMM,
5336/* 0xaa */ x86emuOp_stos_byte,
5337/* 0xab */ x86emuOp_stos_word,
5338/* 0xac */ x86emuOp_lods_byte,
5339/* 0xad */ x86emuOp_lods_word,
5340/* 0xac */ x86emuOp_scas_byte,
5341/* 0xad */ x86emuOp_scas_word,
5342
5343/* 0xb0 */ x86emuOp_mov_byte_register_IMM,
5344/* 0xb1 */ x86emuOp_mov_byte_register_IMM,
5345/* 0xb2 */ x86emuOp_mov_byte_register_IMM,
5346/* 0xb3 */ x86emuOp_mov_byte_register_IMM,
5347/* 0xb4 */ x86emuOp_mov_byte_register_IMM,
5348/* 0xb5 */ x86emuOp_mov_byte_register_IMM,
5349/* 0xb6 */ x86emuOp_mov_byte_register_IMM,
5350/* 0xb7 */ x86emuOp_mov_byte_register_IMM,
5351
5352/* 0xb8 */ x86emuOp_mov_word_register_IMM,
5353/* 0xb9 */ x86emuOp_mov_word_register_IMM,
5354/* 0xba */ x86emuOp_mov_word_register_IMM,
5355/* 0xbb */ x86emuOp_mov_word_register_IMM,
5356/* 0xbc */ x86emuOp_mov_word_register_IMM,
5357/* 0xbd */ x86emuOp_mov_word_register_IMM,
5358/* 0xbe */ x86emuOp_mov_word_register_IMM,
5359/* 0xbf */ x86emuOp_mov_word_register_IMM,
5360
5361/* 0xc0 */ x86emuOp_opcC0_byte_RM_MEM,
5362/* 0xc1 */ x86emuOp_opcC1_word_RM_MEM,
5363/* 0xc2 */ x86emuOp_ret_near_IMM,
5364/* 0xc3 */ x86emuOp_ret_near,
5365/* 0xc4 */ x86emuOp_les_R_IMM,
5366/* 0xc5 */ x86emuOp_lds_R_IMM,
5367/* 0xc6 */ x86emuOp_mov_byte_RM_IMM,
5368/* 0xc7 */ x86emuOp_mov_word_RM_IMM,
5369/* 0xc8 */ x86emuOp_enter,
5370/* 0xc9 */ x86emuOp_leave,
5371/* 0xca */ x86emuOp_ret_far_IMM,
5372/* 0xcb */ x86emuOp_ret_far,
5373/* 0xcc */ x86emuOp_int3,
5374/* 0xcd */ x86emuOp_int_IMM,
5375/* 0xce */ x86emuOp_into,
5376/* 0xcf */ x86emuOp_iret,
5377
5378/* 0xd0 */ x86emuOp_opcD0_byte_RM_1,
5379/* 0xd1 */ x86emuOp_opcD1_word_RM_1,
5380/* 0xd2 */ x86emuOp_opcD2_byte_RM_CL,
5381/* 0xd3 */ x86emuOp_opcD3_word_RM_CL,
5382/* 0xd4 */ x86emuOp_aam,
5383/* 0xd5 */ x86emuOp_aad,
5384/* 0xd6 */ x86emuOp_illegal_op, /* Undocumented SETALC instruction */
5385/* 0xd7 */ x86emuOp_xlat,
5386/* 0xd8 */ NULL, /*x86emuOp_esc_coprocess_d8,*/
5387/* 0xd9 */ NULL, /*x86emuOp_esc_coprocess_d9,*/
5388/* 0xda */ NULL, /*x86emuOp_esc_coprocess_da,*/
5389/* 0xdb */ NULL, /*x86emuOp_esc_coprocess_db,*/
5390/* 0xdc */ NULL, /*x86emuOp_esc_coprocess_dc,*/
5391/* 0xdd */ NULL, /*x86emuOp_esc_coprocess_dd,*/
5392/* 0xde */ NULL, /*x86emuOp_esc_coprocess_de,*/
5393/* 0xdf */ NULL, /*x86emuOp_esc_coprocess_df,*/
5394
5395/* 0xe0 */ x86emuOp_loopne,
5396/* 0xe1 */ x86emuOp_loope,
5397/* 0xe2 */ x86emuOp_loop,
5398/* 0xe3 */ x86emuOp_jcxz,
5399/* 0xe4 */ x86emuOp_in_byte_AL_IMM,
5400/* 0xe5 */ x86emuOp_in_word_AX_IMM,
5401/* 0xe6 */ x86emuOp_out_byte_IMM_AL,
5402/* 0xe7 */ x86emuOp_out_word_IMM_AX,
5403
5404/* 0xe8 */ x86emuOp_call_near_IMM,
5405/* 0xe9 */ x86emuOp_jump_near_IMM,
5406/* 0xea */ x86emuOp_jump_far_IMM,
5407/* 0xeb */ x86emuOp_jump_byte_IMM,
5408/* 0xec */ x86emuOp_in_byte_AL_DX,
5409/* 0xed */ x86emuOp_in_word_AX_DX,
5410/* 0xee */ x86emuOp_out_byte_DX_AL,
5411/* 0xef */ x86emuOp_out_word_DX_AX,
5412
5413/* 0xf0 */ x86emuOp_lock,
5414/* 0xf1 */ x86emuOp_illegal_op,
5415/* 0xf2 */ x86emuOp_repne,
5416/* 0xf3 */ x86emuOp_repe,
5417/* 0xf4 */ x86emuOp_halt,
5418/* 0xf5 */ x86emuOp_cmc,
5419/* 0xf6 */ x86emuOp_opcF6_byte_RM,
5420/* 0xf7 */ x86emuOp_opcF7_word_RM,
5421
5422/* 0xf8 */ x86emuOp_clc,
5423/* 0xf9 */ x86emuOp_stc,
5424/* 0xfa */ x86emuOp_cli,
5425/* 0xfb */ x86emuOp_sti,
5426/* 0xfc */ x86emuOp_cld,
5427/* 0xfd */ x86emuOp_std,
5428/* 0xfe */ x86emuOp_opcFE_byte_RM,
5429/* 0xff */ x86emuOp_opcFF_word_RM,
5430};