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