blob: c66da95760632f16db466ca4eac0024a30020ffa [file] [log] [blame]
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001/****************************************************************************
2*
3* Realmode X86 Emulator Library
4*
5* Copyright (C) 1991-2004 SciTech Software, Inc.
6* Copyright (C) David Mosberger-Tang
7* Copyright (C) 1999 Egbert Eich
8*
9* ========================================================================
10*
11* Permission to use, copy, modify, distribute, and sell this software and
12* its documentation for any purpose is hereby granted without fee,
13* provided that the above copyright notice appear in all copies and that
14* both that copyright notice and this permission notice appear in
15* supporting documentation, and that the name of the authors not be used
16* in advertising or publicity pertaining to distribution of the software
17* without specific, written prior permission. The authors makes no
18* representations about the suitability of this software for any purpose.
19* It is provided "as is" without express or implied warranty.
20*
21* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
22* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
23* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
24* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
25* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
26* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
27* PERFORMANCE OF THIS SOFTWARE.
28*
29* ========================================================================
30*
31* Language: ANSI C
32* Environment: Any
33* Developer: Kendall Bennett
34*
35* Description: This file includes subroutines to implement the decoding
36* and emulation of all the x86 processor instructions.
37*
38* There are approximately 250 subroutines in here, which correspond
39* to the 256 byte-"opcodes" found on the 8086. The table which
40* dispatches this is found in the files optab.[ch].
41*
42* Each opcode proc has a comment preceeding it which gives it's table
43* address. Several opcodes are missing (undefined) in the table.
44*
45* Each proc includes information for decoding (DECODE_PRINTF and
46* DECODE_PRINTF2), debugging (TRACE_REGS, SINGLE_STEP), and misc
47* functions (START_OF_INSTR, END_OF_INSTR).
48*
49* Many of the procedures are *VERY* similar in coding. This has
50* allowed for a very large amount of code to be generated in a fairly
51* short amount of time (i.e. cut, paste, and modify). The result is
52* that much of the code below could have been folded into subroutines
53* for a large reduction in size of this file. The downside would be
54* that there would be a penalty in execution speed. The file could
55* also have been *MUCH* larger by inlining certain functions which
56* were called. This could have resulted even faster execution. The
57* prime directive I used to decide whether to inline the code or to
58* modularize it, was basically: 1) no unnecessary subroutine calls,
59* 2) no routines more than about 200 lines in size, and 3) modularize
60* any code that I might not get right the first time. The fetch_*
61* subroutines fall into the latter category. The The decode_* fall
62* into the second category. The coding of the "switch(mod){ .... }"
63* in many of the subroutines below falls into the first category.
64* Especially, the coding of {add,and,or,sub,...}_{byte,word}
65* subroutines are an especially glaring case of the third guideline.
66* Since so much of the code is cloned from other modules (compare
67* opcode #00 to opcode #01), making the basic operations subroutine
68* calls is especially important; otherwise mistakes in coding an
69* "add" would represent a nightmare in maintenance.
70*
71****************************************************************************/
72
73#include "x86emui.h"
74
75/*----------------------------- Implementation ----------------------------*/
76
77/* constant arrays to do several instructions in just one function */
78
Myles Watson8e9234f2010-02-19 19:08:11 +000079#ifdef DEBUG
Uwe Hermann01ce6012010-03-05 10:03:50 +000080static const char *x86emu_GenOpName[8] = {
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000081 "ADD", "OR", "ADC", "SBB", "AND", "SUB", "XOR", "CMP"};
82#endif
83
84/* used by several opcodes */
85static u8 (*genop_byte_operation[])(u8 d, u8 s) =
86{
87 add_byte, /* 00 */
88 or_byte, /* 01 */
89 adc_byte, /* 02 */
90 sbb_byte, /* 03 */
91 and_byte, /* 04 */
92 sub_byte, /* 05 */
93 xor_byte, /* 06 */
94 cmp_byte, /* 07 */
95};
96
97static u16 (*genop_word_operation[])(u16 d, u16 s) =
98{
99 add_word, /*00 */
100 or_word, /*01 */
101 adc_word, /*02 */
102 sbb_word, /*03 */
103 and_word, /*04 */
104 sub_word, /*05 */
105 xor_word, /*06 */
106 cmp_word, /*07 */
107};
108
109static u32 (*genop_long_operation[])(u32 d, u32 s) =
110{
111 add_long, /*00 */
112 or_long, /*01 */
113 adc_long, /*02 */
114 sbb_long, /*03 */
115 and_long, /*04 */
116 sub_long, /*05 */
117 xor_long, /*06 */
118 cmp_long, /*07 */
119};
120
121/* used by opcodes 80, c0, d0, and d2. */
122static u8(*opcD0_byte_operation[])(u8 d, u8 s) =
123{
124 rol_byte,
125 ror_byte,
126 rcl_byte,
127 rcr_byte,
128 shl_byte,
129 shr_byte,
130 shl_byte, /* sal_byte === shl_byte by definition */
131 sar_byte,
132};
133
134/* used by opcodes c1, d1, and d3. */
135static u16(*opcD1_word_operation[])(u16 s, u8 d) =
136{
137 rol_word,
138 ror_word,
139 rcl_word,
140 rcr_word,
141 shl_word,
142 shr_word,
143 shl_word, /* sal_byte === shl_byte by definition */
144 sar_word,
145};
146
147/* used by opcodes c1, d1, and d3. */
148static u32 (*opcD1_long_operation[])(u32 s, u8 d) =
149{
150 rol_long,
151 ror_long,
152 rcl_long,
153 rcr_long,
154 shl_long,
155 shr_long,
156 shl_long, /* sal_byte === shl_byte by definition */
157 sar_long,
158};
159
Myles Watson8e9234f2010-02-19 19:08:11 +0000160#ifdef DEBUG
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000161
Uwe Hermann01ce6012010-03-05 10:03:50 +0000162static const char *opF6_names[8] =
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000163 { "TEST\t", "", "NOT\t", "NEG\t", "MUL\t", "IMUL\t", "DIV\t", "IDIV\t" };
164
165#endif
166
167/****************************************************************************
168PARAMETERS:
169op1 - Instruction op code
170
171REMARKS:
172Handles illegal opcodes.
173****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000174static void x86emuOp_illegal_op(
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000175 u8 op1)
176{
177 START_OF_INSTR();
178 if (M.x86.R_SP != 0) {
179 DECODE_PRINTF("ILLEGAL X86 OPCODE\n");
180 TRACE_REGS();
Uwe Hermann01ce6012010-03-05 10:03:50 +0000181 DB( printf("%04x:%04x: %02X ILLEGAL X86 OPCODE!\n",
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000182 M.x86.R_CS, M.x86.R_IP-1,op1));
183 HALT_SYS();
184 }
185 else {
186 /* If we get here, it means the stack pointer is back to zero
187 * so we are just returning from an emulator service call
188 * so therte is no need to display an error message. We trap
189 * the emulator with an 0xF1 opcode to finish the service
190 * call.
191 */
192 X86EMU_halt_sys();
193 }
194 END_OF_INSTR();
195}
196
197/****************************************************************************
198REMARKS:
199Handles opcodes 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38
200****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000201static void x86emuOp_genop_byte_RM_R(u8 op1)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000202{
203 int mod, rl, rh;
204 uint destoffset;
205 u8 *destreg, *srcreg;
206 u8 destval;
207
208 op1 = (op1 >> 3) & 0x7;
209
210 START_OF_INSTR();
211 DECODE_PRINTF(x86emu_GenOpName[op1]);
212 DECODE_PRINTF("\t");
213 FETCH_DECODE_MODRM(mod, rh, rl);
214 if(mod<3)
215 { destoffset = decode_rmXX_address(mod,rl);
216 DECODE_PRINTF(",");
217 destval = fetch_data_byte(destoffset);
218 srcreg = DECODE_RM_BYTE_REGISTER(rh);
219 DECODE_PRINTF("\n");
220 TRACE_AND_STEP();
221 destval = genop_byte_operation[op1](destval, *srcreg);
222 if (op1 != 7)
223 store_data_byte(destoffset, destval);
224 }
225 else
226 { /* register to register */
227 destreg = DECODE_RM_BYTE_REGISTER(rl);
228 DECODE_PRINTF(",");
229 srcreg = DECODE_RM_BYTE_REGISTER(rh);
230 DECODE_PRINTF("\n");
231 TRACE_AND_STEP();
232 *destreg = genop_byte_operation[op1](*destreg, *srcreg);
233 }
234 DECODE_CLEAR_SEGOVR();
235 END_OF_INSTR();
236}
237
238/****************************************************************************
239REMARKS:
240Handles opcodes 0x01, 0x09, 0x11, 0x19, 0x21, 0x29, 0x31, 0x39
241****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000242static void x86emuOp_genop_word_RM_R(u8 op1)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000243{
244 int mod, rl, rh;
245 uint destoffset;
246
247 op1 = (op1 >> 3) & 0x7;
248
249 START_OF_INSTR();
250 DECODE_PRINTF(x86emu_GenOpName[op1]);
251 DECODE_PRINTF("\t");
252 FETCH_DECODE_MODRM(mod, rh, rl);
253
254 if(mod<3) {
255 destoffset = decode_rmXX_address(mod,rl);
256 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
257 u32 destval;
258 u32 *srcreg;
259
260 DECODE_PRINTF(",");
261 destval = fetch_data_long(destoffset);
262 srcreg = DECODE_RM_LONG_REGISTER(rh);
263 DECODE_PRINTF("\n");
264 TRACE_AND_STEP();
265 destval = genop_long_operation[op1](destval, *srcreg);
266 if (op1 != 7)
267 store_data_long(destoffset, destval);
268 } else {
269 u16 destval;
270 u16 *srcreg;
271
272 DECODE_PRINTF(",");
273 destval = fetch_data_word(destoffset);
274 srcreg = DECODE_RM_WORD_REGISTER(rh);
275 DECODE_PRINTF("\n");
276 TRACE_AND_STEP();
277 destval = genop_word_operation[op1](destval, *srcreg);
278 if (op1 != 7)
279 store_data_word(destoffset, destval);
280 }
281 } else { /* register to register */
282 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
283 u32 *destreg, *srcreg;
284
285 destreg = DECODE_RM_LONG_REGISTER(rl);
286 DECODE_PRINTF(",");
287 srcreg = DECODE_RM_LONG_REGISTER(rh);
288 DECODE_PRINTF("\n");
289 TRACE_AND_STEP();
290 *destreg = genop_long_operation[op1](*destreg, *srcreg);
291 } else {
292 u16 *destreg, *srcreg;
293
294 destreg = DECODE_RM_WORD_REGISTER(rl);
295 DECODE_PRINTF(",");
296 srcreg = DECODE_RM_WORD_REGISTER(rh);
297 DECODE_PRINTF("\n");
298 TRACE_AND_STEP();
299 *destreg = genop_word_operation[op1](*destreg, *srcreg);
300 }
301 }
302 DECODE_CLEAR_SEGOVR();
303 END_OF_INSTR();
304}
305
306/****************************************************************************
307REMARKS:
308Handles opcodes 0x02, 0x0a, 0x12, 0x1a, 0x22, 0x2a, 0x32, 0x3a
309****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000310static void x86emuOp_genop_byte_R_RM(u8 op1)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000311{
312 int mod, rl, rh;
313 u8 *destreg, *srcreg;
314 uint srcoffset;
315 u8 srcval;
316
317 op1 = (op1 >> 3) & 0x7;
318
319 START_OF_INSTR();
320 DECODE_PRINTF(x86emu_GenOpName[op1]);
321 DECODE_PRINTF("\t");
322 FETCH_DECODE_MODRM(mod, rh, rl);
323 if (mod < 3) {
324 destreg = DECODE_RM_BYTE_REGISTER(rh);
325 DECODE_PRINTF(",");
326 srcoffset = decode_rmXX_address(mod,rl);
327 srcval = fetch_data_byte(srcoffset);
328 } else { /* register to register */
329 destreg = DECODE_RM_BYTE_REGISTER(rh);
330 DECODE_PRINTF(",");
331 srcreg = DECODE_RM_BYTE_REGISTER(rl);
332 srcval = *srcreg;
333 }
334 DECODE_PRINTF("\n");
335 TRACE_AND_STEP();
336 *destreg = genop_byte_operation[op1](*destreg, srcval);
337
338 DECODE_CLEAR_SEGOVR();
339 END_OF_INSTR();
340}
341
342/****************************************************************************
343REMARKS:
344Handles opcodes 0x03, 0x0b, 0x13, 0x1b, 0x23, 0x2b, 0x33, 0x3b
345****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000346static void x86emuOp_genop_word_R_RM(u8 op1)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000347{
348 int mod, rl, rh;
349 uint srcoffset;
350 u32 *destreg32, srcval;
351 u16 *destreg;
352
353 op1 = (op1 >> 3) & 0x7;
354
355 START_OF_INSTR();
356 DECODE_PRINTF(x86emu_GenOpName[op1]);
357 DECODE_PRINTF("\t");
358 FETCH_DECODE_MODRM(mod, rh, rl);
359 if (mod < 3) {
360 srcoffset = decode_rmXX_address(mod,rl);
361 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
362 destreg32 = DECODE_RM_LONG_REGISTER(rh);
363 DECODE_PRINTF(",");
364 srcval = fetch_data_long(srcoffset);
365 DECODE_PRINTF("\n");
366 TRACE_AND_STEP();
367 *destreg32 = genop_long_operation[op1](*destreg32, srcval);
368 } else {
369 destreg = DECODE_RM_WORD_REGISTER(rh);
370 DECODE_PRINTF(",");
371 srcval = fetch_data_word(srcoffset);
372 DECODE_PRINTF("\n");
373 TRACE_AND_STEP();
374 *destreg = genop_word_operation[op1](*destreg, srcval);
375 }
376 } else { /* register to register */
377 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
378 u32 *srcreg;
379 destreg32 = DECODE_RM_LONG_REGISTER(rh);
380 DECODE_PRINTF(",");
381 srcreg = DECODE_RM_LONG_REGISTER(rl);
382 DECODE_PRINTF("\n");
383 TRACE_AND_STEP();
384 *destreg32 = genop_long_operation[op1](*destreg32, *srcreg);
385 } else {
386 u16 *srcreg;
387 destreg = DECODE_RM_WORD_REGISTER(rh);
388 DECODE_PRINTF(",");
389 srcreg = DECODE_RM_WORD_REGISTER(rl);
390 DECODE_PRINTF("\n");
391 TRACE_AND_STEP();
392 *destreg = genop_word_operation[op1](*destreg, *srcreg);
393 }
394 }
395 DECODE_CLEAR_SEGOVR();
396 END_OF_INSTR();
397}
398
399/****************************************************************************
400REMARKS:
401Handles opcodes 0x04, 0x0c, 0x14, 0x1c, 0x24, 0x2c, 0x34, 0x3c
402****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000403static void x86emuOp_genop_byte_AL_IMM(u8 op1)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000404{
405 u8 srcval;
406
407 op1 = (op1 >> 3) & 0x7;
408
409 START_OF_INSTR();
410 DECODE_PRINTF(x86emu_GenOpName[op1]);
411 DECODE_PRINTF("\tAL,");
412 srcval = fetch_byte_imm();
413 DECODE_PRINTF2("%x\n", srcval);
414 TRACE_AND_STEP();
415 M.x86.R_AL = genop_byte_operation[op1](M.x86.R_AL, srcval);
416 DECODE_CLEAR_SEGOVR();
417 END_OF_INSTR();
418}
419
420/****************************************************************************
421REMARKS:
422Handles opcodes 0x05, 0x0d, 0x15, 0x1d, 0x25, 0x2d, 0x35, 0x3d
423****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000424static void x86emuOp_genop_word_AX_IMM(u8 op1)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000425{
426 u32 srcval;
427
428 op1 = (op1 >> 3) & 0x7;
429
430 START_OF_INSTR();
431 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
432 DECODE_PRINTF(x86emu_GenOpName[op1]);
433 DECODE_PRINTF("\tEAX,");
434 srcval = fetch_long_imm();
435 } else {
436 DECODE_PRINTF(x86emu_GenOpName[op1]);
437 DECODE_PRINTF("\tAX,");
438 srcval = fetch_word_imm();
439 }
440 DECODE_PRINTF2("%x\n", srcval);
441 TRACE_AND_STEP();
442 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
443 M.x86.R_EAX = genop_long_operation[op1](M.x86.R_EAX, srcval);
444 } else {
445 M.x86.R_AX = genop_word_operation[op1](M.x86.R_AX, (u16)srcval);
446 }
447 DECODE_CLEAR_SEGOVR();
448 END_OF_INSTR();
449}
450
451/****************************************************************************
452REMARKS:
453Handles opcode 0x06
454****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000455static void x86emuOp_push_ES(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000456{
457 START_OF_INSTR();
458 DECODE_PRINTF("PUSH\tES\n");
459 TRACE_AND_STEP();
460 push_word(M.x86.R_ES);
461 DECODE_CLEAR_SEGOVR();
462 END_OF_INSTR();
463}
464
465/****************************************************************************
466REMARKS:
467Handles opcode 0x07
468****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000469static void x86emuOp_pop_ES(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000470{
471 START_OF_INSTR();
472 DECODE_PRINTF("POP\tES\n");
473 TRACE_AND_STEP();
474 M.x86.R_ES = pop_word();
475 DECODE_CLEAR_SEGOVR();
476 END_OF_INSTR();
477}
478
479/****************************************************************************
480REMARKS:
481Handles opcode 0x0e
482****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000483static void x86emuOp_push_CS(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000484{
485 START_OF_INSTR();
486 DECODE_PRINTF("PUSH\tCS\n");
487 TRACE_AND_STEP();
488 push_word(M.x86.R_CS);
489 DECODE_CLEAR_SEGOVR();
490 END_OF_INSTR();
491}
492
493/****************************************************************************
494REMARKS:
495Handles opcode 0x0f. Escape for two-byte opcode (286 or better)
496****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000497static void x86emuOp_two_byte(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000498{
499 u8 op2 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
500 INC_DECODED_INST_LEN(1);
501 (*x86emu_optab2[op2])(op2);
502}
503
504/****************************************************************************
505REMARKS:
506Handles opcode 0x16
507****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000508static void x86emuOp_push_SS(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000509{
510 START_OF_INSTR();
511 DECODE_PRINTF("PUSH\tSS\n");
512 TRACE_AND_STEP();
513 push_word(M.x86.R_SS);
514 DECODE_CLEAR_SEGOVR();
515 END_OF_INSTR();
516}
517
518/****************************************************************************
519REMARKS:
520Handles opcode 0x17
521****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000522static void x86emuOp_pop_SS(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000523{
524 START_OF_INSTR();
525 DECODE_PRINTF("POP\tSS\n");
526 TRACE_AND_STEP();
527 M.x86.R_SS = pop_word();
528 DECODE_CLEAR_SEGOVR();
529 END_OF_INSTR();
530}
531
532/****************************************************************************
533REMARKS:
534Handles opcode 0x1e
535****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000536static void x86emuOp_push_DS(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000537{
538 START_OF_INSTR();
539 DECODE_PRINTF("PUSH\tDS\n");
540 TRACE_AND_STEP();
541 push_word(M.x86.R_DS);
542 DECODE_CLEAR_SEGOVR();
543 END_OF_INSTR();
544}
545
546/****************************************************************************
547REMARKS:
548Handles opcode 0x1f
549****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000550static void x86emuOp_pop_DS(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000551{
552 START_OF_INSTR();
553 DECODE_PRINTF("POP\tDS\n");
554 TRACE_AND_STEP();
555 M.x86.R_DS = pop_word();
556 DECODE_CLEAR_SEGOVR();
557 END_OF_INSTR();
558}
559
560/****************************************************************************
561REMARKS:
562Handles opcode 0x26
563****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000564static void x86emuOp_segovr_ES(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000565{
566 START_OF_INSTR();
567 DECODE_PRINTF("ES:\n");
568 TRACE_AND_STEP();
569 M.x86.mode |= SYSMODE_SEGOVR_ES;
570 /*
571 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
572 * opcode subroutines we do not want to do this.
573 */
574 END_OF_INSTR();
575}
576
577/****************************************************************************
578REMARKS:
579Handles opcode 0x27
580****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000581static void x86emuOp_daa(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000582{
583 START_OF_INSTR();
584 DECODE_PRINTF("DAA\n");
585 TRACE_AND_STEP();
586 M.x86.R_AL = daa_byte(M.x86.R_AL);
587 DECODE_CLEAR_SEGOVR();
588 END_OF_INSTR();
589}
590
591/****************************************************************************
592REMARKS:
593Handles opcode 0x2e
594****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000595static void x86emuOp_segovr_CS(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000596{
597 START_OF_INSTR();
598 DECODE_PRINTF("CS:\n");
599 TRACE_AND_STEP();
600 M.x86.mode |= SYSMODE_SEGOVR_CS;
601 /* note no DECODE_CLEAR_SEGOVR here. */
602 END_OF_INSTR();
603}
604
605/****************************************************************************
606REMARKS:
607Handles opcode 0x2f
608****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000609static void x86emuOp_das(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000610{
611 START_OF_INSTR();
612 DECODE_PRINTF("DAS\n");
613 TRACE_AND_STEP();
614 M.x86.R_AL = das_byte(M.x86.R_AL);
615 DECODE_CLEAR_SEGOVR();
616 END_OF_INSTR();
617}
618
619/****************************************************************************
620REMARKS:
621Handles opcode 0x36
622****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000623static void x86emuOp_segovr_SS(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000624{
625 START_OF_INSTR();
626 DECODE_PRINTF("SS:\n");
627 TRACE_AND_STEP();
628 M.x86.mode |= SYSMODE_SEGOVR_SS;
629 /* no DECODE_CLEAR_SEGOVR ! */
630 END_OF_INSTR();
631}
632
633/****************************************************************************
634REMARKS:
635Handles opcode 0x37
636****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000637static void x86emuOp_aaa(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000638{
639 START_OF_INSTR();
640 DECODE_PRINTF("AAA\n");
641 TRACE_AND_STEP();
642 M.x86.R_AX = aaa_word(M.x86.R_AX);
643 DECODE_CLEAR_SEGOVR();
644 END_OF_INSTR();
645}
646
647/****************************************************************************
648REMARKS:
649Handles opcode 0x3e
650****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000651static void x86emuOp_segovr_DS(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000652{
653 START_OF_INSTR();
654 DECODE_PRINTF("DS:\n");
655 TRACE_AND_STEP();
656 M.x86.mode |= SYSMODE_SEGOVR_DS;
657 /* NO DECODE_CLEAR_SEGOVR! */
658 END_OF_INSTR();
659}
660
661/****************************************************************************
662REMARKS:
663Handles opcode 0x3f
664****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000665static void x86emuOp_aas(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000666{
667 START_OF_INSTR();
668 DECODE_PRINTF("AAS\n");
669 TRACE_AND_STEP();
670 M.x86.R_AX = aas_word(M.x86.R_AX);
671 DECODE_CLEAR_SEGOVR();
672 END_OF_INSTR();
673}
674
675/****************************************************************************
676REMARKS:
677Handles opcode 0x40 - 0x47
678****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000679static void x86emuOp_inc_register(u8 op1)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000680{
681 START_OF_INSTR();
682 op1 &= 0x7;
683 DECODE_PRINTF("INC\t");
684 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
685 u32 *reg;
686 reg = DECODE_RM_LONG_REGISTER(op1);
687 DECODE_PRINTF("\n");
688 TRACE_AND_STEP();
689 *reg = inc_long(*reg);
690 } else {
691 u16 *reg;
692 reg = DECODE_RM_WORD_REGISTER(op1);
693 DECODE_PRINTF("\n");
694 TRACE_AND_STEP();
695 *reg = inc_word(*reg);
696 }
697 DECODE_CLEAR_SEGOVR();
698 END_OF_INSTR();
699}
700
701/****************************************************************************
702REMARKS:
703Handles opcode 0x48 - 0x4F
704****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000705static void x86emuOp_dec_register(u8 op1)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000706{
707 START_OF_INSTR();
708 op1 &= 0x7;
709 DECODE_PRINTF("DEC\t");
710 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
711 u32 *reg;
712 reg = DECODE_RM_LONG_REGISTER(op1);
713 DECODE_PRINTF("\n");
714 TRACE_AND_STEP();
715 *reg = dec_long(*reg);
716 } else {
717 u16 *reg;
718 reg = DECODE_RM_WORD_REGISTER(op1);
719 DECODE_PRINTF("\n");
720 TRACE_AND_STEP();
721 *reg = dec_word(*reg);
722 }
723 DECODE_CLEAR_SEGOVR();
724 END_OF_INSTR();
725}
726
727/****************************************************************************
728REMARKS:
729Handles opcode 0x50 - 0x57
730****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000731static void x86emuOp_push_register(u8 op1)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000732{
733 START_OF_INSTR();
734 op1 &= 0x7;
735 DECODE_PRINTF("PUSH\t");
736 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
737 u32 *reg;
738 reg = DECODE_RM_LONG_REGISTER(op1);
739 DECODE_PRINTF("\n");
740 TRACE_AND_STEP();
741 push_long(*reg);
742 } else {
743 u16 *reg;
744 reg = DECODE_RM_WORD_REGISTER(op1);
745 DECODE_PRINTF("\n");
746 TRACE_AND_STEP();
747 push_word(*reg);
748 }
749 DECODE_CLEAR_SEGOVR();
750 END_OF_INSTR();
751}
752
753/****************************************************************************
754REMARKS:
755Handles opcode 0x58 - 0x5F
756****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000757static void x86emuOp_pop_register(u8 op1)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000758{
759 START_OF_INSTR();
760 op1 &= 0x7;
761 DECODE_PRINTF("POP\t");
762 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
763 u32 *reg;
764 reg = DECODE_RM_LONG_REGISTER(op1);
765 DECODE_PRINTF("\n");
766 TRACE_AND_STEP();
767 *reg = pop_long();
768 } else {
769 u16 *reg;
770 reg = DECODE_RM_WORD_REGISTER(op1);
771 DECODE_PRINTF("\n");
772 TRACE_AND_STEP();
773 *reg = pop_word();
774 }
775 DECODE_CLEAR_SEGOVR();
776 END_OF_INSTR();
777}
778
779/****************************************************************************
780REMARKS:
781Handles opcode 0x60
782****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000783static void x86emuOp_push_all(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000784{
785 START_OF_INSTR();
786 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
787 DECODE_PRINTF("PUSHAD\n");
788 } else {
789 DECODE_PRINTF("PUSHA\n");
790 }
791 TRACE_AND_STEP();
792 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
793 u32 old_sp = M.x86.R_ESP;
794
795 push_long(M.x86.R_EAX);
796 push_long(M.x86.R_ECX);
797 push_long(M.x86.R_EDX);
798 push_long(M.x86.R_EBX);
799 push_long(old_sp);
800 push_long(M.x86.R_EBP);
801 push_long(M.x86.R_ESI);
802 push_long(M.x86.R_EDI);
803 } else {
804 u16 old_sp = M.x86.R_SP;
805
806 push_word(M.x86.R_AX);
807 push_word(M.x86.R_CX);
808 push_word(M.x86.R_DX);
809 push_word(M.x86.R_BX);
810 push_word(old_sp);
811 push_word(M.x86.R_BP);
812 push_word(M.x86.R_SI);
813 push_word(M.x86.R_DI);
814 }
815 DECODE_CLEAR_SEGOVR();
816 END_OF_INSTR();
817}
818
819/****************************************************************************
820REMARKS:
821Handles opcode 0x61
822****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000823static void x86emuOp_pop_all(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000824{
825 START_OF_INSTR();
826 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
827 DECODE_PRINTF("POPAD\n");
828 } else {
829 DECODE_PRINTF("POPA\n");
830 }
831 TRACE_AND_STEP();
832 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
833 M.x86.R_EDI = pop_long();
834 M.x86.R_ESI = pop_long();
835 M.x86.R_EBP = pop_long();
836 M.x86.R_ESP += 4; /* skip ESP */
837 M.x86.R_EBX = pop_long();
838 M.x86.R_EDX = pop_long();
839 M.x86.R_ECX = pop_long();
840 M.x86.R_EAX = pop_long();
841 } else {
842 M.x86.R_DI = pop_word();
843 M.x86.R_SI = pop_word();
844 M.x86.R_BP = pop_word();
845 M.x86.R_SP += 2; /* skip SP */
846 M.x86.R_BX = pop_word();
847 M.x86.R_DX = pop_word();
848 M.x86.R_CX = pop_word();
849 M.x86.R_AX = pop_word();
850 }
851 DECODE_CLEAR_SEGOVR();
852 END_OF_INSTR();
853}
854
855/*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */
856/*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */
857
858/****************************************************************************
859REMARKS:
860Handles opcode 0x64
861****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000862static void x86emuOp_segovr_FS(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000863{
864 START_OF_INSTR();
865 DECODE_PRINTF("FS:\n");
866 TRACE_AND_STEP();
867 M.x86.mode |= SYSMODE_SEGOVR_FS;
868 /*
869 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
870 * opcode subroutines we do not want to do this.
871 */
872 END_OF_INSTR();
873}
874
875/****************************************************************************
876REMARKS:
877Handles opcode 0x65
878****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000879static void x86emuOp_segovr_GS(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000880{
881 START_OF_INSTR();
882 DECODE_PRINTF("GS:\n");
883 TRACE_AND_STEP();
884 M.x86.mode |= SYSMODE_SEGOVR_GS;
885 /*
886 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
887 * opcode subroutines we do not want to do this.
888 */
889 END_OF_INSTR();
890}
891
892/****************************************************************************
893REMARKS:
894Handles opcode 0x66 - prefix for 32-bit register
895****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000896static void x86emuOp_prefix_data(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000897{
898 START_OF_INSTR();
899 DECODE_PRINTF("DATA:\n");
900 TRACE_AND_STEP();
901 M.x86.mode |= SYSMODE_PREFIX_DATA;
902 /* note no DECODE_CLEAR_SEGOVR here. */
903 END_OF_INSTR();
904}
905
906/****************************************************************************
907REMARKS:
908Handles opcode 0x67 - prefix for 32-bit address
909****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000910static void x86emuOp_prefix_addr(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000911{
912 START_OF_INSTR();
913 DECODE_PRINTF("ADDR:\n");
914 TRACE_AND_STEP();
915 M.x86.mode |= SYSMODE_PREFIX_ADDR;
916 /* note no DECODE_CLEAR_SEGOVR here. */
917 END_OF_INSTR();
918}
919
920/****************************************************************************
921REMARKS:
922Handles opcode 0x68
923****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000924static void x86emuOp_push_word_IMM(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000925{
926 u32 imm;
927
928 START_OF_INSTR();
929 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
930 imm = fetch_long_imm();
931 } else {
932 imm = fetch_word_imm();
933 }
934 DECODE_PRINTF2("PUSH\t%x\n", imm);
935 TRACE_AND_STEP();
936 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
937 push_long(imm);
938 } else {
939 push_word((u16)imm);
940 }
941 DECODE_CLEAR_SEGOVR();
942 END_OF_INSTR();
943}
944
945/****************************************************************************
946REMARKS:
947Handles opcode 0x69
948****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000949static void x86emuOp_imul_word_IMM(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000950{
951 int mod, rl, rh;
952 uint srcoffset;
953
954 START_OF_INSTR();
955 DECODE_PRINTF("IMUL\t");
956 FETCH_DECODE_MODRM(mod, rh, rl);
957 if (mod < 3) {
958 srcoffset = decode_rmXX_address(mod, rl);
959 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
960 u32 *destreg;
961 u32 srcval;
962 u32 res_lo,res_hi;
963 s32 imm;
964
965 destreg = DECODE_RM_LONG_REGISTER(rh);
966 DECODE_PRINTF(",");
967 srcval = fetch_data_long(srcoffset);
968 imm = fetch_long_imm();
969 DECODE_PRINTF2(",%d\n", (s32)imm);
970 TRACE_AND_STEP();
971 imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
972 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
973 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
974 CLEAR_FLAG(F_CF);
975 CLEAR_FLAG(F_OF);
976 } else {
977 SET_FLAG(F_CF);
978 SET_FLAG(F_OF);
979 }
980 *destreg = (u32)res_lo;
981 } else {
982 u16 *destreg;
983 u16 srcval;
984 u32 res;
985 s16 imm;
986
987 destreg = DECODE_RM_WORD_REGISTER(rh);
988 DECODE_PRINTF(",");
989 srcval = fetch_data_word(srcoffset);
990 imm = fetch_word_imm();
991 DECODE_PRINTF2(",%d\n", (s32)imm);
992 TRACE_AND_STEP();
993 res = (s16)srcval * (s16)imm;
994 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
995 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
996 CLEAR_FLAG(F_CF);
997 CLEAR_FLAG(F_OF);
998 } else {
999 SET_FLAG(F_CF);
1000 SET_FLAG(F_OF);
1001 }
1002 *destreg = (u16)res;
1003 }
1004 } else { /* register to register */
1005 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1006 u32 *destreg,*srcreg;
1007 u32 res_lo,res_hi;
1008 s32 imm;
1009
1010 destreg = DECODE_RM_LONG_REGISTER(rh);
1011 DECODE_PRINTF(",");
1012 srcreg = DECODE_RM_LONG_REGISTER(rl);
1013 imm = fetch_long_imm();
1014 DECODE_PRINTF2(",%d\n", (s32)imm);
1015 TRACE_AND_STEP();
1016 imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
1017 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1018 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1019 CLEAR_FLAG(F_CF);
1020 CLEAR_FLAG(F_OF);
1021 } else {
1022 SET_FLAG(F_CF);
1023 SET_FLAG(F_OF);
1024 }
1025 *destreg = (u32)res_lo;
1026 } else {
1027 u16 *destreg,*srcreg;
1028 u32 res;
1029 s16 imm;
1030
1031 destreg = DECODE_RM_WORD_REGISTER(rh);
1032 DECODE_PRINTF(",");
1033 srcreg = DECODE_RM_WORD_REGISTER(rl);
1034 imm = fetch_word_imm();
1035 DECODE_PRINTF2(",%d\n", (s32)imm);
1036 res = (s16)*srcreg * (s16)imm;
1037 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1038 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1039 CLEAR_FLAG(F_CF);
1040 CLEAR_FLAG(F_OF);
1041 } else {
1042 SET_FLAG(F_CF);
1043 SET_FLAG(F_OF);
1044 }
1045 *destreg = (u16)res;
1046 }
1047 }
1048 DECODE_CLEAR_SEGOVR();
1049 END_OF_INSTR();
1050}
1051
1052/****************************************************************************
1053REMARKS:
1054Handles opcode 0x6a
1055****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001056static void x86emuOp_push_byte_IMM(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001057{
1058 s16 imm;
1059
1060 START_OF_INSTR();
1061 imm = (s8)fetch_byte_imm();
1062 DECODE_PRINTF2("PUSH\t%d\n", imm);
1063 TRACE_AND_STEP();
1064 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1065 push_long(imm);
1066 } else {
1067 push_word(imm);
1068 }
1069 DECODE_CLEAR_SEGOVR();
1070 END_OF_INSTR();
1071}
1072
1073/****************************************************************************
1074REMARKS:
1075Handles opcode 0x6b
1076****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001077static void x86emuOp_imul_byte_IMM(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001078{
1079 int mod, rl, rh;
1080 uint srcoffset;
1081 s8 imm;
1082
1083 START_OF_INSTR();
1084 DECODE_PRINTF("IMUL\t");
1085 FETCH_DECODE_MODRM(mod, rh, rl);
1086 if (mod < 3) {
1087 srcoffset = decode_rmXX_address(mod, rl);
1088 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1089 u32 *destreg;
1090 u32 srcval;
1091 u32 res_lo,res_hi;
1092
1093 destreg = DECODE_RM_LONG_REGISTER(rh);
1094 DECODE_PRINTF(",");
1095 srcval = fetch_data_long(srcoffset);
1096 imm = fetch_byte_imm();
1097 DECODE_PRINTF2(",%d\n", (s32)imm);
1098 TRACE_AND_STEP();
1099 imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
1100 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1101 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1102 CLEAR_FLAG(F_CF);
1103 CLEAR_FLAG(F_OF);
1104 } else {
1105 SET_FLAG(F_CF);
1106 SET_FLAG(F_OF);
1107 }
1108 *destreg = (u32)res_lo;
1109 } else {
1110 u16 *destreg;
1111 u16 srcval;
1112 u32 res;
1113
1114 destreg = DECODE_RM_WORD_REGISTER(rh);
1115 DECODE_PRINTF(",");
1116 srcval = fetch_data_word(srcoffset);
1117 imm = fetch_byte_imm();
1118 DECODE_PRINTF2(",%d\n", (s32)imm);
1119 TRACE_AND_STEP();
1120 res = (s16)srcval * (s16)imm;
1121 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1122 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1123 CLEAR_FLAG(F_CF);
1124 CLEAR_FLAG(F_OF);
1125 } else {
1126 SET_FLAG(F_CF);
1127 SET_FLAG(F_OF);
1128 }
1129 *destreg = (u16)res;
1130 }
1131 } else { /* register to register */
1132 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1133 u32 *destreg,*srcreg;
1134 u32 res_lo,res_hi;
1135
1136 destreg = DECODE_RM_LONG_REGISTER(rh);
1137 DECODE_PRINTF(",");
1138 srcreg = DECODE_RM_LONG_REGISTER(rl);
1139 imm = fetch_byte_imm();
1140 DECODE_PRINTF2(",%d\n", (s32)imm);
1141 TRACE_AND_STEP();
1142 imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
1143 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1144 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1145 CLEAR_FLAG(F_CF);
1146 CLEAR_FLAG(F_OF);
1147 } else {
1148 SET_FLAG(F_CF);
1149 SET_FLAG(F_OF);
1150 }
1151 *destreg = (u32)res_lo;
1152 } else {
1153 u16 *destreg,*srcreg;
1154 u32 res;
1155
1156 destreg = DECODE_RM_WORD_REGISTER(rh);
1157 DECODE_PRINTF(",");
1158 srcreg = DECODE_RM_WORD_REGISTER(rl);
1159 imm = fetch_byte_imm();
1160 DECODE_PRINTF2(",%d\n", (s32)imm);
1161 TRACE_AND_STEP();
1162 res = (s16)*srcreg * (s16)imm;
1163 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1164 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1165 CLEAR_FLAG(F_CF);
1166 CLEAR_FLAG(F_OF);
1167 } else {
1168 SET_FLAG(F_CF);
1169 SET_FLAG(F_OF);
1170 }
1171 *destreg = (u16)res;
1172 }
1173 }
1174 DECODE_CLEAR_SEGOVR();
1175 END_OF_INSTR();
1176}
1177
1178/****************************************************************************
1179REMARKS:
1180Handles opcode 0x6c
1181****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001182static void x86emuOp_ins_byte(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001183{
1184 START_OF_INSTR();
1185 DECODE_PRINTF("INSB\n");
1186 ins(1);
1187 TRACE_AND_STEP();
1188 DECODE_CLEAR_SEGOVR();
1189 END_OF_INSTR();
1190}
1191
1192/****************************************************************************
1193REMARKS:
1194Handles opcode 0x6d
1195****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001196static void x86emuOp_ins_word(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001197{
1198 START_OF_INSTR();
1199 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1200 DECODE_PRINTF("INSD\n");
1201 ins(4);
1202 } else {
1203 DECODE_PRINTF("INSW\n");
1204 ins(2);
1205 }
1206 TRACE_AND_STEP();
1207 DECODE_CLEAR_SEGOVR();
1208 END_OF_INSTR();
1209}
1210
1211/****************************************************************************
1212REMARKS:
1213Handles opcode 0x6e
1214****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001215static void x86emuOp_outs_byte(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001216{
1217 START_OF_INSTR();
1218 DECODE_PRINTF("OUTSB\n");
1219 outs(1);
1220 TRACE_AND_STEP();
1221 DECODE_CLEAR_SEGOVR();
1222 END_OF_INSTR();
1223}
1224
1225/****************************************************************************
1226REMARKS:
1227Handles opcode 0x6f
1228****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001229static void x86emuOp_outs_word(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001230{
1231 START_OF_INSTR();
1232 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1233 DECODE_PRINTF("OUTSD\n");
1234 outs(4);
1235 } else {
1236 DECODE_PRINTF("OUTSW\n");
1237 outs(2);
1238 }
1239 TRACE_AND_STEP();
1240 DECODE_CLEAR_SEGOVR();
1241 END_OF_INSTR();
1242}
1243
1244/****************************************************************************
1245REMARKS:
1246Handles opcode 0x70 - 0x7F
1247****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001248static void x86emuOp_jump_near_cond(u8 op1)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001249{
1250 s8 offset;
1251 u16 target;
1252 int cond;
1253
1254 /* jump to byte offset if overflow flag is set */
1255 START_OF_INSTR();
1256 cond = x86emu_check_jump_condition(op1 & 0xF);
1257 offset = (s8)fetch_byte_imm();
1258 target = (u16)(M.x86.R_IP + (s16)offset);
1259 DECODE_PRINTF2("%x\n", target);
1260 TRACE_AND_STEP();
1261 if (cond) {
1262 M.x86.R_IP = target;
1263 JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, " NEAR COND ");
1264 }
1265 DECODE_CLEAR_SEGOVR();
1266 END_OF_INSTR();
1267}
1268
1269/****************************************************************************
1270REMARKS:
1271Handles opcode 0x80
1272****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001273static void x86emuOp_opc80_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001274{
1275 int mod, rl, rh;
1276 u8 *destreg;
1277 uint destoffset;
1278 u8 imm;
1279 u8 destval;
1280
1281 /*
1282 * Weirdo special case instruction format. Part of the opcode
1283 * held below in "RH". Doubly nested case would result, except
1284 * that the decoded instruction
1285 */
1286 START_OF_INSTR();
1287 FETCH_DECODE_MODRM(mod, rh, rl);
Myles Watson8e9234f2010-02-19 19:08:11 +00001288#ifdef DEBUG
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001289 if (DEBUG_DECODE()) {
1290 /* XXX DECODE_PRINTF may be changed to something more
1291 general, so that it is important to leave the strings
1292 in the same format, even though the result is that the
1293 above test is done twice. */
1294
1295 switch (rh) {
1296 case 0:
1297 DECODE_PRINTF("ADD\t");
1298 break;
1299 case 1:
1300 DECODE_PRINTF("OR\t");
1301 break;
1302 case 2:
1303 DECODE_PRINTF("ADC\t");
1304 break;
1305 case 3:
1306 DECODE_PRINTF("SBB\t");
1307 break;
1308 case 4:
1309 DECODE_PRINTF("AND\t");
1310 break;
1311 case 5:
1312 DECODE_PRINTF("SUB\t");
1313 break;
1314 case 6:
1315 DECODE_PRINTF("XOR\t");
1316 break;
1317 case 7:
1318 DECODE_PRINTF("CMP\t");
1319 break;
1320 }
1321 }
1322#endif
1323 /* know operation, decode the mod byte to find the addressing
1324 mode. */
1325 if (mod < 3) {
1326 DECODE_PRINTF("BYTE PTR ");
1327 destoffset = decode_rmXX_address(mod, rl);
1328 DECODE_PRINTF(",");
1329 destval = fetch_data_byte(destoffset);
1330 imm = fetch_byte_imm();
1331 DECODE_PRINTF2("%x\n", imm);
1332 TRACE_AND_STEP();
1333 destval = (*genop_byte_operation[rh]) (destval, imm);
1334 if (rh != 7)
1335 store_data_byte(destoffset, destval);
1336 } else { /* register to register */
1337 destreg = DECODE_RM_BYTE_REGISTER(rl);
1338 DECODE_PRINTF(",");
1339 imm = fetch_byte_imm();
1340 DECODE_PRINTF2("%x\n", imm);
1341 TRACE_AND_STEP();
1342 *destreg = (*genop_byte_operation[rh]) (*destreg, imm);
1343 }
1344 DECODE_CLEAR_SEGOVR();
1345 END_OF_INSTR();
1346}
1347
1348/****************************************************************************
1349REMARKS:
1350Handles opcode 0x81
1351****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001352static void x86emuOp_opc81_word_RM_IMM(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001353{
1354 int mod, rl, rh;
1355 uint destoffset;
1356
1357 /*
1358 * Weirdo special case instruction format. Part of the opcode
1359 * held below in "RH". Doubly nested case would result, except
1360 * that the decoded instruction
1361 */
1362 START_OF_INSTR();
1363 FETCH_DECODE_MODRM(mod, rh, rl);
Myles Watson8e9234f2010-02-19 19:08:11 +00001364#ifdef DEBUG
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001365 if (DEBUG_DECODE()) {
1366 /* XXX DECODE_PRINTF may be changed to something more
1367 general, so that it is important to leave the strings
1368 in the same format, even though the result is that the
1369 above test is done twice. */
1370
1371 switch (rh) {
1372 case 0:
1373 DECODE_PRINTF("ADD\t");
1374 break;
1375 case 1:
1376 DECODE_PRINTF("OR\t");
1377 break;
1378 case 2:
1379 DECODE_PRINTF("ADC\t");
1380 break;
1381 case 3:
1382 DECODE_PRINTF("SBB\t");
1383 break;
1384 case 4:
1385 DECODE_PRINTF("AND\t");
1386 break;
1387 case 5:
1388 DECODE_PRINTF("SUB\t");
1389 break;
1390 case 6:
1391 DECODE_PRINTF("XOR\t");
1392 break;
1393 case 7:
1394 DECODE_PRINTF("CMP\t");
1395 break;
1396 }
1397 }
1398#endif
1399 /*
1400 * Know operation, decode the mod byte to find the addressing
1401 * mode.
1402 */
1403 if (mod < 3) {
1404 DECODE_PRINTF("DWORD PTR ");
1405 destoffset = decode_rmXX_address(mod, rl);
1406 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1407 u32 destval,imm;
1408
1409 DECODE_PRINTF(",");
1410 destval = fetch_data_long(destoffset);
1411 imm = fetch_long_imm();
1412 DECODE_PRINTF2("%x\n", imm);
1413 TRACE_AND_STEP();
1414 destval = (*genop_long_operation[rh]) (destval, imm);
1415 if (rh != 7)
1416 store_data_long(destoffset, destval);
1417 } else {
1418 u16 destval,imm;
1419
1420 DECODE_PRINTF(",");
1421 destval = fetch_data_word(destoffset);
1422 imm = fetch_word_imm();
1423 DECODE_PRINTF2("%x\n", imm);
1424 TRACE_AND_STEP();
1425 destval = (*genop_word_operation[rh]) (destval, imm);
1426 if (rh != 7)
1427 store_data_word(destoffset, destval);
1428 }
1429 } else { /* register to register */
1430 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1431 u32 *destreg, imm;
1432
1433 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 *destreg = (*genop_long_operation[rh]) (*destreg, imm);
1439 } else {
1440 u16 *destreg, imm;
1441
1442 destreg = DECODE_RM_WORD_REGISTER(rl);
1443 DECODE_PRINTF(",");
1444 imm = fetch_word_imm();
1445 DECODE_PRINTF2("%x\n", imm);
1446 TRACE_AND_STEP();
1447 *destreg = (*genop_word_operation[rh]) (*destreg, imm);
1448 }
1449 }
1450 DECODE_CLEAR_SEGOVR();
1451 END_OF_INSTR();
1452}
1453
1454/****************************************************************************
1455REMARKS:
1456Handles opcode 0x82
1457****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001458static void x86emuOp_opc82_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001459{
1460 int mod, rl, rh;
1461 u8 *destreg;
1462 uint destoffset;
1463 u8 imm;
1464 u8 destval;
1465
1466 /*
1467 * Weirdo special case instruction format. Part of the opcode
1468 * held below in "RH". Doubly nested case would result, except
1469 * that the decoded instruction Similar to opcode 81, except that
1470 * the immediate byte is sign extended to a word length.
1471 */
1472 START_OF_INSTR();
1473 FETCH_DECODE_MODRM(mod, rh, rl);
Myles Watson8e9234f2010-02-19 19:08:11 +00001474#ifdef DEBUG
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001475 if (DEBUG_DECODE()) {
1476 /* XXX DECODE_PRINTF may be changed to something more
1477 general, so that it is important to leave the strings
1478 in the same format, even though the result is that the
1479 above test is done twice. */
1480 switch (rh) {
1481 case 0:
1482 DECODE_PRINTF("ADD\t");
1483 break;
1484 case 1:
1485 DECODE_PRINTF("OR\t");
1486 break;
1487 case 2:
1488 DECODE_PRINTF("ADC\t");
1489 break;
1490 case 3:
1491 DECODE_PRINTF("SBB\t");
1492 break;
1493 case 4:
1494 DECODE_PRINTF("AND\t");
1495 break;
1496 case 5:
1497 DECODE_PRINTF("SUB\t");
1498 break;
1499 case 6:
1500 DECODE_PRINTF("XOR\t");
1501 break;
1502 case 7:
1503 DECODE_PRINTF("CMP\t");
1504 break;
1505 }
1506 }
1507#endif
1508 /* know operation, decode the mod byte to find the addressing
1509 mode. */
1510 if (mod < 3) {
1511 DECODE_PRINTF("BYTE PTR ");
1512 destoffset = decode_rmXX_address(mod, rl);
1513 destval = fetch_data_byte(destoffset);
1514 imm = fetch_byte_imm();
1515 DECODE_PRINTF2(",%x\n", imm);
1516 TRACE_AND_STEP();
1517 destval = (*genop_byte_operation[rh]) (destval, imm);
1518 if (rh != 7)
1519 store_data_byte(destoffset, destval);
1520 } else { /* register to register */
1521 destreg = DECODE_RM_BYTE_REGISTER(rl);
1522 imm = fetch_byte_imm();
1523 DECODE_PRINTF2(",%x\n", imm);
1524 TRACE_AND_STEP();
1525 *destreg = (*genop_byte_operation[rh]) (*destreg, imm);
1526 }
1527 DECODE_CLEAR_SEGOVR();
1528 END_OF_INSTR();
1529}
1530
1531/****************************************************************************
1532REMARKS:
1533Handles opcode 0x83
1534****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001535static void x86emuOp_opc83_word_RM_IMM(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001536{
1537 int mod, rl, rh;
1538 uint destoffset;
1539
1540 /*
1541 * Weirdo special case instruction format. Part of the opcode
1542 * held below in "RH". Doubly nested case would result, except
1543 * that the decoded instruction Similar to opcode 81, except that
1544 * the immediate byte is sign extended to a word length.
1545 */
1546 START_OF_INSTR();
1547 FETCH_DECODE_MODRM(mod, rh, rl);
Myles Watson8e9234f2010-02-19 19:08:11 +00001548#ifdef DEBUG
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001549 if (DEBUG_DECODE()) {
1550 /* XXX DECODE_PRINTF may be changed to something more
1551 general, so that it is important to leave the strings
1552 in the same format, even though the result is that the
1553 above test is done twice. */
1554 switch (rh) {
1555 case 0:
1556 DECODE_PRINTF("ADD\t");
1557 break;
1558 case 1:
1559 DECODE_PRINTF("OR\t");
1560 break;
1561 case 2:
1562 DECODE_PRINTF("ADC\t");
1563 break;
1564 case 3:
1565 DECODE_PRINTF("SBB\t");
1566 break;
1567 case 4:
1568 DECODE_PRINTF("AND\t");
1569 break;
1570 case 5:
1571 DECODE_PRINTF("SUB\t");
1572 break;
1573 case 6:
1574 DECODE_PRINTF("XOR\t");
1575 break;
1576 case 7:
1577 DECODE_PRINTF("CMP\t");
1578 break;
1579 }
1580 }
1581#endif
1582 /* know operation, decode the mod byte to find the addressing
1583 mode. */
1584 if (mod < 3) {
1585 DECODE_PRINTF("DWORD PTR ");
1586 destoffset = decode_rmXX_address(mod,rl);
1587
1588 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1589 u32 destval,imm;
1590
1591 destval = fetch_data_long(destoffset);
1592 imm = (s8) fetch_byte_imm();
1593 DECODE_PRINTF2(",%x\n", imm);
1594 TRACE_AND_STEP();
1595 destval = (*genop_long_operation[rh]) (destval, imm);
1596 if (rh != 7)
1597 store_data_long(destoffset, destval);
1598 } else {
1599 u16 destval,imm;
1600
1601 destval = fetch_data_word(destoffset);
1602 imm = (s8) fetch_byte_imm();
1603 DECODE_PRINTF2(",%x\n", imm);
1604 TRACE_AND_STEP();
1605 destval = (*genop_word_operation[rh]) (destval, imm);
1606 if (rh != 7)
1607 store_data_word(destoffset, destval);
1608 }
1609 } else { /* register to register */
1610 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1611 u32 *destreg, imm;
1612
1613 destreg = DECODE_RM_LONG_REGISTER(rl);
1614 imm = (s8) fetch_byte_imm();
1615 DECODE_PRINTF2(",%x\n", imm);
1616 TRACE_AND_STEP();
1617 *destreg = (*genop_long_operation[rh]) (*destreg, imm);
1618 } else {
1619 u16 *destreg, imm;
1620
1621 destreg = DECODE_RM_WORD_REGISTER(rl);
1622 imm = (s8) fetch_byte_imm();
1623 DECODE_PRINTF2(",%x\n", imm);
1624 TRACE_AND_STEP();
1625 *destreg = (*genop_word_operation[rh]) (*destreg, imm);
1626 }
1627 }
1628 DECODE_CLEAR_SEGOVR();
1629 END_OF_INSTR();
1630}
1631
1632/****************************************************************************
1633REMARKS:
1634Handles opcode 0x84
1635****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001636static void x86emuOp_test_byte_RM_R(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001637{
1638 int mod, rl, rh;
1639 u8 *destreg, *srcreg;
1640 uint destoffset;
1641 u8 destval;
1642
1643 START_OF_INSTR();
1644 DECODE_PRINTF("TEST\t");
1645 FETCH_DECODE_MODRM(mod, rh, rl);
1646 if (mod < 3) {
1647 destoffset = decode_rmXX_address(mod, rl);
1648 DECODE_PRINTF(",");
1649 destval = fetch_data_byte(destoffset);
1650 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1651 DECODE_PRINTF("\n");
1652 TRACE_AND_STEP();
1653 test_byte(destval, *srcreg);
1654 } else { /* register to register */
1655 destreg = DECODE_RM_BYTE_REGISTER(rl);
1656 DECODE_PRINTF(",");
1657 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1658 DECODE_PRINTF("\n");
1659 TRACE_AND_STEP();
1660 test_byte(*destreg, *srcreg);
1661 }
1662 DECODE_CLEAR_SEGOVR();
1663 END_OF_INSTR();
1664}
1665
1666/****************************************************************************
1667REMARKS:
1668Handles opcode 0x85
1669****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001670static void x86emuOp_test_word_RM_R(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001671{
1672 int mod, rl, rh;
1673 uint destoffset;
1674
1675 START_OF_INSTR();
1676 DECODE_PRINTF("TEST\t");
1677 FETCH_DECODE_MODRM(mod, rh, rl);
1678 if (mod < 3) {
1679 destoffset = decode_rmXX_address(mod, rl);
1680 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1681 u32 destval;
1682 u32 *srcreg;
1683
1684 DECODE_PRINTF(",");
1685 destval = fetch_data_long(destoffset);
1686 srcreg = DECODE_RM_LONG_REGISTER(rh);
1687 DECODE_PRINTF("\n");
1688 TRACE_AND_STEP();
1689 test_long(destval, *srcreg);
1690 } else {
1691 u16 destval;
1692 u16 *srcreg;
1693
1694 DECODE_PRINTF(",");
1695 destval = fetch_data_word(destoffset);
1696 srcreg = DECODE_RM_WORD_REGISTER(rh);
1697 DECODE_PRINTF("\n");
1698 TRACE_AND_STEP();
1699 test_word(destval, *srcreg);
1700 }
1701 } else { /* register to register */
1702 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1703 u32 *destreg,*srcreg;
1704
1705 destreg = DECODE_RM_LONG_REGISTER(rl);
1706 DECODE_PRINTF(",");
1707 srcreg = DECODE_RM_LONG_REGISTER(rh);
1708 DECODE_PRINTF("\n");
1709 TRACE_AND_STEP();
1710 test_long(*destreg, *srcreg);
1711 } else {
1712 u16 *destreg,*srcreg;
1713
1714 destreg = DECODE_RM_WORD_REGISTER(rl);
1715 DECODE_PRINTF(",");
1716 srcreg = DECODE_RM_WORD_REGISTER(rh);
1717 DECODE_PRINTF("\n");
1718 TRACE_AND_STEP();
1719 test_word(*destreg, *srcreg);
1720 }
1721 }
1722 DECODE_CLEAR_SEGOVR();
1723 END_OF_INSTR();
1724}
1725
1726/****************************************************************************
1727REMARKS:
1728Handles opcode 0x86
1729****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001730static void x86emuOp_xchg_byte_RM_R(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001731{
1732 int mod, rl, rh;
1733 u8 *destreg, *srcreg;
1734 uint destoffset;
1735 u8 destval;
1736 u8 tmp;
1737
1738 START_OF_INSTR();
1739 DECODE_PRINTF("XCHG\t");
1740 FETCH_DECODE_MODRM(mod, rh, rl);
1741 if (mod < 3) {
1742 destoffset = decode_rmXX_address(mod, rl);
1743 DECODE_PRINTF(",");
1744 destval = fetch_data_byte(destoffset);
1745 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1746 DECODE_PRINTF("\n");
1747 TRACE_AND_STEP();
1748 tmp = *srcreg;
1749 *srcreg = destval;
1750 destval = tmp;
1751 store_data_byte(destoffset, destval);
1752 } else { /* register to register */
1753 destreg = DECODE_RM_BYTE_REGISTER(rl);
1754 DECODE_PRINTF(",");
1755 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1756 DECODE_PRINTF("\n");
1757 TRACE_AND_STEP();
1758 tmp = *srcreg;
1759 *srcreg = *destreg;
1760 *destreg = tmp;
1761 }
1762 DECODE_CLEAR_SEGOVR();
1763 END_OF_INSTR();
1764}
1765
1766/****************************************************************************
1767REMARKS:
1768Handles opcode 0x87
1769****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001770static void x86emuOp_xchg_word_RM_R(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001771{
1772 int mod, rl, rh;
1773 uint destoffset;
1774
1775 START_OF_INSTR();
1776 DECODE_PRINTF("XCHG\t");
1777 FETCH_DECODE_MODRM(mod, rh, rl);
1778 if (mod < 3) {
1779 destoffset = decode_rmXX_address(mod, rl);
1780 DECODE_PRINTF(",");
1781 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1782 u32 *srcreg;
1783 u32 destval,tmp;
1784
1785 destval = fetch_data_long(destoffset);
1786 srcreg = DECODE_RM_LONG_REGISTER(rh);
1787 DECODE_PRINTF("\n");
1788 TRACE_AND_STEP();
1789 tmp = *srcreg;
1790 *srcreg = destval;
1791 destval = tmp;
1792 store_data_long(destoffset, destval);
1793 } else {
1794 u16 *srcreg;
1795 u16 destval,tmp;
1796
1797 destval = fetch_data_word(destoffset);
1798 srcreg = DECODE_RM_WORD_REGISTER(rh);
1799 DECODE_PRINTF("\n");
1800 TRACE_AND_STEP();
1801 tmp = *srcreg;
1802 *srcreg = destval;
1803 destval = tmp;
1804 store_data_word(destoffset, destval);
1805 }
1806 } else { /* register to register */
1807 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1808 u32 *destreg,*srcreg;
1809 u32 tmp;
1810
1811 destreg = DECODE_RM_LONG_REGISTER(rl);
1812 DECODE_PRINTF(",");
1813 srcreg = DECODE_RM_LONG_REGISTER(rh);
1814 DECODE_PRINTF("\n");
1815 TRACE_AND_STEP();
1816 tmp = *srcreg;
1817 *srcreg = *destreg;
1818 *destreg = tmp;
1819 } else {
1820 u16 *destreg,*srcreg;
1821 u16 tmp;
1822
1823 destreg = DECODE_RM_WORD_REGISTER(rl);
1824 DECODE_PRINTF(",");
1825 srcreg = DECODE_RM_WORD_REGISTER(rh);
1826 DECODE_PRINTF("\n");
1827 TRACE_AND_STEP();
1828 tmp = *srcreg;
1829 *srcreg = *destreg;
1830 *destreg = tmp;
1831 }
1832 }
1833 DECODE_CLEAR_SEGOVR();
1834 END_OF_INSTR();
1835}
1836
1837/****************************************************************************
1838REMARKS:
1839Handles opcode 0x88
1840****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001841static void x86emuOp_mov_byte_RM_R(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001842{
1843 int mod, rl, rh;
1844 u8 *destreg, *srcreg;
1845 uint destoffset;
1846
1847 START_OF_INSTR();
1848 DECODE_PRINTF("MOV\t");
1849 FETCH_DECODE_MODRM(mod, rh, rl);
1850 if (mod < 3) {
1851 destoffset = decode_rmXX_address(mod, rl);
1852 DECODE_PRINTF(",");
1853 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1854 DECODE_PRINTF("\n");
1855 TRACE_AND_STEP();
1856 store_data_byte(destoffset, *srcreg);
1857 } else { /* register to register */
1858 destreg = DECODE_RM_BYTE_REGISTER(rl);
1859 DECODE_PRINTF(",");
1860 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1861 DECODE_PRINTF("\n");
1862 TRACE_AND_STEP();
1863 *destreg = *srcreg;
1864 }
1865 DECODE_CLEAR_SEGOVR();
1866 END_OF_INSTR();
1867}
1868
1869/****************************************************************************
1870REMARKS:
1871Handles opcode 0x89
1872****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001873static void x86emuOp_mov_word_RM_R(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001874{
1875 int mod, rl, rh;
1876 uint destoffset;
1877
1878 START_OF_INSTR();
1879 DECODE_PRINTF("MOV\t");
1880 FETCH_DECODE_MODRM(mod, rh, rl);
1881 if (mod < 3) {
1882 destoffset = decode_rmXX_address(mod, rl);
1883 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1884 u32 *srcreg;
1885
1886 DECODE_PRINTF(",");
1887 srcreg = DECODE_RM_LONG_REGISTER(rh);
1888 DECODE_PRINTF("\n");
1889 TRACE_AND_STEP();
1890 store_data_long(destoffset, *srcreg);
1891 } else {
1892 u16 *srcreg;
1893
1894 DECODE_PRINTF(",");
1895 srcreg = DECODE_RM_WORD_REGISTER(rh);
1896 DECODE_PRINTF("\n");
1897 TRACE_AND_STEP();
1898 store_data_word(destoffset, *srcreg);
1899 }
1900 } else { /* register to register */
1901 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1902 u32 *destreg,*srcreg;
1903
1904 destreg = DECODE_RM_LONG_REGISTER(rl);
1905 DECODE_PRINTF(",");
1906 srcreg = DECODE_RM_LONG_REGISTER(rh);
1907 DECODE_PRINTF("\n");
1908 TRACE_AND_STEP();
1909 *destreg = *srcreg;
1910 } else {
1911 u16 *destreg,*srcreg;
1912
1913 destreg = DECODE_RM_WORD_REGISTER(rl);
1914 DECODE_PRINTF(",");
1915 srcreg = DECODE_RM_WORD_REGISTER(rh);
1916 DECODE_PRINTF("\n");
1917 TRACE_AND_STEP();
1918 *destreg = *srcreg;
1919 }
1920 }
1921 DECODE_CLEAR_SEGOVR();
1922 END_OF_INSTR();
1923}
1924
1925/****************************************************************************
1926REMARKS:
1927Handles opcode 0x8a
1928****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001929static void x86emuOp_mov_byte_R_RM(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001930{
1931 int mod, rl, rh;
1932 u8 *destreg, *srcreg;
1933 uint srcoffset;
1934 u8 srcval;
1935
1936 START_OF_INSTR();
1937 DECODE_PRINTF("MOV\t");
1938 FETCH_DECODE_MODRM(mod, rh, rl);
1939 if (mod < 3) {
1940 destreg = DECODE_RM_BYTE_REGISTER(rh);
1941 DECODE_PRINTF(",");
1942 srcoffset = decode_rmXX_address(mod, rl);
1943 srcval = fetch_data_byte(srcoffset);
1944 DECODE_PRINTF("\n");
1945 TRACE_AND_STEP();
1946 *destreg = srcval;
1947 } else { /* register to register */
1948 destreg = DECODE_RM_BYTE_REGISTER(rh);
1949 DECODE_PRINTF(",");
1950 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1951 DECODE_PRINTF("\n");
1952 TRACE_AND_STEP();
1953 *destreg = *srcreg;
1954 }
1955 DECODE_CLEAR_SEGOVR();
1956 END_OF_INSTR();
1957}
1958
1959/****************************************************************************
1960REMARKS:
1961Handles opcode 0x8b
1962****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001963static void x86emuOp_mov_word_R_RM(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001964{
1965 int mod, rl, rh;
1966 uint srcoffset;
1967
1968 START_OF_INSTR();
1969 DECODE_PRINTF("MOV\t");
1970 FETCH_DECODE_MODRM(mod, rh, rl);
1971 if (mod < 3) {
1972 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1973 u32 *destreg;
1974 u32 srcval;
1975
1976 destreg = DECODE_RM_LONG_REGISTER(rh);
1977 DECODE_PRINTF(",");
1978 srcoffset = decode_rmXX_address(mod, rl);
1979 srcval = fetch_data_long(srcoffset);
1980 DECODE_PRINTF("\n");
1981 TRACE_AND_STEP();
1982 *destreg = srcval;
1983 } else {
1984 u16 *destreg;
1985 u16 srcval;
1986
1987 destreg = DECODE_RM_WORD_REGISTER(rh);
1988 DECODE_PRINTF(",");
1989 srcoffset = decode_rmXX_address(mod, rl);
1990 srcval = fetch_data_word(srcoffset);
1991 DECODE_PRINTF("\n");
1992 TRACE_AND_STEP();
1993 *destreg = srcval;
1994 }
1995 } else { /* register to register */
1996 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1997 u32 *destreg, *srcreg;
1998
1999 destreg = DECODE_RM_LONG_REGISTER(rh);
2000 DECODE_PRINTF(",");
2001 srcreg = DECODE_RM_LONG_REGISTER(rl);
2002 DECODE_PRINTF("\n");
2003 TRACE_AND_STEP();
2004 *destreg = *srcreg;
2005 } else {
2006 u16 *destreg, *srcreg;
2007
2008 destreg = DECODE_RM_WORD_REGISTER(rh);
2009 DECODE_PRINTF(",");
2010 srcreg = DECODE_RM_WORD_REGISTER(rl);
2011 DECODE_PRINTF("\n");
2012 TRACE_AND_STEP();
2013 *destreg = *srcreg;
2014 }
2015 }
2016 DECODE_CLEAR_SEGOVR();
2017 END_OF_INSTR();
2018}
2019
2020/****************************************************************************
2021REMARKS:
2022Handles opcode 0x8c
2023****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00002024static void x86emuOp_mov_word_RM_SR(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00002025{
2026 int mod, rl, rh;
2027 u16 *destreg, *srcreg;
2028 uint destoffset;
2029 u16 destval;
2030
2031 START_OF_INSTR();
2032 DECODE_PRINTF("MOV\t");
2033 FETCH_DECODE_MODRM(mod, rh, rl);
2034 if (mod < 3) {
2035 destoffset = decode_rmXX_address(mod, rl);
2036 DECODE_PRINTF(",");
2037 srcreg = decode_rm_seg_register(rh);
2038 DECODE_PRINTF("\n");
2039 TRACE_AND_STEP();
2040 destval = *srcreg;
2041 store_data_word(destoffset, destval);
2042 } else { /* register to register */
2043 destreg = DECODE_RM_WORD_REGISTER(rl);
2044 DECODE_PRINTF(",");
2045 srcreg = decode_rm_seg_register(rh);
2046 DECODE_PRINTF("\n");
2047 TRACE_AND_STEP();
2048 *destreg = *srcreg;
2049 }
2050 DECODE_CLEAR_SEGOVR();
2051 END_OF_INSTR();
2052}
2053
2054/****************************************************************************
2055REMARKS:
2056Handles opcode 0x8d
2057****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00002058static void x86emuOp_lea_word_R_M(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00002059{
2060 int mod, rl, rh;
2061 u16 *srcreg;
2062 uint destoffset;
2063
2064/*
2065 * TODO: Need to handle address size prefix!
2066 *
2067 * lea eax,[eax+ebx*2] ??
2068 */
2069
2070 START_OF_INSTR();
2071 DECODE_PRINTF("LEA\t");
2072 FETCH_DECODE_MODRM(mod, rh, rl);
2073 if (mod < 3) {
2074 srcreg = DECODE_RM_WORD_REGISTER(rh);
2075 DECODE_PRINTF(",");
2076 destoffset = decode_rmXX_address(mod, rl);
2077 DECODE_PRINTF("\n");
2078 TRACE_AND_STEP();
2079 *srcreg = (u16)destoffset;
2080 }
2081 /* } else { undefined. Do nothing. } */
2082 DECODE_CLEAR_SEGOVR();
2083 END_OF_INSTR();
2084}
2085
2086/****************************************************************************
2087REMARKS:
2088Handles opcode 0x8e
2089****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00002090static void x86emuOp_mov_word_SR_RM(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00002091{
2092 int mod, rl, rh;
2093 u16 *destreg, *srcreg;
2094 uint srcoffset;
2095 u16 srcval;
2096
2097 START_OF_INSTR();
2098 DECODE_PRINTF("MOV\t");
2099 FETCH_DECODE_MODRM(mod, rh, rl);
2100 if (mod < 3) {
2101 destreg = decode_rm_seg_register(rh);
2102 DECODE_PRINTF(",");
2103 srcoffset = decode_rmXX_address(mod, rl);
2104 srcval = fetch_data_word(srcoffset);
2105 DECODE_PRINTF("\n");
2106 TRACE_AND_STEP();
2107 *destreg = srcval;
2108 } else { /* register to register */
2109 destreg = decode_rm_seg_register(rh);
2110 DECODE_PRINTF(",");
2111 srcreg = DECODE_RM_WORD_REGISTER(rl);
2112 DECODE_PRINTF("\n");
2113 TRACE_AND_STEP();
2114 *destreg = *srcreg;
2115 }
2116 /*
2117 * Clean up, and reset all the R_xSP pointers to the correct
2118 * locations. This is about 3x too much overhead (doing all the
2119 * segreg ptrs when only one is needed, but this instruction
2120 * *cannot* be that common, and this isn't too much work anyway.
2121 */
2122 DECODE_CLEAR_SEGOVR();
2123 END_OF_INSTR();
2124}
2125
2126/****************************************************************************
2127REMARKS:
2128Handles opcode 0x8f
2129****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00002130static void x86emuOp_pop_RM(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00002131{
2132 int mod, rl, rh;
2133 uint destoffset;
2134
2135 START_OF_INSTR();
2136 DECODE_PRINTF("POP\t");
2137 FETCH_DECODE_MODRM(mod, rh, rl);
2138 if (rh != 0) {
2139 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
2140 HALT_SYS();
2141 }
2142 if (mod < 3) {
2143 destoffset = decode_rmXX_address(mod, rl);
2144 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2145 u32 destval;
2146
2147 DECODE_PRINTF("\n");
2148 TRACE_AND_STEP();
2149 destval = pop_long();
2150 store_data_long(destoffset, destval);
2151 } else {
2152 u16 destval;
2153
2154 DECODE_PRINTF("\n");
2155 TRACE_AND_STEP();
2156 destval = pop_word();
2157 store_data_word(destoffset, destval);
2158 }
2159 } else { /* register to register */
2160 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2161 u32 *destreg;
2162
2163 destreg = DECODE_RM_LONG_REGISTER(rl);
2164 DECODE_PRINTF("\n");
2165 TRACE_AND_STEP();
2166 *destreg = pop_long();
2167 } else {
2168 u16 *destreg;
2169
2170 destreg = DECODE_RM_WORD_REGISTER(rl);
2171 DECODE_PRINTF("\n");
2172 TRACE_AND_STEP();
2173 *destreg = pop_word();
2174 }
2175 }
2176 DECODE_CLEAR_SEGOVR();
2177 END_OF_INSTR();
2178}
2179
2180/****************************************************************************
2181REMARKS:
2182Handles opcode 0x90
2183****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00002184static void x86emuOp_nop(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00002185{
2186 START_OF_INSTR();
2187 DECODE_PRINTF("NOP\n");
2188 TRACE_AND_STEP();
2189 DECODE_CLEAR_SEGOVR();
2190 END_OF_INSTR();
2191}
2192
2193/****************************************************************************
2194REMARKS:
2195Handles opcode 0x91-0x97
2196****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00002197static void x86emuOp_xchg_word_AX_register(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00002198{
2199 u32 tmp;
2200
2201 op1 &= 0x7;
2202
2203 START_OF_INSTR();
2204
2205 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2206 u32 *reg32;
2207 DECODE_PRINTF("XCHG\tEAX,");
2208 reg32 = DECODE_RM_LONG_REGISTER(op1);
2209 DECODE_PRINTF("\n");
2210 TRACE_AND_STEP();
2211 tmp = M.x86.R_EAX;
2212 M.x86.R_EAX = *reg32;
2213 *reg32 = tmp;
2214 } else {
2215 u16 *reg16;
2216 DECODE_PRINTF("XCHG\tAX,");
2217 reg16 = DECODE_RM_WORD_REGISTER(op1);
2218 DECODE_PRINTF("\n");
2219 TRACE_AND_STEP();
2220 tmp = M.x86.R_AX;
2221 M.x86.R_AX = *reg16;
2222 *reg16 = (u16)tmp;
2223 }
2224 DECODE_CLEAR_SEGOVR();
2225 END_OF_INSTR();
2226}
2227
2228/****************************************************************************
2229REMARKS:
2230Handles opcode 0x98
2231****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00002232static void x86emuOp_cbw(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00002233{
2234 START_OF_INSTR();
2235 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2236 DECODE_PRINTF("CWDE\n");
2237 } else {
2238 DECODE_PRINTF("CBW\n");
2239 }
2240 TRACE_AND_STEP();
2241 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2242 if (M.x86.R_AX & 0x8000) {
2243 M.x86.R_EAX |= 0xffff0000;
2244 } else {
2245 M.x86.R_EAX &= 0x0000ffff;
2246 }
2247 } else {
2248 if (M.x86.R_AL & 0x80) {
2249 M.x86.R_AH = 0xff;
2250 } else {
2251 M.x86.R_AH = 0x0;
2252 }
2253 }
2254 DECODE_CLEAR_SEGOVR();
2255 END_OF_INSTR();
2256}
2257
2258/****************************************************************************
2259REMARKS:
2260Handles opcode 0x99
2261****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00002262static void x86emuOp_cwd(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00002263{
2264 START_OF_INSTR();
2265 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2266 DECODE_PRINTF("CDQ\n");
2267 } else {
2268 DECODE_PRINTF("CWD\n");
2269 }
2270 DECODE_PRINTF("CWD\n");
2271 TRACE_AND_STEP();
2272 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2273 if (M.x86.R_EAX & 0x80000000) {
2274 M.x86.R_EDX = 0xffffffff;
2275 } else {
2276 M.x86.R_EDX = 0x0;
2277 }
2278 } else {
2279 if (M.x86.R_AX & 0x8000) {
2280 M.x86.R_DX = 0xffff;
2281 } else {
2282 M.x86.R_DX = 0x0;
2283 }
2284 }
2285 DECODE_CLEAR_SEGOVR();
2286 END_OF_INSTR();
2287}
2288
2289/****************************************************************************
2290REMARKS:
2291Handles opcode 0x9a
2292****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00002293static void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00002294{
2295 u16 farseg, faroff;
2296
2297 START_OF_INSTR();
2298 DECODE_PRINTF("CALL\t");
2299 faroff = fetch_word_imm();
2300 farseg = fetch_word_imm();
2301 DECODE_PRINTF2("%04x:", farseg);
2302 DECODE_PRINTF2("%04x\n", faroff);
2303 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, farseg, faroff, "FAR ");
2304
2305 /* XXX
2306 *
2307 * Hooked interrupt vectors calling into our "BIOS" will cause
2308 * problems unless all intersegment stuff is checked for BIOS
2309 * access. Check needed here. For moment, let it alone.
2310 */
2311 TRACE_AND_STEP();
2312 push_word(M.x86.R_CS);
2313 M.x86.R_CS = farseg;
2314 push_word(M.x86.R_IP);
2315 M.x86.R_IP = faroff;
2316 DECODE_CLEAR_SEGOVR();
2317 END_OF_INSTR();
2318}
2319
2320/****************************************************************************
2321REMARKS:
2322Handles opcode 0x9b
2323****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00002324static void x86emuOp_wait(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00002325{
2326 START_OF_INSTR();
2327 DECODE_PRINTF("WAIT");
2328 TRACE_AND_STEP();
2329 /* NADA. */
2330 DECODE_CLEAR_SEGOVR();
2331 END_OF_INSTR();
2332}
2333
2334/****************************************************************************
2335REMARKS:
2336Handles opcode 0x9c
2337****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00002338static void x86emuOp_pushf_word(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00002339{
2340 u32 flags;
2341
2342 START_OF_INSTR();
2343 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2344 DECODE_PRINTF("PUSHFD\n");
2345 } else {
2346 DECODE_PRINTF("PUSHF\n");
2347 }
2348 TRACE_AND_STEP();
2349
2350 /* clear out *all* bits not representing flags, and turn on real bits */
2351 flags = (M.x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
2352 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2353 push_long(flags);
2354 } else {
2355 push_word((u16)flags);
2356 }
2357 DECODE_CLEAR_SEGOVR();
2358 END_OF_INSTR();
2359}
2360
2361/****************************************************************************
2362REMARKS:
2363Handles opcode 0x9d
2364****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00002365static void x86emuOp_popf_word(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00002366{
2367 START_OF_INSTR();
2368 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2369 DECODE_PRINTF("POPFD\n");
2370 } else {
2371 DECODE_PRINTF("POPF\n");
2372 }
2373 TRACE_AND_STEP();
2374 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2375 M.x86.R_EFLG = pop_long();
2376 } else {
2377 M.x86.R_FLG = pop_word();
2378 }
2379 DECODE_CLEAR_SEGOVR();
2380 END_OF_INSTR();
2381}
2382
2383/****************************************************************************
2384REMARKS:
2385Handles opcode 0x9e
2386****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00002387static void x86emuOp_sahf(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00002388{
2389 START_OF_INSTR();
2390 DECODE_PRINTF("SAHF\n");
2391 TRACE_AND_STEP();
2392 /* clear the lower bits of the flag register */
2393 M.x86.R_FLG &= 0xffffff00;
2394 /* or in the AH register into the flags register */
2395 M.x86.R_FLG |= M.x86.R_AH;
2396 DECODE_CLEAR_SEGOVR();
2397 END_OF_INSTR();
2398}
2399
2400/****************************************************************************
2401REMARKS:
2402Handles opcode 0x9f
2403****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00002404static void x86emuOp_lahf(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00002405{
2406 START_OF_INSTR();
2407 DECODE_PRINTF("LAHF\n");
2408 TRACE_AND_STEP();
2409 M.x86.R_AH = (u8)(M.x86.R_FLG & 0xff);
2410 /*undocumented TC++ behavior??? Nope. It's documented, but
2411 you have too look real hard to notice it. */
2412 M.x86.R_AH |= 0x2;
2413 DECODE_CLEAR_SEGOVR();
2414 END_OF_INSTR();
2415}
2416
2417/****************************************************************************
2418REMARKS:
2419Handles opcode 0xa0
2420****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00002421static void x86emuOp_mov_AL_M_IMM(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00002422{
2423 u16 offset;
2424
2425 START_OF_INSTR();
2426 DECODE_PRINTF("MOV\tAL,");
2427 offset = fetch_word_imm();
2428 DECODE_PRINTF2("[%04x]\n", offset);
2429 TRACE_AND_STEP();
2430 M.x86.R_AL = fetch_data_byte(offset);
2431 DECODE_CLEAR_SEGOVR();
2432 END_OF_INSTR();
2433}
2434
2435/****************************************************************************
2436REMARKS:
2437Handles opcode 0xa1
2438****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00002439static void x86emuOp_mov_AX_M_IMM(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00002440{
2441 u16 offset;
2442
2443 START_OF_INSTR();
2444 offset = fetch_word_imm();
2445 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2446 DECODE_PRINTF2("MOV\tEAX,[%04x]\n", offset);
2447 } else {
2448 DECODE_PRINTF2("MOV\tAX,[%04x]\n", offset);
2449 }
2450 TRACE_AND_STEP();
2451 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2452 M.x86.R_EAX = fetch_data_long(offset);
2453 } else {
2454 M.x86.R_AX = fetch_data_word(offset);
2455 }
2456 DECODE_CLEAR_SEGOVR();
2457 END_OF_INSTR();
2458}
2459
2460/****************************************************************************
2461REMARKS:
2462Handles opcode 0xa2
2463****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00002464static void x86emuOp_mov_M_AL_IMM(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00002465{
2466 u16 offset;
2467
2468 START_OF_INSTR();
2469 DECODE_PRINTF("MOV\t");
2470 offset = fetch_word_imm();
2471 DECODE_PRINTF2("[%04x],AL\n", offset);
2472 TRACE_AND_STEP();
2473 store_data_byte(offset, M.x86.R_AL);
2474 DECODE_CLEAR_SEGOVR();
2475 END_OF_INSTR();
2476}
2477
2478/****************************************************************************
2479REMARKS:
2480Handles opcode 0xa3
2481****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00002482static void x86emuOp_mov_M_AX_IMM(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00002483{
2484 u16 offset;
2485
2486 START_OF_INSTR();
2487 offset = fetch_word_imm();
2488 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2489 DECODE_PRINTF2("MOV\t[%04x],EAX\n", offset);
2490 } else {
2491 DECODE_PRINTF2("MOV\t[%04x],AX\n", offset);
2492 }
2493 TRACE_AND_STEP();
2494 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2495 store_data_long(offset, M.x86.R_EAX);
2496 } else {
2497 store_data_word(offset, M.x86.R_AX);
2498 }
2499 DECODE_CLEAR_SEGOVR();
2500 END_OF_INSTR();
2501}
2502
2503/****************************************************************************
2504REMARKS:
2505Handles opcode 0xa4
2506****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00002507static void x86emuOp_movs_byte(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00002508{
2509 u8 val;
2510 u32 count;
2511 int inc;
2512
2513 START_OF_INSTR();
2514 DECODE_PRINTF("MOVS\tBYTE\n");
2515 if (ACCESS_FLAG(F_DF)) /* down */
2516 inc = -1;
2517 else
2518 inc = 1;
2519 TRACE_AND_STEP();
2520 count = 1;
2521 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2522 /* dont care whether REPE or REPNE */
2523 /* move them until (E)CX is ZERO. */
2524 count = (M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX;
2525 M.x86.R_CX = 0;
2526 if (M.x86.mode & SYSMODE_32BIT_REP)
2527 M.x86.R_ECX = 0;
2528 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2529 }
2530 while (count--) {
2531 val = fetch_data_byte(M.x86.R_SI);
2532 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, val);
2533 M.x86.R_SI += inc;
2534 M.x86.R_DI += inc;
2535 if (M.x86.intr & INTR_HALTED)
2536 break;
2537 }
2538 DECODE_CLEAR_SEGOVR();
2539 END_OF_INSTR();
2540}
2541
2542/****************************************************************************
2543REMARKS:
2544Handles opcode 0xa5
2545****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00002546static void x86emuOp_movs_word(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00002547{
2548 u32 val;
2549 int inc;
2550 u32 count;
2551
2552 START_OF_INSTR();
2553 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2554 DECODE_PRINTF("MOVS\tDWORD\n");
2555 if (ACCESS_FLAG(F_DF)) /* down */
2556 inc = -4;
2557 else
2558 inc = 4;
2559 } else {
2560 DECODE_PRINTF("MOVS\tWORD\n");
2561 if (ACCESS_FLAG(F_DF)) /* down */
2562 inc = -2;
2563 else
2564 inc = 2;
2565 }
2566 TRACE_AND_STEP();
2567 count = 1;
2568 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2569 /* dont care whether REPE or REPNE */
2570 /* move them until (E)CX is ZERO. */
2571 count = (M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX;
2572 M.x86.R_CX = 0;
2573 if (M.x86.mode & SYSMODE_32BIT_REP)
2574 M.x86.R_ECX = 0;
2575 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2576 }
2577 while (count--) {
2578 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2579 val = fetch_data_long(M.x86.R_SI);
2580 store_data_long_abs(M.x86.R_ES, M.x86.R_DI, val);
2581 } else {
2582 val = fetch_data_word(M.x86.R_SI);
2583 store_data_word_abs(M.x86.R_ES, M.x86.R_DI, (u16)val);
2584 }
2585 M.x86.R_SI += inc;
2586 M.x86.R_DI += inc;
2587 if (M.x86.intr & INTR_HALTED)
2588 break;
2589 }
2590 DECODE_CLEAR_SEGOVR();
2591 END_OF_INSTR();
2592}
2593
2594/****************************************************************************
2595REMARKS:
2596Handles opcode 0xa6
2597****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00002598static void x86emuOp_cmps_byte(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00002599{
2600 s8 val1, val2;
2601 int inc;
2602
2603 START_OF_INSTR();
2604 DECODE_PRINTF("CMPS\tBYTE\n");
2605 TRACE_AND_STEP();
2606 if (ACCESS_FLAG(F_DF)) /* down */
2607 inc = -1;
2608 else
2609 inc = 1;
2610
2611 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2612 /* REPE */
2613 /* move them until (E)CX is ZERO. */
2614 while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
2615 val1 = fetch_data_byte(M.x86.R_SI);
2616 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2617 cmp_byte(val1, val2);
2618 if (M.x86.mode & SYSMODE_32BIT_REP)
2619 M.x86.R_ECX -= 1;
2620 else
2621 M.x86.R_CX -= 1;
2622 M.x86.R_SI += inc;
2623 M.x86.R_DI += inc;
2624 if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && (ACCESS_FLAG(F_ZF) == 0) ) break;
2625 if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2626 if (M.x86.intr & INTR_HALTED)
2627 break;
2628 }
2629 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2630 } else {
2631 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;
2636 }
2637 DECODE_CLEAR_SEGOVR();
2638 END_OF_INSTR();
2639}
2640
2641/****************************************************************************
2642REMARKS:
2643Handles opcode 0xa7
2644****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00002645static void x86emuOp_cmps_word(u8 X86EMU_UNUSED(op1))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00002646{
2647 u32 val1,val2;
2648 int inc;
2649
2650 START_OF_INSTR();
2651 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2652 DECODE_PRINTF("CMPS\tDWORD\n");
2653 inc = 4;
2654 } else {
2655 DECODE_PRINTF("CMPS\tWORD\n");
2656 inc = 2;
2657 }
2658 if (ACCESS_FLAG(F_DF)) /* down */
2659 inc = -inc;
2660
2661 TRACE_AND_STEP();
2662 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2663 /* REPE */
2664 /* move them until (E)CX is ZERO. */
2665 while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : 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 if (M.x86.mode & SYSMODE_32BIT_REP)
2676 M.x86.R_ECX -= 1;
2677 else
2678 M.x86.R_CX -= 1;
2679 M.x86.R_SI += inc;
2680 M.x86.R_DI += inc;
2681 if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && ACCESS_FLAG(F_ZF) == 0 ) break;
2682 if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2683 if (M.x86.intr & INTR_HALTED)
2684 break;
2685 }
2686 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2687 } else {
2688 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2689 val1 = fetch_data_long(M.x86.R_SI);
2690 val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2691 cmp_long(val1, val2);
2692 } else {
2693 val1 = fetch_data_word(M.x86.R_SI);
2694 val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2695 cmp_word((u16)val1, (u16)val2);
2696 }
2697 M.x86.R_SI += inc;
2698 M.x86.R_DI += inc;
2699 }
2700 DECODE_CLEAR_SEGOVR();
2701 END_OF_INSTR();
2702}
2703
2704/****************************************************************************
2705REMARKS:
2706Handles opcode 0xa8
2707****************************************************************************/