1 /* $NetBSD: x86emu.c,v 1.6 2009/02/03 19:14:52 joerg Exp $ */
3 /****************************************************************************
5 * Realmode X86 Emulator Library
7 * Copyright (C) 1996-1999 SciTech Software, Inc.
8 * Copyright (C) David Mosberger-Tang
9 * Copyright (C) 1999 Egbert Eich
10 * Copyright (C) 2007 Joerg Sonnenberger
12 * ========================================================================
14 * Permission to use, copy, modify, distribute, and sell this software and
15 * its documentation for any purpose is hereby granted without fee,
16 * provided that the above copyright notice appear in all copies and that
17 * both that copyright notice and this permission notice appear in
18 * supporting documentation, and that the name of the authors not be used
19 * in advertising or publicity pertaining to distribution of the software
20 * without specific, written prior permission. The authors makes no
21 * representations about the suitability of this software for any purpose.
22 * It is provided "as is" without express or implied warranty.
24 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
25 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
26 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
27 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
28 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
29 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
30 * PERFORMANCE OF THIS SOFTWARE.
32 ****************************************************************************/
38 #include <x86emu/x86emu.h>
39 #include <x86emu/x86emu_regs.h>
41 static void x86emu_intr_raise (struct X86EMU
*, uint8_t type
);
43 static void X86EMU_exec_one_byte(struct X86EMU
*);
44 static void X86EMU_exec_two_byte(struct X86EMU
*);
46 static void fetch_decode_modrm (struct X86EMU
*);
47 static uint8_t fetch_byte_imm (struct X86EMU
*);
48 static uint16_t fetch_word_imm (struct X86EMU
*);
49 static uint32_t fetch_long_imm (struct X86EMU
*);
50 static uint8_t fetch_data_byte (struct X86EMU
*, uint32_t offset
);
51 static uint8_t fetch_byte (struct X86EMU
*, uint segment
, uint32_t offset
);
52 static uint16_t fetch_data_word (struct X86EMU
*, uint32_t offset
);
53 static uint16_t fetch_word (struct X86EMU
*, uint32_t segment
, uint32_t offset
);
54 static uint32_t fetch_data_long (struct X86EMU
*, uint32_t offset
);
55 static uint32_t fetch_long (struct X86EMU
*, uint32_t segment
, uint32_t offset
);
56 static void store_data_byte (struct X86EMU
*, uint32_t offset
, uint8_t val
);
57 static void store_byte (struct X86EMU
*, uint32_t segment
, uint32_t offset
, uint8_t val
);
58 static void store_data_word (struct X86EMU
*, uint32_t offset
, uint16_t val
);
59 static void store_word (struct X86EMU
*, uint32_t segment
, uint32_t offset
, uint16_t val
);
60 static void store_data_long (struct X86EMU
*, uint32_t offset
, uint32_t val
);
61 static void store_long (struct X86EMU
*, uint32_t segment
, uint32_t offset
, uint32_t val
);
62 static uint8_t* decode_rl_byte_register(struct X86EMU
*);
63 static uint16_t* decode_rl_word_register(struct X86EMU
*);
64 static uint32_t* decode_rl_long_register(struct X86EMU
*);
65 static uint8_t* decode_rh_byte_register(struct X86EMU
*);
66 static uint16_t* decode_rh_word_register(struct X86EMU
*);
67 static uint32_t* decode_rh_long_register(struct X86EMU
*);
68 static uint16_t* decode_rh_seg_register(struct X86EMU
*);
69 static uint32_t decode_rl_address(struct X86EMU
*);
71 static uint8_t decode_and_fetch_byte(struct X86EMU
*);
72 static uint16_t decode_and_fetch_word(struct X86EMU
*);
73 static uint32_t decode_and_fetch_long(struct X86EMU
*);
75 static uint8_t decode_and_fetch_byte_imm8(struct X86EMU
*, uint8_t *);
76 static uint16_t decode_and_fetch_word_imm8(struct X86EMU
*, uint8_t *);
77 static uint32_t decode_and_fetch_long_imm8(struct X86EMU
*, uint8_t *);
79 static uint16_t decode_and_fetch_word_disp(struct X86EMU
*, int16_t);
80 static uint32_t decode_and_fetch_long_disp(struct X86EMU
*, int16_t);
82 static void write_back_byte(struct X86EMU
*, uint8_t);
83 static void write_back_word(struct X86EMU
*, uint16_t);
84 static void write_back_long(struct X86EMU
*, uint32_t);
86 static uint16_t aaa_word (struct X86EMU
*, uint16_t d
);
87 static uint16_t aas_word (struct X86EMU
*, uint16_t d
);
88 static uint16_t aad_word (struct X86EMU
*, uint16_t d
);
89 static uint16_t aam_word (struct X86EMU
*, uint8_t d
);
90 static uint8_t adc_byte (struct X86EMU
*, uint8_t d
, uint8_t s
);
91 static uint16_t adc_word (struct X86EMU
*, uint16_t d
, uint16_t s
);
92 static uint32_t adc_long (struct X86EMU
*, uint32_t d
, uint32_t s
);
93 static uint8_t add_byte (struct X86EMU
*, uint8_t d
, uint8_t s
);
94 static uint16_t add_word (struct X86EMU
*, uint16_t d
, uint16_t s
);
95 static uint32_t add_long (struct X86EMU
*, uint32_t d
, uint32_t s
);
96 static uint8_t and_byte (struct X86EMU
*, uint8_t d
, uint8_t s
);
97 static uint16_t and_word (struct X86EMU
*, uint16_t d
, uint16_t s
);
98 static uint32_t and_long (struct X86EMU
*, uint32_t d
, uint32_t s
);
99 static uint8_t cmp_byte (struct X86EMU
*, uint8_t d
, uint8_t s
);
100 static uint16_t cmp_word (struct X86EMU
*, uint16_t d
, uint16_t s
);
101 static uint32_t cmp_long (struct X86EMU
*, uint32_t d
, uint32_t s
);
102 static void cmp_byte_no_return (struct X86EMU
*, uint8_t d
, uint8_t s
);
103 static void cmp_word_no_return (struct X86EMU
*, uint16_t d
, uint16_t s
);
104 static void cmp_long_no_return (struct X86EMU
*, uint32_t d
, uint32_t s
);
105 static uint8_t daa_byte (struct X86EMU
*, uint8_t d
);
106 static uint8_t das_byte (struct X86EMU
*, uint8_t d
);
107 static uint8_t dec_byte (struct X86EMU
*, uint8_t d
);
108 static uint16_t dec_word (struct X86EMU
*, uint16_t d
);
109 static uint32_t dec_long (struct X86EMU
*, uint32_t d
);
110 static uint8_t inc_byte (struct X86EMU
*, uint8_t d
);
111 static uint16_t inc_word (struct X86EMU
*, uint16_t d
);
112 static uint32_t inc_long (struct X86EMU
*, uint32_t d
);
113 static uint8_t or_byte (struct X86EMU
*, uint8_t d
, uint8_t s
);
114 static uint16_t or_word (struct X86EMU
*, uint16_t d
, uint16_t s
);
115 static uint32_t or_long (struct X86EMU
*, uint32_t d
, uint32_t s
);
116 static uint8_t neg_byte (struct X86EMU
*, uint8_t s
);
117 static uint16_t neg_word (struct X86EMU
*, uint16_t s
);
118 static uint32_t neg_long (struct X86EMU
*, uint32_t s
);
119 static uint8_t rcl_byte (struct X86EMU
*, uint8_t d
, uint8_t s
);
120 static uint16_t rcl_word (struct X86EMU
*, uint16_t d
, uint8_t s
);
121 static uint32_t rcl_long (struct X86EMU
*, uint32_t d
, uint8_t s
);
122 static uint8_t rcr_byte (struct X86EMU
*, uint8_t d
, uint8_t s
);
123 static uint16_t rcr_word (struct X86EMU
*, uint16_t d
, uint8_t s
);
124 static uint32_t rcr_long (struct X86EMU
*, uint32_t d
, uint8_t s
);
125 static uint8_t rol_byte (struct X86EMU
*, uint8_t d
, uint8_t s
);
126 static uint16_t rol_word (struct X86EMU
*, uint16_t d
, uint8_t s
);
127 static uint32_t rol_long (struct X86EMU
*, uint32_t d
, uint8_t s
);
128 static uint8_t ror_byte (struct X86EMU
*, uint8_t d
, uint8_t s
);
129 static uint16_t ror_word (struct X86EMU
*, uint16_t d
, uint8_t s
);
130 static uint32_t ror_long (struct X86EMU
*, uint32_t d
, uint8_t s
);
131 static uint8_t shl_byte (struct X86EMU
*, uint8_t d
, uint8_t s
);
132 static uint16_t shl_word (struct X86EMU
*, uint16_t d
, uint8_t s
);
133 static uint32_t shl_long (struct X86EMU
*, uint32_t d
, uint8_t s
);
134 static uint8_t shr_byte (struct X86EMU
*, uint8_t d
, uint8_t s
);
135 static uint16_t shr_word (struct X86EMU
*, uint16_t d
, uint8_t s
);
136 static uint32_t shr_long (struct X86EMU
*, uint32_t d
, uint8_t s
);
137 static uint8_t sar_byte (struct X86EMU
*, uint8_t d
, uint8_t s
);
138 static uint16_t sar_word (struct X86EMU
*, uint16_t d
, uint8_t s
);
139 static uint32_t sar_long (struct X86EMU
*, uint32_t d
, uint8_t s
);
140 static uint16_t shld_word (struct X86EMU
*, uint16_t d
, uint16_t fill
, uint8_t s
);
141 static uint32_t shld_long (struct X86EMU
*, uint32_t d
, uint32_t fill
, uint8_t s
);
142 static uint16_t shrd_word (struct X86EMU
*, uint16_t d
, uint16_t fill
, uint8_t s
);
143 static uint32_t shrd_long (struct X86EMU
*, uint32_t d
, uint32_t fill
, uint8_t s
);
144 static uint8_t sbb_byte (struct X86EMU
*, uint8_t d
, uint8_t s
);
145 static uint16_t sbb_word (struct X86EMU
*, uint16_t d
, uint16_t s
);
146 static uint32_t sbb_long (struct X86EMU
*, uint32_t d
, uint32_t s
);
147 static uint8_t sub_byte (struct X86EMU
*, uint8_t d
, uint8_t s
);
148 static uint16_t sub_word (struct X86EMU
*, uint16_t d
, uint16_t s
);
149 static uint32_t sub_long (struct X86EMU
*, uint32_t d
, uint32_t s
);
150 static void test_byte (struct X86EMU
*, uint8_t d
, uint8_t s
);
151 static void test_word (struct X86EMU
*, uint16_t d
, uint16_t s
);
152 static void test_long (struct X86EMU
*, uint32_t d
, uint32_t s
);
153 static uint8_t xor_byte (struct X86EMU
*, uint8_t d
, uint8_t s
);
154 static uint16_t xor_word (struct X86EMU
*, uint16_t d
, uint16_t s
);
155 static uint32_t xor_long (struct X86EMU
*, uint32_t d
, uint32_t s
);
156 static void imul_byte (struct X86EMU
*, uint8_t s
);
157 static void imul_word (struct X86EMU
*, uint16_t s
);
158 static void imul_long (struct X86EMU
*, uint32_t s
);
159 static void mul_byte (struct X86EMU
*, uint8_t s
);
160 static void mul_word (struct X86EMU
*, uint16_t s
);
161 static void mul_long (struct X86EMU
*, uint32_t s
);
162 static void idiv_byte (struct X86EMU
*, uint8_t s
);
163 static void idiv_word (struct X86EMU
*, uint16_t s
);
164 static void idiv_long (struct X86EMU
*, uint32_t s
);
165 static void div_byte (struct X86EMU
*, uint8_t s
);
166 static void div_word (struct X86EMU
*, uint16_t s
);
167 static void div_long (struct X86EMU
*, uint32_t s
);
168 static void ins (struct X86EMU
*, int size
);
169 static void outs (struct X86EMU
*, int size
);
170 static void push_word (struct X86EMU
*, uint16_t w
);
171 static void push_long (struct X86EMU
*, uint32_t w
);
172 static uint16_t pop_word (struct X86EMU
*);
173 static uint32_t pop_long (struct X86EMU
*);
175 /****************************************************************************
177 Handles any pending asychronous interrupts.
178 ****************************************************************************/
180 x86emu_intr_dispatch(struct X86EMU
*emu
, uint8_t intno
)
182 if (emu
->_X86EMU_intrTab
[intno
]) {
183 (*emu
->_X86EMU_intrTab
[intno
]) (emu
, intno
);
185 push_word(emu
, (uint16_t) emu
->x86
.R_FLG
);
188 push_word(emu
, emu
->x86
.R_CS
);
189 emu
->x86
.R_CS
= fetch_word(emu
, 0, intno
* 4 + 2);
190 push_word(emu
, emu
->x86
.R_IP
);
191 emu
->x86
.R_IP
= fetch_word(emu
, 0, intno
* 4);
196 x86emu_intr_handle(struct X86EMU
*emu
)
200 if (emu
->x86
.intr
& INTR_SYNCH
) {
201 intno
= emu
->x86
.intno
;
203 x86emu_intr_dispatch(emu
, intno
);
206 /****************************************************************************
208 intrnum - Interrupt number to raise
211 Raise the specified interrupt to be handled before the execution of the
213 ****************************************************************************/
215 x86emu_intr_raise(struct X86EMU
*emu
, uint8_t intrnum
)
217 emu
->x86
.intno
= intrnum
;
218 emu
->x86
.intr
|= INTR_SYNCH
;
220 /****************************************************************************
222 Main execution loop for the emulator. We return from here when the system
223 halts, which is normally caused by a stack fault when we return from the
224 original real mode call.
225 ****************************************************************************/
227 X86EMU_exec(struct X86EMU
*emu
)
232 if (setjmp(&emu
->exec_state
))
235 if (setjmp(emu
->exec_state
))
241 if (((emu
->x86
.intr
& INTR_SYNCH
) && (emu
->x86
.intno
== 0 || emu
->x86
.intno
== 2)) ||
242 !ACCESS_FLAG(F_IF
)) {
243 x86emu_intr_handle(emu
);
246 if (emu
->x86
.R_CS
== 0 && emu
->x86
.R_IP
== 0)
248 X86EMU_exec_one_byte(emu
);
254 X86EMU_exec_call(struct X86EMU
*emu
, uint16_t seg
, uint16_t off
)
265 X86EMU_exec_intr(struct X86EMU
*emu
, uint8_t intr
)
267 push_word(emu
, emu
->x86
.R_FLG
);
272 emu
->x86
.R_CS
= (*emu
->emu_rdw
)(emu
, intr
* 4 + 2);
273 emu
->x86
.R_IP
= (*emu
->emu_rdw
)(emu
, intr
* 4);
278 /****************************************************************************
280 Halts the system by setting the halted system flag.
281 ****************************************************************************/
283 X86EMU_halt_sys(struct X86EMU
*emu
)
286 longjmp(&emu
->exec_state
);
288 longjmp(emu
->exec_state
, 1);
291 /****************************************************************************
293 mod - Mod value from decoded byte
294 regh - Reg h value from decoded byte
295 regl - Reg l value from decoded byte
298 Raise the specified interrupt to be handled before the execution of the
301 NOTE: Do not inline this function, as (*emu->emu_rdb) is already inline!
302 ****************************************************************************/
304 fetch_decode_modrm(struct X86EMU
*emu
)
308 fetched
= fetch_byte_imm(emu
);
309 emu
->cur_mod
= (fetched
>> 6) & 0x03;
310 emu
->cur_rh
= (fetched
>> 3) & 0x07;
311 emu
->cur_rl
= (fetched
>> 0) & 0x07;
313 /****************************************************************************
315 Immediate byte value read from instruction queue
318 This function returns the immediate byte from the instruction queue, and
319 moves the instruction pointer to the next value.
321 NOTE: Do not inline this function, as (*emu->emu_rdb) is already inline!
322 ****************************************************************************/
324 fetch_byte_imm(struct X86EMU
*emu
)
328 fetched
= fetch_byte(emu
, emu
->x86
.R_CS
, emu
->x86
.R_IP
);
332 /****************************************************************************
334 Immediate word value read from instruction queue
337 This function returns the immediate byte from the instruction queue, and
338 moves the instruction pointer to the next value.
340 NOTE: Do not inline this function, as (*emu->emu_rdw) is already inline!
341 ****************************************************************************/
343 fetch_word_imm(struct X86EMU
*emu
)
347 fetched
= fetch_word(emu
, emu
->x86
.R_CS
, emu
->x86
.R_IP
);
351 /****************************************************************************
353 Immediate lone value read from instruction queue
356 This function returns the immediate byte from the instruction queue, and
357 moves the instruction pointer to the next value.
359 NOTE: Do not inline this function, as (*emu->emu_rdw) is already inline!
360 ****************************************************************************/
362 fetch_long_imm(struct X86EMU
*emu
)
366 fetched
= fetch_long(emu
, emu
->x86
.R_CS
, emu
->x86
.R_IP
);
370 /****************************************************************************
372 Value of the default data segment
375 Inline function that returns the default data segment for the current
378 On the x86 processor, the default segment is not always DS if there is
379 no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to
380 addresses relative to SS (ie: on the stack). So, at the minimum, all
381 decodings of addressing modes would have to set/clear a bit describing
382 whether the access is relative to DS or SS. That is the function of the
383 cpu-state-varible emu->x86.mode. There are several potential states:
385 repe prefix seen (handled elsewhere)
386 repne prefix seen (ditto)
395 ds/ss select (in absense of override)
397 Each of the above 7 items are handled with a bit in the mode field.
398 ****************************************************************************/
400 get_data_segment(struct X86EMU
*emu
)
402 switch (emu
->x86
.mode
& SYSMODE_SEGMASK
) {
403 case 0: /* default case: use ds register */
404 case SYSMODE_SEGOVR_DS
:
405 case SYSMODE_SEGOVR_DS
| SYSMODE_SEG_DS_SS
:
406 return emu
->x86
.R_DS
;
407 case SYSMODE_SEG_DS_SS
:/* non-overridden, use ss register */
408 return emu
->x86
.R_SS
;
409 case SYSMODE_SEGOVR_CS
:
410 case SYSMODE_SEGOVR_CS
| SYSMODE_SEG_DS_SS
:
411 return emu
->x86
.R_CS
;
412 case SYSMODE_SEGOVR_ES
:
413 case SYSMODE_SEGOVR_ES
| SYSMODE_SEG_DS_SS
:
414 return emu
->x86
.R_ES
;
415 case SYSMODE_SEGOVR_FS
:
416 case SYSMODE_SEGOVR_FS
| SYSMODE_SEG_DS_SS
:
417 return emu
->x86
.R_FS
;
418 case SYSMODE_SEGOVR_GS
:
419 case SYSMODE_SEGOVR_GS
| SYSMODE_SEG_DS_SS
:
420 return emu
->x86
.R_GS
;
421 case SYSMODE_SEGOVR_SS
:
422 case SYSMODE_SEGOVR_SS
| SYSMODE_SEG_DS_SS
:
423 return emu
->x86
.R_SS
;
425 X86EMU_halt_sys(emu
);
427 /****************************************************************************
429 offset - Offset to load data from
432 Byte value read from the absolute memory location.
434 NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
435 ****************************************************************************/
437 fetch_data_byte(struct X86EMU
*emu
, uint32_t offset
)
439 return fetch_byte(emu
, get_data_segment(emu
), offset
);
441 /****************************************************************************
443 offset - Offset to load data from
446 Word value read from the absolute memory location.
448 NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
449 ****************************************************************************/
451 fetch_data_word(struct X86EMU
*emu
, uint32_t offset
)
453 return fetch_word(emu
, get_data_segment(emu
), offset
);
455 /****************************************************************************
457 offset - Offset to load data from
460 Long value read from the absolute memory location.
462 NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
463 ****************************************************************************/
465 fetch_data_long(struct X86EMU
*emu
, uint32_t offset
)
467 return fetch_long(emu
, get_data_segment(emu
), offset
);
469 /****************************************************************************
471 segment - Segment to load data from
472 offset - Offset to load data from
475 Byte value read from the absolute memory location.
477 NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
478 ****************************************************************************/
480 fetch_byte(struct X86EMU
*emu
, uint32_t segment
, uint32_t offset
)
482 return (*emu
->emu_rdb
) (emu
, ((uint32_t) segment
<< 4) + offset
);
484 /****************************************************************************
486 segment - Segment to load data from
487 offset - Offset to load data from
490 Word value read from the absolute memory location.
492 NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
493 ****************************************************************************/
495 fetch_word(struct X86EMU
*emu
, uint32_t segment
, uint32_t offset
)
497 return (*emu
->emu_rdw
) (emu
, ((uint32_t) segment
<< 4) + offset
);
499 /****************************************************************************
501 segment - Segment to load data from
502 offset - Offset to load data from
505 Long value read from the absolute memory location.
507 NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
508 ****************************************************************************/
510 fetch_long(struct X86EMU
*emu
, uint32_t segment
, uint32_t offset
)
512 return (*emu
->emu_rdl
) (emu
, ((uint32_t) segment
<< 4) + offset
);
514 /****************************************************************************
516 offset - Offset to store data at
520 Writes a word value to an segmented memory location. The segment used is
521 the current 'default' segment, which may have been overridden.
523 NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
524 ****************************************************************************/
526 store_data_byte(struct X86EMU
*emu
, uint32_t offset
, uint8_t val
)
528 store_byte(emu
, get_data_segment(emu
), offset
, val
);
530 /****************************************************************************
532 offset - Offset to store data at
536 Writes a word value to an segmented memory location. The segment used is
537 the current 'default' segment, which may have been overridden.
539 NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
540 ****************************************************************************/
542 store_data_word(struct X86EMU
*emu
, uint32_t offset
, uint16_t val
)
544 store_word(emu
, get_data_segment(emu
), offset
, val
);
546 /****************************************************************************
548 offset - Offset to store data at
552 Writes a long value to an segmented memory location. The segment used is
553 the current 'default' segment, which may have been overridden.
555 NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
556 ****************************************************************************/
558 store_data_long(struct X86EMU
*emu
, uint32_t offset
, uint32_t val
)
560 store_long(emu
, get_data_segment(emu
), offset
, val
);
562 /****************************************************************************
564 segment - Segment to store data at
565 offset - Offset to store data at
569 Writes a byte value to an absolute memory location.
571 NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
572 ****************************************************************************/
574 store_byte(struct X86EMU
*emu
, uint32_t segment
, uint32_t offset
, uint8_t val
)
576 (*emu
->emu_wrb
) (emu
, ((uint32_t) segment
<< 4) + offset
, val
);
578 /****************************************************************************
580 segment - Segment to store data at
581 offset - Offset to store data at
585 Writes a word value to an absolute memory location.
587 NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
588 ****************************************************************************/
590 store_word(struct X86EMU
*emu
, uint32_t segment
, uint32_t offset
, uint16_t val
)
592 (*emu
->emu_wrw
) (emu
, ((uint32_t) segment
<< 4) + offset
, val
);
594 /****************************************************************************
596 segment - Segment to store data at
597 offset - Offset to store data at
601 Writes a long value to an absolute memory location.
603 NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
604 ****************************************************************************/
606 store_long(struct X86EMU
*emu
, uint32_t segment
, uint32_t offset
, uint32_t val
)
608 (*emu
->emu_wrl
) (emu
, ((uint32_t) segment
<< 4) + offset
, val
);
610 /****************************************************************************
612 reg - Register to decode
615 Pointer to the appropriate register
618 Return a pointer to the register given by the R/RM field of the
619 modrm byte, for byte operands. Also enables the decoding of instructions.
620 ****************************************************************************/
622 decode_rm_byte_register(struct X86EMU
*emu
, int reg
)
626 return &emu
->x86
.R_AL
;
628 return &emu
->x86
.R_CL
;
630 return &emu
->x86
.R_DL
;
632 return &emu
->x86
.R_BL
;
634 return &emu
->x86
.R_AH
;
636 return &emu
->x86
.R_CH
;
638 return &emu
->x86
.R_DH
;
640 return &emu
->x86
.R_BH
;
642 X86EMU_halt_sys(emu
);
647 decode_rl_byte_register(struct X86EMU
*emu
)
649 return decode_rm_byte_register(emu
, emu
->cur_rl
);
653 decode_rh_byte_register(struct X86EMU
*emu
)
655 return decode_rm_byte_register(emu
, emu
->cur_rh
);
657 /****************************************************************************
659 reg - Register to decode
662 Pointer to the appropriate register
665 Return a pointer to the register given by the R/RM field of the
666 modrm byte, for word operands. Also enables the decoding of instructions.
667 ****************************************************************************/
669 decode_rm_word_register(struct X86EMU
*emu
, int reg
)
673 return &emu
->x86
.R_AX
;
675 return &emu
->x86
.R_CX
;
677 return &emu
->x86
.R_DX
;
679 return &emu
->x86
.R_BX
;
681 return &emu
->x86
.R_SP
;
683 return &emu
->x86
.R_BP
;
685 return &emu
->x86
.R_SI
;
687 return &emu
->x86
.R_DI
;
689 X86EMU_halt_sys(emu
);
694 decode_rl_word_register(struct X86EMU
*emu
)
696 return decode_rm_word_register(emu
, emu
->cur_rl
);
700 decode_rh_word_register(struct X86EMU
*emu
)
702 return decode_rm_word_register(emu
, emu
->cur_rh
);
704 /****************************************************************************
706 reg - Register to decode
709 Pointer to the appropriate register
712 Return a pointer to the register given by the R/RM field of the
713 modrm byte, for dword operands. Also enables the decoding of instructions.
714 ****************************************************************************/
716 decode_rm_long_register(struct X86EMU
*emu
, int reg
)
720 return &emu
->x86
.R_EAX
;
722 return &emu
->x86
.R_ECX
;
724 return &emu
->x86
.R_EDX
;
726 return &emu
->x86
.R_EBX
;
728 return &emu
->x86
.R_ESP
;
730 return &emu
->x86
.R_EBP
;
732 return &emu
->x86
.R_ESI
;
734 return &emu
->x86
.R_EDI
;
736 X86EMU_halt_sys(emu
);
741 decode_rl_long_register(struct X86EMU
*emu
)
743 return decode_rm_long_register(emu
, emu
->cur_rl
);
747 decode_rh_long_register(struct X86EMU
*emu
)
749 return decode_rm_long_register(emu
, emu
->cur_rh
);
752 /****************************************************************************
754 reg - Register to decode
757 Pointer to the appropriate register
760 Return a pointer to the register given by the R/RM field of the
761 modrm byte, for word operands, modified from above for the weirdo
762 special case of segreg operands. Also enables the decoding of instructions.
763 ****************************************************************************/
765 decode_rh_seg_register(struct X86EMU
*emu
)
767 switch (emu
->cur_rh
) {
769 return &emu
->x86
.R_ES
;
771 return &emu
->x86
.R_CS
;
773 return &emu
->x86
.R_SS
;
775 return &emu
->x86
.R_DS
;
777 return &emu
->x86
.R_FS
;
779 return &emu
->x86
.R_GS
;
781 X86EMU_halt_sys(emu
);
786 * return offset from the SIB Byte
789 decode_sib_address(struct X86EMU
*emu
, int sib
, int mod
)
791 uint32_t base
= 0, i
= 0, scale
= 1;
793 switch (sib
& 0x07) {
795 base
= emu
->x86
.R_EAX
;
798 base
= emu
->x86
.R_ECX
;
801 base
= emu
->x86
.R_EDX
;
804 base
= emu
->x86
.R_EBX
;
807 base
= emu
->x86
.R_ESP
;
808 emu
->x86
.mode
|= SYSMODE_SEG_DS_SS
;
812 base
= fetch_long_imm(emu
);
814 base
= emu
->x86
.R_EBP
;
815 emu
->x86
.mode
|= SYSMODE_SEG_DS_SS
;
819 base
= emu
->x86
.R_ESI
;
822 base
= emu
->x86
.R_EDI
;
825 switch ((sib
>> 3) & 0x07) {
851 scale
= 1 << ((sib
>> 6) & 0x03);
852 return base
+ (i
* scale
);
854 /****************************************************************************
856 rm - RM value to decode
859 Offset in memory for the address decoding
862 Return the offset given by mod=00, mod=01 or mod=10 addressing.
863 Also enables the decoding of instructions.
864 ****************************************************************************/
866 decode_rl_address(struct X86EMU
*emu
)
868 if (emu
->x86
.mode
& SYSMODE_PREFIX_ADDR
) {
869 uint32_t offset
, sib
;
870 /* 32-bit addressing */
871 switch (emu
->cur_rl
) {
873 offset
= emu
->x86
.R_EAX
;
876 offset
= emu
->x86
.R_ECX
;
879 offset
= emu
->x86
.R_EDX
;
882 offset
= emu
->x86
.R_EBX
;
885 sib
= fetch_byte_imm(emu
);
886 offset
= decode_sib_address(emu
, sib
, 0);
889 if (emu
->cur_mod
== 0) {
890 offset
= fetch_long_imm(emu
);
892 emu
->x86
.mode
|= SYSMODE_SEG_DS_SS
;
893 offset
= emu
->x86
.R_EBP
;
897 offset
= emu
->x86
.R_ESI
;
900 offset
= emu
->x86
.R_EDI
;
903 X86EMU_halt_sys(emu
);
905 if (emu
->cur_mod
== 1)
906 offset
+= (int8_t)fetch_byte_imm(emu
);
907 else if (emu
->cur_mod
== 2)
908 offset
+= fetch_long_imm(emu
);
913 /* 16-bit addressing */
914 switch (emu
->cur_rl
) {
916 offset
= emu
->x86
.R_BX
+ emu
->x86
.R_SI
;
919 offset
= emu
->x86
.R_BX
+ emu
->x86
.R_DI
;
922 emu
->x86
.mode
|= SYSMODE_SEG_DS_SS
;
923 offset
= emu
->x86
.R_BP
+ emu
->x86
.R_SI
;
926 emu
->x86
.mode
|= SYSMODE_SEG_DS_SS
;
927 offset
= emu
->x86
.R_BP
+ emu
->x86
.R_DI
;
930 offset
= emu
->x86
.R_SI
;
933 offset
= emu
->x86
.R_DI
;
936 if (emu
->cur_mod
== 0) {
937 offset
= fetch_word_imm(emu
);
939 emu
->x86
.mode
|= SYSMODE_SEG_DS_SS
;
940 offset
= emu
->x86
.R_BP
;
944 offset
= emu
->x86
.R_BX
;
947 X86EMU_halt_sys(emu
);
949 if (emu
->cur_mod
== 1)
950 offset
+= (int8_t)fetch_byte_imm(emu
);
951 else if (emu
->cur_mod
== 2)
952 offset
+= fetch_word_imm(emu
);
958 decode_and_fetch_byte(struct X86EMU
*emu
)
960 if (emu
->cur_mod
!= 3) {
961 emu
->cur_offset
= decode_rl_address(emu
);
962 return fetch_data_byte(emu
, emu
->cur_offset
);
964 return *decode_rl_byte_register(emu
);
969 decode_and_fetch_word_disp(struct X86EMU
*emu
, int16_t disp
)
971 if (emu
->cur_mod
!= 3) {
972 /* TODO: A20 gate emulation */
973 emu
->cur_offset
= decode_rl_address(emu
) + disp
;
974 if ((emu
->x86
.mode
& SYSMODE_PREFIX_ADDR
) == 0)
975 emu
->cur_offset
&= 0xffff;
976 return fetch_data_word(emu
, emu
->cur_offset
);
978 return *decode_rl_word_register(emu
);
983 decode_and_fetch_long_disp(struct X86EMU
*emu
, int16_t disp
)
985 if (emu
->cur_mod
!= 3) {
986 /* TODO: A20 gate emulation */
987 emu
->cur_offset
= decode_rl_address(emu
) + disp
;
988 if ((emu
->x86
.mode
& SYSMODE_PREFIX_ADDR
) == 0)
989 emu
->cur_offset
&= 0xffff;
990 return fetch_data_long(emu
, emu
->cur_offset
);
992 return *decode_rl_long_register(emu
);
997 decode_and_fetch_word(struct X86EMU
*emu
)
999 return decode_and_fetch_word_disp(emu
, 0);
1003 decode_and_fetch_long(struct X86EMU
*emu
)
1005 return decode_and_fetch_long_disp(emu
, 0);
1009 decode_and_fetch_byte_imm8(struct X86EMU
*emu
, uint8_t *imm
)
1011 if (emu
->cur_mod
!= 3) {
1012 emu
->cur_offset
= decode_rl_address(emu
);
1013 *imm
= fetch_byte_imm(emu
);
1014 return fetch_data_byte(emu
, emu
->cur_offset
);
1016 *imm
= fetch_byte_imm(emu
);
1017 return *decode_rl_byte_register(emu
);
1022 decode_and_fetch_word_imm8(struct X86EMU
*emu
, uint8_t *imm
)
1024 if (emu
->cur_mod
!= 3) {
1025 emu
->cur_offset
= decode_rl_address(emu
);
1026 *imm
= fetch_byte_imm(emu
);
1027 return fetch_data_word(emu
, emu
->cur_offset
);
1029 *imm
= fetch_byte_imm(emu
);
1030 return *decode_rl_word_register(emu
);
1035 decode_and_fetch_long_imm8(struct X86EMU
*emu
, uint8_t *imm
)
1037 if (emu
->cur_mod
!= 3) {
1038 emu
->cur_offset
= decode_rl_address(emu
);
1039 *imm
= fetch_byte_imm(emu
);
1040 return fetch_data_long(emu
, emu
->cur_offset
);
1042 *imm
= fetch_byte_imm(emu
);
1043 return *decode_rl_long_register(emu
);
1048 write_back_byte(struct X86EMU
*emu
, uint8_t val
)
1050 if (emu
->cur_mod
!= 3)
1051 store_data_byte(emu
, emu
->cur_offset
, val
);
1053 *decode_rl_byte_register(emu
) = val
;
1057 write_back_word(struct X86EMU
*emu
, uint16_t val
)
1059 if (emu
->cur_mod
!= 3)
1060 store_data_word(emu
, emu
->cur_offset
, val
);
1062 *decode_rl_word_register(emu
) = val
;
1066 write_back_long(struct X86EMU
*emu
, uint32_t val
)
1068 if (emu
->cur_mod
!= 3)
1069 store_data_long(emu
, emu
->cur_offset
, val
);
1071 *decode_rl_long_register(emu
) = val
;
1075 common_inc_word_long(struct X86EMU
*emu
, union X86EMU_register
*reg
)
1077 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
1078 reg
->I32_reg
.e_reg
= inc_long(emu
, reg
->I32_reg
.e_reg
);
1080 reg
->I16_reg
.x_reg
= inc_word(emu
, reg
->I16_reg
.x_reg
);
1084 common_dec_word_long(struct X86EMU
*emu
, union X86EMU_register
*reg
)
1086 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
1087 reg
->I32_reg
.e_reg
= dec_long(emu
, reg
->I32_reg
.e_reg
);
1089 reg
->I16_reg
.x_reg
= dec_word(emu
, reg
->I16_reg
.x_reg
);
1093 common_binop_byte_rm_r(struct X86EMU
*emu
, uint8_t (*binop
)(struct X86EMU
*, uint8_t, uint8_t))
1095 uint32_t destoffset
;
1096 uint8_t *destreg
, srcval
;
1099 fetch_decode_modrm(emu
);
1100 srcval
= *decode_rh_byte_register(emu
);
1101 if (emu
->cur_mod
!= 3) {
1102 destoffset
= decode_rl_address(emu
);
1103 destval
= fetch_data_byte(emu
, destoffset
);
1104 destval
= (*binop
)(emu
, destval
, srcval
);
1105 store_data_byte(emu
, destoffset
, destval
);
1107 destreg
= decode_rl_byte_register(emu
);
1108 *destreg
= (*binop
)(emu
, *destreg
, srcval
);
1113 common_binop_ns_byte_rm_r(struct X86EMU
*emu
, void (*binop
)(struct X86EMU
*, uint8_t, uint8_t))
1115 uint32_t destoffset
;
1116 uint8_t destval
, srcval
;
1118 fetch_decode_modrm(emu
);
1119 srcval
= *decode_rh_byte_register(emu
);
1120 if (emu
->cur_mod
!= 3) {
1121 destoffset
= decode_rl_address(emu
);
1122 destval
= fetch_data_byte(emu
, destoffset
);
1124 destval
= *decode_rl_byte_register(emu
);
1126 (*binop
)(emu
, destval
, srcval
);
1130 common_binop_word_rm_r(struct X86EMU
*emu
, uint16_t (*binop
)(struct X86EMU
*, uint16_t, uint16_t))
1132 uint32_t destoffset
;
1133 uint16_t destval
, *destreg
, srcval
;
1135 fetch_decode_modrm(emu
);
1136 srcval
= *decode_rh_word_register(emu
);
1137 if (emu
->cur_mod
!= 3) {
1138 destoffset
= decode_rl_address(emu
);
1139 destval
= fetch_data_word(emu
, destoffset
);
1140 destval
= (*binop
)(emu
, destval
, srcval
);
1141 store_data_word(emu
, destoffset
, destval
);
1143 destreg
= decode_rl_word_register(emu
);
1144 *destreg
= (*binop
)(emu
, *destreg
, srcval
);
1149 common_binop_byte_r_rm(struct X86EMU
*emu
, uint8_t (*binop
)(struct X86EMU
*, uint8_t, uint8_t))
1151 uint8_t *destreg
, srcval
;
1154 fetch_decode_modrm(emu
);
1155 destreg
= decode_rh_byte_register(emu
);
1156 if (emu
->cur_mod
!= 3) {
1157 srcoffset
= decode_rl_address(emu
);
1158 srcval
= fetch_data_byte(emu
, srcoffset
);
1160 srcval
= *decode_rl_byte_register(emu
);
1162 *destreg
= (*binop
)(emu
, *destreg
, srcval
);
1166 common_binop_long_rm_r(struct X86EMU
*emu
, uint32_t (*binop
)(struct X86EMU
*, uint32_t, uint32_t))
1168 uint32_t destoffset
;
1169 uint32_t destval
, *destreg
, srcval
;
1171 fetch_decode_modrm(emu
);
1172 srcval
= *decode_rh_long_register(emu
);
1173 if (emu
->cur_mod
!= 3) {
1174 destoffset
= decode_rl_address(emu
);
1175 destval
= fetch_data_long(emu
, destoffset
);
1176 destval
= (*binop
)(emu
, destval
, srcval
);
1177 store_data_long(emu
, destoffset
, destval
);
1179 destreg
= decode_rl_long_register(emu
);
1180 *destreg
= (*binop
)(emu
, *destreg
, srcval
);
1185 common_binop_word_long_rm_r(struct X86EMU
*emu
,
1186 uint16_t (*binop16
)(struct X86EMU
*, uint16_t, uint16_t), uint32_t (*binop32
)(struct X86EMU
*, uint32_t, uint32_t))
1188 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
1189 common_binop_long_rm_r(emu
, binop32
);
1191 common_binop_word_rm_r(emu
, binop16
);
1195 common_binop_ns_word_rm_r(struct X86EMU
*emu
, void (*binop
)(struct X86EMU
*, uint16_t, uint16_t))
1197 uint32_t destoffset
;
1198 uint16_t destval
, srcval
;
1200 fetch_decode_modrm(emu
);
1201 srcval
= *decode_rh_word_register(emu
);
1202 if (emu
->cur_mod
!= 3) {
1203 destoffset
= decode_rl_address(emu
);
1204 destval
= fetch_data_word(emu
, destoffset
);
1206 destval
= *decode_rl_word_register(emu
);
1208 (*binop
)(emu
, destval
, srcval
);
1213 common_binop_ns_long_rm_r(struct X86EMU
*emu
, void (*binop
)(struct X86EMU
*, uint32_t, uint32_t))
1215 uint32_t destoffset
;
1216 uint32_t destval
, srcval
;
1218 fetch_decode_modrm(emu
);
1219 srcval
= *decode_rh_long_register(emu
);
1220 if (emu
->cur_mod
!= 3) {
1221 destoffset
= decode_rl_address(emu
);
1222 destval
= fetch_data_long(emu
, destoffset
);
1224 destval
= *decode_rl_long_register(emu
);
1226 (*binop
)(emu
, destval
, srcval
);
1230 common_binop_ns_word_long_rm_r(struct X86EMU
*emu
,
1231 void (*binop16
)(struct X86EMU
*, uint16_t, uint16_t), void (*binop32
)(struct X86EMU
*, uint32_t, uint32_t))
1233 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
1234 common_binop_ns_long_rm_r(emu
, binop32
);
1236 common_binop_ns_word_rm_r(emu
, binop16
);
1240 common_binop_long_r_rm(struct X86EMU
*emu
, uint32_t (*binop
)(struct X86EMU
*, uint32_t, uint32_t))
1243 uint32_t *destreg
, srcval
;
1245 fetch_decode_modrm(emu
);
1246 destreg
= decode_rh_long_register(emu
);
1247 if (emu
->cur_mod
!= 3) {
1248 srcoffset
= decode_rl_address(emu
);
1249 srcval
= fetch_data_long(emu
, srcoffset
);
1251 srcval
= *decode_rl_long_register(emu
);
1253 *destreg
= (*binop
)(emu
, *destreg
, srcval
);
1257 common_binop_word_r_rm(struct X86EMU
*emu
, uint16_t (*binop
)(struct X86EMU
*, uint16_t, uint16_t))
1260 uint16_t *destreg
, srcval
;
1262 fetch_decode_modrm(emu
);
1263 destreg
= decode_rh_word_register(emu
);
1264 if (emu
->cur_mod
!= 3) {
1265 srcoffset
= decode_rl_address(emu
);
1266 srcval
= fetch_data_word(emu
, srcoffset
);
1268 srcval
= *decode_rl_word_register(emu
);
1270 *destreg
= (*binop
)(emu
, *destreg
, srcval
);
1274 common_binop_word_long_r_rm(struct X86EMU
*emu
,
1275 uint16_t (*binop16
)(struct X86EMU
*, uint16_t, uint16_t), uint32_t (*binop32
)(struct X86EMU
*, uint32_t, uint32_t))
1277 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
1278 common_binop_long_r_rm(emu
, binop32
);
1280 common_binop_word_r_rm(emu
, binop16
);
1284 common_binop_byte_imm(struct X86EMU
*emu
, uint8_t (*binop
)(struct X86EMU
*, uint8_t, uint8_t))
1288 srcval
= fetch_byte_imm(emu
);
1289 emu
->x86
.R_AL
= (*binop
)(emu
, emu
->x86
.R_AL
, srcval
);
1293 common_binop_word_long_imm(struct X86EMU
*emu
,
1294 uint16_t (*binop16
)(struct X86EMU
*, uint16_t, uint16_t), uint32_t (*binop32
)(struct X86EMU
*, uint32_t, uint32_t))
1296 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
1299 srcval
= fetch_long_imm(emu
);
1300 emu
->x86
.R_EAX
= (*binop32
)(emu
, emu
->x86
.R_EAX
, srcval
);
1304 srcval
= fetch_word_imm(emu
);
1305 emu
->x86
.R_AX
= (*binop16
)(emu
, emu
->x86
.R_AX
, srcval
);
1310 common_push_word_long(struct X86EMU
*emu
, union X86EMU_register
*reg
)
1312 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
1313 push_long(emu
, reg
->I32_reg
.e_reg
);
1315 push_word(emu
, reg
->I16_reg
.x_reg
);
1319 common_pop_word_long(struct X86EMU
*emu
, union X86EMU_register
*reg
)
1321 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
1322 reg
->I32_reg
.e_reg
= pop_long(emu
);
1324 reg
->I16_reg
.x_reg
= pop_word(emu
);
1328 common_imul_long_IMM(struct X86EMU
*emu
, bool byte_imm
)
1331 uint32_t *destreg
, srcval
;
1335 fetch_decode_modrm(emu
);
1336 destreg
= decode_rh_long_register(emu
);
1337 if (emu
->cur_mod
!= 3) {
1338 srcoffset
= decode_rl_address(emu
);
1339 srcval
= fetch_data_long(emu
, srcoffset
);
1341 srcval
= *decode_rl_long_register(emu
);
1345 imm
= (int8_t)fetch_byte_imm(emu
);
1347 imm
= fetch_long_imm(emu
);
1348 res
= (int32_t)srcval
* imm
;
1350 if (res
> 0xffffffff) {
1357 *destreg
= (uint32_t)res
;
1361 common_imul_word_IMM(struct X86EMU
*emu
, bool byte_imm
)
1364 uint16_t *destreg
, srcval
;
1368 fetch_decode_modrm(emu
);
1369 destreg
= decode_rh_word_register(emu
);
1370 if (emu
->cur_mod
!= 3) {
1371 srcoffset
= decode_rl_address(emu
);
1372 srcval
= fetch_data_word(emu
, srcoffset
);
1374 srcval
= *decode_rl_word_register(emu
);
1378 imm
= (int8_t)fetch_byte_imm(emu
);
1380 imm
= fetch_word_imm(emu
);
1381 res
= (int16_t)srcval
* imm
;
1390 *destreg
= (uint16_t) res
;
1394 common_imul_imm(struct X86EMU
*emu
, bool byte_imm
)
1396 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
1397 common_imul_long_IMM(emu
, byte_imm
);
1399 common_imul_word_IMM(emu
, byte_imm
);
1403 common_jmp_near(struct X86EMU
*emu
, bool cond
)
1408 offset
= (int8_t) fetch_byte_imm(emu
);
1409 target
= (uint16_t) (emu
->x86
.R_IP
+ (int16_t) offset
);
1411 emu
->x86
.R_IP
= target
;
1415 common_load_far_pointer(struct X86EMU
*emu
, uint16_t *seg
)
1420 fetch_decode_modrm(emu
);
1421 if (emu
->cur_mod
== 3)
1422 X86EMU_halt_sys(emu
);
1424 dstreg
= decode_rh_word_register(emu
);
1425 srcoffset
= decode_rl_address(emu
);
1426 *dstreg
= fetch_data_word(emu
, srcoffset
);
1427 *seg
= fetch_data_word(emu
, srcoffset
+ 2);
1430 /*----------------------------- Implementation ----------------------------*/
1431 /****************************************************************************
1434 ****************************************************************************/
1436 x86emuOp_cmp_byte_R_RM(struct X86EMU
*emu
)
1438 uint8_t *destreg
, srcval
;
1440 fetch_decode_modrm(emu
);
1441 destreg
= decode_rh_byte_register(emu
);
1442 srcval
= decode_and_fetch_byte(emu
);
1443 cmp_byte(emu
, *destreg
, srcval
);
1445 /****************************************************************************
1448 ****************************************************************************/
1450 x86emuOp32_cmp_word_R_RM(struct X86EMU
*emu
)
1452 uint32_t srcval
, *destreg
;
1454 fetch_decode_modrm(emu
);
1455 destreg
= decode_rh_long_register(emu
);
1456 srcval
= decode_and_fetch_long(emu
);
1457 cmp_long(emu
, *destreg
, srcval
);
1461 x86emuOp16_cmp_word_R_RM(struct X86EMU
*emu
)
1463 uint16_t srcval
, *destreg
;
1465 fetch_decode_modrm(emu
);
1466 destreg
= decode_rh_word_register(emu
);
1467 srcval
= decode_and_fetch_word(emu
);
1468 cmp_word(emu
, *destreg
, srcval
);
1472 x86emuOp_cmp_word_R_RM(struct X86EMU
*emu
)
1474 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
1475 x86emuOp32_cmp_word_R_RM(emu
);
1477 x86emuOp16_cmp_word_R_RM(emu
);
1479 /****************************************************************************
1482 ****************************************************************************/
1484 x86emuOp_cmp_byte_AL_IMM(struct X86EMU
*emu
)
1488 srcval
= fetch_byte_imm(emu
);
1489 cmp_byte(emu
, emu
->x86
.R_AL
, srcval
);
1491 /****************************************************************************
1494 ****************************************************************************/
1496 x86emuOp32_cmp_word_AX_IMM(struct X86EMU
*emu
)
1500 srcval
= fetch_long_imm(emu
);
1501 cmp_long(emu
, emu
->x86
.R_EAX
, srcval
);
1505 x86emuOp16_cmp_word_AX_IMM(struct X86EMU
*emu
)
1509 srcval
= fetch_word_imm(emu
);
1510 cmp_word(emu
, emu
->x86
.R_AX
, srcval
);
1514 x86emuOp_cmp_word_AX_IMM(struct X86EMU
*emu
)
1516 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
1517 x86emuOp32_cmp_word_AX_IMM(emu
);
1519 x86emuOp16_cmp_word_AX_IMM(emu
);
1521 /****************************************************************************
1524 ****************************************************************************/
1526 x86emuOp_push_all(struct X86EMU
*emu
)
1528 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
1529 uint32_t old_sp
= emu
->x86
.R_ESP
;
1531 push_long(emu
, emu
->x86
.R_EAX
);
1532 push_long(emu
, emu
->x86
.R_ECX
);
1533 push_long(emu
, emu
->x86
.R_EDX
);
1534 push_long(emu
, emu
->x86
.R_EBX
);
1535 push_long(emu
, old_sp
);
1536 push_long(emu
, emu
->x86
.R_EBP
);
1537 push_long(emu
, emu
->x86
.R_ESI
);
1538 push_long(emu
, emu
->x86
.R_EDI
);
1540 uint16_t old_sp
= emu
->x86
.R_SP
;
1542 push_word(emu
, emu
->x86
.R_AX
);
1543 push_word(emu
, emu
->x86
.R_CX
);
1544 push_word(emu
, emu
->x86
.R_DX
);
1545 push_word(emu
, emu
->x86
.R_BX
);
1546 push_word(emu
, old_sp
);
1547 push_word(emu
, emu
->x86
.R_BP
);
1548 push_word(emu
, emu
->x86
.R_SI
);
1549 push_word(emu
, emu
->x86
.R_DI
);
1552 /****************************************************************************
1555 ****************************************************************************/
1557 x86emuOp_pop_all(struct X86EMU
*emu
)
1559 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
1560 emu
->x86
.R_EDI
= pop_long(emu
);
1561 emu
->x86
.R_ESI
= pop_long(emu
);
1562 emu
->x86
.R_EBP
= pop_long(emu
);
1563 emu
->x86
.R_ESP
+= 4; /* skip ESP */
1564 emu
->x86
.R_EBX
= pop_long(emu
);
1565 emu
->x86
.R_EDX
= pop_long(emu
);
1566 emu
->x86
.R_ECX
= pop_long(emu
);
1567 emu
->x86
.R_EAX
= pop_long(emu
);
1569 emu
->x86
.R_DI
= pop_word(emu
);
1570 emu
->x86
.R_SI
= pop_word(emu
);
1571 emu
->x86
.R_BP
= pop_word(emu
);
1572 emu
->x86
.R_SP
+= 2;/* skip SP */
1573 emu
->x86
.R_BX
= pop_word(emu
);
1574 emu
->x86
.R_DX
= pop_word(emu
);
1575 emu
->x86
.R_CX
= pop_word(emu
);
1576 emu
->x86
.R_AX
= pop_word(emu
);
1579 /*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */
1580 /*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */
1582 /****************************************************************************
1585 ****************************************************************************/
1587 x86emuOp_push_word_IMM(struct X86EMU
*emu
)
1589 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
1592 imm
= fetch_long_imm(emu
);
1593 push_long(emu
, imm
);
1597 imm
= fetch_word_imm(emu
);
1598 push_word(emu
, imm
);
1601 /****************************************************************************
1604 ****************************************************************************/
1606 x86emuOp_push_byte_IMM(struct X86EMU
*emu
)
1610 imm
= (int8_t) fetch_byte_imm(emu
);
1611 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
1612 push_long(emu
, (int32_t) imm
);
1614 push_word(emu
, imm
);
1617 /****************************************************************************
1620 ****************************************************************************/
1621 /****************************************************************************
1624 ****************************************************************************/
1626 x86emuOp_ins_word(struct X86EMU
*emu
)
1628 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
1634 /****************************************************************************
1637 ****************************************************************************/
1639 x86emuOp_outs_word(struct X86EMU
*emu
)
1641 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
1647 /****************************************************************************
1650 ****************************************************************************/
1652 x86emuOp_jump_near_L(struct X86EMU
*emu
)
1656 sf
= ACCESS_FLAG(F_SF
) != 0;
1657 of
= ACCESS_FLAG(F_OF
) != 0;
1659 common_jmp_near(emu
, sf
!= of
);
1661 /****************************************************************************
1664 ****************************************************************************/
1666 x86emuOp_jump_near_NL(struct X86EMU
*emu
)
1670 sf
= ACCESS_FLAG(F_SF
) != 0;
1671 of
= ACCESS_FLAG(F_OF
) != 0;
1673 common_jmp_near(emu
, sf
== of
);
1675 /****************************************************************************
1678 ****************************************************************************/
1680 x86emuOp_jump_near_LE(struct X86EMU
*emu
)
1684 sf
= ACCESS_FLAG(F_SF
) != 0;
1685 of
= ACCESS_FLAG(F_OF
) != 0;
1687 common_jmp_near(emu
, sf
!= of
|| ACCESS_FLAG(F_ZF
));
1689 /****************************************************************************
1692 ****************************************************************************/
1694 x86emuOp_jump_near_NLE(struct X86EMU
*emu
)
1698 sf
= ACCESS_FLAG(F_SF
) != 0;
1699 of
= ACCESS_FLAG(F_OF
) != 0;
1701 common_jmp_near(emu
, sf
== of
&& !ACCESS_FLAG(F_ZF
));
1705 uint8_t(*const opc80_byte_operation
[]) (struct X86EMU
*, uint8_t d
, uint8_t s
) =
1716 /****************************************************************************
1719 ****************************************************************************/
1721 x86emuOp_opc80_byte_RM_IMM(struct X86EMU
*emu
)
1723 uint8_t imm
, destval
;
1726 * Weirdo special case instruction format. Part of the opcode
1727 * held below in "RH". Doubly nested case would result, except
1728 * that the decoded instruction
1730 fetch_decode_modrm(emu
);
1731 destval
= decode_and_fetch_byte(emu
);
1732 imm
= fetch_byte_imm(emu
);
1733 destval
= (*opc80_byte_operation
[emu
->cur_rh
]) (emu
, destval
, imm
);
1734 if (emu
->cur_rh
!= 7)
1735 write_back_byte(emu
, destval
);
1739 uint16_t(* const opc81_word_operation
[]) (struct X86EMU
*, uint16_t d
, uint16_t s
) =
1752 uint32_t(* const opc81_long_operation
[]) (struct X86EMU
*, uint32_t d
, uint32_t s
) =
1763 /****************************************************************************
1766 ****************************************************************************/
1768 x86emuOp32_opc81_word_RM_IMM(struct X86EMU
*emu
)
1770 uint32_t destval
, imm
;
1773 * Weirdo special case instruction format. Part of the opcode
1774 * held below in "RH". Doubly nested case would result, except
1775 * that the decoded instruction
1777 fetch_decode_modrm(emu
);
1778 destval
= decode_and_fetch_long(emu
);
1779 imm
= fetch_long_imm(emu
);
1780 destval
= (*opc81_long_operation
[emu
->cur_rh
]) (emu
, destval
, imm
);
1781 if (emu
->cur_rh
!= 7)
1782 write_back_long(emu
, destval
);
1786 x86emuOp16_opc81_word_RM_IMM(struct X86EMU
*emu
)
1788 uint16_t destval
, imm
;
1791 * Weirdo special case instruction format. Part of the opcode
1792 * held below in "RH". Doubly nested case would result, except
1793 * that the decoded instruction
1795 fetch_decode_modrm(emu
);
1796 destval
= decode_and_fetch_word(emu
);
1797 imm
= fetch_word_imm(emu
);
1798 destval
= (*opc81_word_operation
[emu
->cur_rh
]) (emu
, destval
, imm
);
1799 if (emu
->cur_rh
!= 7)
1800 write_back_word(emu
, destval
);
1804 x86emuOp_opc81_word_RM_IMM(struct X86EMU
*emu
)
1806 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
1807 x86emuOp32_opc81_word_RM_IMM(emu
);
1809 x86emuOp16_opc81_word_RM_IMM(emu
);
1813 uint8_t(* const opc82_byte_operation
[]) (struct X86EMU
*, uint8_t s
, uint8_t d
) =
1816 or_byte
, /* 01 *//* YYY UNUSED ???? */
1819 and_byte
, /* 04 *//* YYY UNUSED ???? */
1821 xor_byte
, /* 06 *//* YYY UNUSED ???? */
1824 /****************************************************************************
1827 ****************************************************************************/
1829 x86emuOp_opc82_byte_RM_IMM(struct X86EMU
*emu
)
1831 uint8_t imm
, destval
;
1834 * Weirdo special case instruction format. Part of the opcode
1835 * held below in "RH". Doubly nested case would result, except
1836 * that the decoded instruction Similar to opcode 81, except that
1837 * the immediate byte is sign extended to a word length.
1839 fetch_decode_modrm(emu
);
1840 destval
= decode_and_fetch_byte(emu
);
1841 imm
= fetch_byte_imm(emu
);
1842 destval
= (*opc82_byte_operation
[emu
->cur_rh
]) (emu
, destval
, imm
);
1843 if (emu
->cur_rh
!= 7)
1844 write_back_byte(emu
, destval
);
1848 uint16_t(* const opc83_word_operation
[]) (struct X86EMU
*, uint16_t s
, uint16_t d
) =
1851 or_word
, /* 01 *//* YYY UNUSED ???? */
1854 and_word
, /* 04 *//* YYY UNUSED ???? */
1856 xor_word
, /* 06 *//* YYY UNUSED ???? */
1861 uint32_t(* const opc83_long_operation
[]) (struct X86EMU
*, uint32_t s
, uint32_t d
) =
1864 or_long
, /* 01 *//* YYY UNUSED ???? */
1867 and_long
, /* 04 *//* YYY UNUSED ???? */
1869 xor_long
, /* 06 *//* YYY UNUSED ???? */
1872 /****************************************************************************
1875 ****************************************************************************/
1877 x86emuOp32_opc83_word_RM_IMM(struct X86EMU
*emu
)
1879 uint32_t destval
, imm
;
1881 fetch_decode_modrm(emu
);
1882 destval
= decode_and_fetch_long(emu
);
1883 imm
= (int8_t) fetch_byte_imm(emu
);
1884 destval
= (*opc83_long_operation
[emu
->cur_rh
]) (emu
, destval
, imm
);
1885 if (emu
->cur_rh
!= 7)
1886 write_back_long(emu
, destval
);
1890 x86emuOp16_opc83_word_RM_IMM(struct X86EMU
*emu
)
1892 uint16_t destval
, imm
;
1894 fetch_decode_modrm(emu
);
1895 destval
= decode_and_fetch_word(emu
);
1896 imm
= (int8_t) fetch_byte_imm(emu
);
1897 destval
= (*opc83_word_operation
[emu
->cur_rh
]) (emu
, destval
, imm
);
1898 if (emu
->cur_rh
!= 7)
1899 write_back_word(emu
, destval
);
1903 x86emuOp_opc83_word_RM_IMM(struct X86EMU
*emu
)
1905 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
1906 x86emuOp32_opc83_word_RM_IMM(emu
);
1908 x86emuOp16_opc83_word_RM_IMM(emu
);
1910 /****************************************************************************
1913 ****************************************************************************/
1915 x86emuOp_xchg_byte_RM_R(struct X86EMU
*emu
)
1917 uint8_t *srcreg
, destval
, tmp
;
1919 fetch_decode_modrm(emu
);
1920 destval
= decode_and_fetch_byte(emu
);
1921 srcreg
= decode_rh_byte_register(emu
);
1925 write_back_byte(emu
, destval
);
1927 /****************************************************************************
1930 ****************************************************************************/
1932 x86emuOp32_xchg_word_RM_R(struct X86EMU
*emu
)
1934 uint32_t *srcreg
, destval
, tmp
;
1936 fetch_decode_modrm(emu
);
1937 destval
= decode_and_fetch_long(emu
);
1938 srcreg
= decode_rh_long_register(emu
);
1942 write_back_long(emu
, destval
);
1946 x86emuOp16_xchg_word_RM_R(struct X86EMU
*emu
)
1948 uint16_t *srcreg
, destval
, tmp
;
1950 fetch_decode_modrm(emu
);
1951 destval
= decode_and_fetch_word(emu
);
1952 srcreg
= decode_rh_word_register(emu
);
1956 write_back_word(emu
, destval
);
1960 x86emuOp_xchg_word_RM_R(struct X86EMU
*emu
)
1962 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
1963 x86emuOp32_xchg_word_RM_R(emu
);
1965 x86emuOp16_xchg_word_RM_R(emu
);
1967 /****************************************************************************
1970 ****************************************************************************/
1972 x86emuOp_mov_byte_RM_R(struct X86EMU
*emu
)
1974 uint8_t *destreg
, *srcreg
;
1975 uint32_t destoffset
;
1977 fetch_decode_modrm(emu
);
1978 srcreg
= decode_rh_byte_register(emu
);
1979 if (emu
->cur_mod
!= 3) {
1980 destoffset
= decode_rl_address(emu
);
1981 store_data_byte(emu
, destoffset
, *srcreg
);
1983 destreg
= decode_rl_byte_register(emu
);
1987 /****************************************************************************
1990 ****************************************************************************/
1992 x86emuOp32_mov_word_RM_R(struct X86EMU
*emu
)
1994 uint32_t destoffset
;
1995 uint32_t *destreg
, srcval
;
1997 fetch_decode_modrm(emu
);
1998 srcval
= *decode_rh_long_register(emu
);
1999 if (emu
->cur_mod
!= 3) {
2000 destoffset
= decode_rl_address(emu
);
2001 store_data_long(emu
, destoffset
, srcval
);
2003 destreg
= decode_rl_long_register(emu
);
2009 x86emuOp16_mov_word_RM_R(struct X86EMU
*emu
)
2011 uint32_t destoffset
;
2012 uint16_t *destreg
, srcval
;
2014 fetch_decode_modrm(emu
);
2015 srcval
= *decode_rh_word_register(emu
);
2016 if (emu
->cur_mod
!= 3) {
2017 destoffset
= decode_rl_address(emu
);
2018 store_data_word(emu
, destoffset
, srcval
);
2020 destreg
= decode_rl_word_register(emu
);
2026 x86emuOp_mov_word_RM_R(struct X86EMU
*emu
)
2028 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
2029 x86emuOp32_mov_word_RM_R(emu
);
2031 x86emuOp16_mov_word_RM_R(emu
);
2033 /****************************************************************************
2036 ****************************************************************************/
2038 x86emuOp_mov_byte_R_RM(struct X86EMU
*emu
)
2042 fetch_decode_modrm(emu
);
2043 destreg
= decode_rh_byte_register(emu
);
2044 *destreg
= decode_and_fetch_byte(emu
);
2046 /****************************************************************************
2049 ****************************************************************************/
2051 x86emuOp_mov_word_R_RM(struct X86EMU
*emu
)
2053 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
2056 fetch_decode_modrm(emu
);
2057 destreg
= decode_rh_long_register(emu
);
2058 *destreg
= decode_and_fetch_long(emu
);
2062 fetch_decode_modrm(emu
);
2063 destreg
= decode_rh_word_register(emu
);
2064 *destreg
= decode_and_fetch_word(emu
);
2067 /****************************************************************************
2070 ****************************************************************************/
2072 x86emuOp_mov_word_RM_SR(struct X86EMU
*emu
)
2074 uint16_t *destreg
, srcval
;
2075 uint32_t destoffset
;
2077 fetch_decode_modrm(emu
);
2078 srcval
= *decode_rh_seg_register(emu
);
2079 if (emu
->cur_mod
!= 3) {
2080 destoffset
= decode_rl_address(emu
);
2081 store_data_word(emu
, destoffset
, srcval
);
2083 destreg
= decode_rl_word_register(emu
);
2087 /****************************************************************************
2090 ****************************************************************************/
2092 x86emuOp_lea_word_R_M(struct X86EMU
*emu
)
2095 uint32_t destoffset
;
2098 * TODO: Need to handle address size prefix!
2100 * lea eax,[eax+ebx*2] ??
2102 fetch_decode_modrm(emu
);
2103 if (emu
->cur_mod
== 3)
2104 X86EMU_halt_sys(emu
);
2106 srcreg
= decode_rh_word_register(emu
);
2107 destoffset
= decode_rl_address(emu
);
2108 *srcreg
= (uint16_t) destoffset
;
2110 /****************************************************************************
2113 ****************************************************************************/
2115 x86emuOp_mov_word_SR_RM(struct X86EMU
*emu
)
2119 fetch_decode_modrm(emu
);
2120 destreg
= decode_rh_seg_register(emu
);
2121 *destreg
= decode_and_fetch_word(emu
);
2123 * Clean up, and reset all the R_xSP pointers to the correct
2124 * locations. This is about 3x too much overhead (doing all the
2125 * segreg ptrs when only one is needed, but this instruction
2126 * *cannot* be that common, and this isn't too much work anyway.
2129 /****************************************************************************
2132 ****************************************************************************/
2134 x86emuOp32_pop_RM(struct X86EMU
*emu
)
2136 uint32_t destoffset
;
2137 uint32_t destval
, *destreg
;
2139 fetch_decode_modrm(emu
);
2140 if (emu
->cur_mod
!= 3) {
2141 destoffset
= decode_rl_address(emu
);
2142 destval
= pop_long(emu
);
2143 store_data_long(emu
, destoffset
, destval
);
2145 destreg
= decode_rl_long_register(emu
);
2146 *destreg
= pop_long(emu
);
2151 x86emuOp16_pop_RM(struct X86EMU
*emu
)
2153 uint32_t destoffset
;
2154 uint16_t destval
, *destreg
;
2156 fetch_decode_modrm(emu
);
2157 if (emu
->cur_mod
!= 3) {
2158 destoffset
= decode_rl_address(emu
);
2159 destval
= pop_word(emu
);
2160 store_data_word(emu
, destoffset
, destval
);
2162 destreg
= decode_rl_word_register(emu
);
2163 *destreg
= pop_word(emu
);
2168 x86emuOp_pop_RM(struct X86EMU
*emu
)
2170 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
2171 x86emuOp32_pop_RM(emu
);
2173 x86emuOp16_pop_RM(emu
);
2175 /****************************************************************************
2178 ****************************************************************************/
2180 x86emuOp_xchg_word_AX_CX(struct X86EMU
*emu
)
2184 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
2185 tmp
= emu
->x86
.R_EAX
;
2186 emu
->x86
.R_EAX
= emu
->x86
.R_ECX
;
2187 emu
->x86
.R_ECX
= tmp
;
2189 tmp
= emu
->x86
.R_AX
;
2190 emu
->x86
.R_AX
= emu
->x86
.R_CX
;
2191 emu
->x86
.R_CX
= (uint16_t) tmp
;
2194 /****************************************************************************
2197 ****************************************************************************/
2199 x86emuOp_xchg_word_AX_DX(struct X86EMU
*emu
)
2203 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
2204 tmp
= emu
->x86
.R_EAX
;
2205 emu
->x86
.R_EAX
= emu
->x86
.R_EDX
;
2206 emu
->x86
.R_EDX
= tmp
;
2208 tmp
= emu
->x86
.R_AX
;
2209 emu
->x86
.R_AX
= emu
->x86
.R_DX
;
2210 emu
->x86
.R_DX
= (uint16_t) tmp
;
2213 /****************************************************************************
2216 ****************************************************************************/
2218 x86emuOp_xchg_word_AX_BX(struct X86EMU
*emu
)
2222 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
2223 tmp
= emu
->x86
.R_EAX
;
2224 emu
->x86
.R_EAX
= emu
->x86
.R_EBX
;
2225 emu
->x86
.R_EBX
= tmp
;
2227 tmp
= emu
->x86
.R_AX
;
2228 emu
->x86
.R_AX
= emu
->x86
.R_BX
;
2229 emu
->x86
.R_BX
= (uint16_t) tmp
;
2232 /****************************************************************************
2235 ****************************************************************************/
2237 x86emuOp_xchg_word_AX_SP(struct X86EMU
*emu
)
2241 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
2242 tmp
= emu
->x86
.R_EAX
;
2243 emu
->x86
.R_EAX
= emu
->x86
.R_ESP
;
2244 emu
->x86
.R_ESP
= tmp
;
2246 tmp
= emu
->x86
.R_AX
;
2247 emu
->x86
.R_AX
= emu
->x86
.R_SP
;
2248 emu
->x86
.R_SP
= (uint16_t) tmp
;
2251 /****************************************************************************
2254 ****************************************************************************/
2256 x86emuOp_xchg_word_AX_BP(struct X86EMU
*emu
)
2260 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
2261 tmp
= emu
->x86
.R_EAX
;
2262 emu
->x86
.R_EAX
= emu
->x86
.R_EBP
;
2263 emu
->x86
.R_EBP
= tmp
;
2265 tmp
= emu
->x86
.R_AX
;
2266 emu
->x86
.R_AX
= emu
->x86
.R_BP
;
2267 emu
->x86
.R_BP
= (uint16_t) tmp
;
2270 /****************************************************************************
2273 ****************************************************************************/
2275 x86emuOp_xchg_word_AX_SI(struct X86EMU
*emu
)
2279 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
2280 tmp
= emu
->x86
.R_EAX
;
2281 emu
->x86
.R_EAX
= emu
->x86
.R_ESI
;
2282 emu
->x86
.R_ESI
= tmp
;
2284 tmp
= emu
->x86
.R_AX
;
2285 emu
->x86
.R_AX
= emu
->x86
.R_SI
;
2286 emu
->x86
.R_SI
= (uint16_t) tmp
;
2289 /****************************************************************************
2292 ****************************************************************************/
2294 x86emuOp_xchg_word_AX_DI(struct X86EMU
*emu
)
2298 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
2299 tmp
= emu
->x86
.R_EAX
;
2300 emu
->x86
.R_EAX
= emu
->x86
.R_EDI
;
2301 emu
->x86
.R_EDI
= tmp
;
2303 tmp
= emu
->x86
.R_AX
;
2304 emu
->x86
.R_AX
= emu
->x86
.R_DI
;
2305 emu
->x86
.R_DI
= (uint16_t) tmp
;
2308 /****************************************************************************
2311 ****************************************************************************/
2313 x86emuOp_cbw(struct X86EMU
*emu
)
2315 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
2316 if (emu
->x86
.R_AX
& 0x8000) {
2317 emu
->x86
.R_EAX
|= 0xffff0000;
2319 emu
->x86
.R_EAX
&= 0x0000ffff;
2322 if (emu
->x86
.R_AL
& 0x80) {
2323 emu
->x86
.R_AH
= 0xff;
2325 emu
->x86
.R_AH
= 0x0;
2329 /****************************************************************************
2332 ****************************************************************************/
2334 x86emuOp_cwd(struct X86EMU
*emu
)
2336 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
2337 if (emu
->x86
.R_EAX
& 0x80000000) {
2338 emu
->x86
.R_EDX
= 0xffffffff;
2340 emu
->x86
.R_EDX
= 0x0;
2343 if (emu
->x86
.R_AX
& 0x8000) {
2344 emu
->x86
.R_DX
= 0xffff;
2346 emu
->x86
.R_DX
= 0x0;
2350 /****************************************************************************
2353 ****************************************************************************/
2355 x86emuOp_call_far_IMM(struct X86EMU
*emu
)
2357 uint16_t farseg
, faroff
;
2359 faroff
= fetch_word_imm(emu
);
2360 farseg
= fetch_word_imm(emu
);
2363 * Hooked interrupt vectors calling into our "BIOS" will cause problems
2364 * unless all intersegment stuff is checked for BIOS access. Check
2365 * needed here. For moment, let it alone. */
2366 push_word(emu
, emu
->x86
.R_CS
);
2367 emu
->x86
.R_CS
= farseg
;
2368 push_word(emu
, emu
->x86
.R_IP
);
2369 emu
->x86
.R_IP
= faroff
;
2371 /****************************************************************************
2374 ****************************************************************************/
2376 x86emuOp_pushf_word(struct X86EMU
*emu
)
2380 /* clear out *all* bits not representing flags, and turn on real bits */
2381 flags
= (emu
->x86
.R_EFLG
& F_MSK
) | F_ALWAYS_ON
;
2382 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
2383 push_long(emu
, flags
);
2385 push_word(emu
, (uint16_t) flags
);
2388 /****************************************************************************
2391 ****************************************************************************/
2393 x86emuOp_popf_word(struct X86EMU
*emu
)
2395 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
2396 emu
->x86
.R_EFLG
= pop_long(emu
);
2398 emu
->x86
.R_FLG
= pop_word(emu
);
2401 /****************************************************************************
2404 ****************************************************************************/
2406 x86emuOp_sahf(struct X86EMU
*emu
)
2408 /* clear the lower bits of the flag register */
2409 emu
->x86
.R_FLG
&= 0xffffff00;
2410 /* or in the AH register into the flags register */
2411 emu
->x86
.R_FLG
|= emu
->x86
.R_AH
;
2413 /****************************************************************************
2416 ****************************************************************************/
2418 x86emuOp_lahf(struct X86EMU
*emu
)
2420 emu
->x86
.R_AH
= (uint8_t) (emu
->x86
.R_FLG
& 0xff);
2421 /* undocumented TC++ behavior??? Nope. It's documented, but you have
2422 * too look real hard to notice it. */
2423 emu
->x86
.R_AH
|= 0x2;
2425 /****************************************************************************
2428 ****************************************************************************/
2430 x86emuOp_mov_AL_M_IMM(struct X86EMU
*emu
)
2434 offset
= fetch_word_imm(emu
);
2435 emu
->x86
.R_AL
= fetch_data_byte(emu
, offset
);
2437 /****************************************************************************
2440 ****************************************************************************/
2442 x86emuOp_mov_AX_M_IMM(struct X86EMU
*emu
)
2446 offset
= fetch_word_imm(emu
);
2447 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
2448 emu
->x86
.R_EAX
= fetch_data_long(emu
, offset
);
2450 emu
->x86
.R_AX
= fetch_data_word(emu
, offset
);
2453 /****************************************************************************
2456 ****************************************************************************/
2458 x86emuOp_mov_M_AL_IMM(struct X86EMU
*emu
)
2462 offset
= fetch_word_imm(emu
);
2463 store_data_byte(emu
, offset
, emu
->x86
.R_AL
);
2465 /****************************************************************************
2468 ****************************************************************************/
2470 x86emuOp_mov_M_AX_IMM(struct X86EMU
*emu
)
2474 offset
= fetch_word_imm(emu
);
2475 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
2476 store_data_long(emu
, offset
, emu
->x86
.R_EAX
);
2478 store_data_word(emu
, offset
, emu
->x86
.R_AX
);
2481 /****************************************************************************
2484 ****************************************************************************/
2486 x86emuOp_movs_byte(struct X86EMU
*emu
)
2492 if (ACCESS_FLAG(F_DF
)) /* down */
2497 if (emu
->x86
.mode
& (SYSMODE_PREFIX_REPE
| SYSMODE_PREFIX_REPNE
)) {
2498 /* dont care whether REPE or REPNE */
2499 /* move them until CX is ZERO. */
2500 count
= emu
->x86
.R_CX
;
2502 emu
->x86
.mode
&= ~(SYSMODE_PREFIX_REPE
| SYSMODE_PREFIX_REPNE
);
2505 val
= fetch_data_byte(emu
, emu
->x86
.R_SI
);
2506 store_byte(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
, val
);
2507 emu
->x86
.R_SI
+= inc
;
2508 emu
->x86
.R_DI
+= inc
;
2511 /****************************************************************************
2514 ****************************************************************************/
2516 x86emuOp_movs_word(struct X86EMU
*emu
)
2522 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
2527 if (ACCESS_FLAG(F_DF
)) /* down */
2531 if (emu
->x86
.mode
& (SYSMODE_PREFIX_REPE
| SYSMODE_PREFIX_REPNE
)) {
2532 /* dont care whether REPE or REPNE */
2533 /* move them until CX is ZERO. */
2534 count
= emu
->x86
.R_CX
;
2536 emu
->x86
.mode
&= ~(SYSMODE_PREFIX_REPE
| SYSMODE_PREFIX_REPNE
);
2539 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
2540 val
= fetch_data_long(emu
, emu
->x86
.R_SI
);
2541 store_long(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
, val
);
2543 val
= fetch_data_word(emu
, emu
->x86
.R_SI
);
2544 store_word(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
, (uint16_t) val
);
2546 emu
->x86
.R_SI
+= inc
;
2547 emu
->x86
.R_DI
+= inc
;
2550 /****************************************************************************
2553 ****************************************************************************/
2555 x86emuOp_cmps_byte(struct X86EMU
*emu
)
2560 if (ACCESS_FLAG(F_DF
)) /* down */
2565 if (emu
->x86
.mode
& SYSMODE_PREFIX_REPE
) {
2567 /* move them until CX is ZERO. */
2568 while (emu
->x86
.R_CX
!= 0) {
2569 val1
= fetch_data_byte(emu
, emu
->x86
.R_SI
);
2570 val2
= fetch_byte(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
);
2571 cmp_byte(emu
, val1
, val2
);
2573 emu
->x86
.R_SI
+= inc
;
2574 emu
->x86
.R_DI
+= inc
;
2575 if (ACCESS_FLAG(F_ZF
) == 0)
2578 emu
->x86
.mode
&= ~SYSMODE_PREFIX_REPE
;
2579 } else if (emu
->x86
.mode
& SYSMODE_PREFIX_REPNE
) {
2581 /* move them until CX is ZERO. */
2582 while (emu
->x86
.R_CX
!= 0) {
2583 val1
= fetch_data_byte(emu
, emu
->x86
.R_SI
);
2584 val2
= fetch_byte(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
);
2585 cmp_byte(emu
, val1
, val2
);
2587 emu
->x86
.R_SI
+= inc
;
2588 emu
->x86
.R_DI
+= inc
;
2589 if (ACCESS_FLAG(F_ZF
))
2590 break; /* zero flag set means equal */
2592 emu
->x86
.mode
&= ~SYSMODE_PREFIX_REPNE
;
2594 val1
= fetch_data_byte(emu
, emu
->x86
.R_SI
);
2595 val2
= fetch_byte(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
);
2596 cmp_byte(emu
, val1
, val2
);
2597 emu
->x86
.R_SI
+= inc
;
2598 emu
->x86
.R_DI
+= inc
;
2601 /****************************************************************************
2604 ****************************************************************************/
2606 x86emuOp_cmps_word(struct X86EMU
*emu
)
2608 uint32_t val1
, val2
;
2611 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
2612 if (ACCESS_FLAG(F_DF
)) /* down */
2617 if (ACCESS_FLAG(F_DF
)) /* down */
2622 if (emu
->x86
.mode
& SYSMODE_PREFIX_REPE
) {
2624 /* move them until CX is ZERO. */
2625 while (emu
->x86
.R_CX
!= 0) {
2626 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
2627 val1
= fetch_data_long(emu
, emu
->x86
.R_SI
);
2628 val2
= fetch_long(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
);
2629 cmp_long(emu
, val1
, val2
);
2631 val1
= fetch_data_word(emu
, emu
->x86
.R_SI
);
2632 val2
= fetch_word(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
);
2633 cmp_word(emu
, (uint16_t) val1
, (uint16_t) val2
);
2636 emu
->x86
.R_SI
+= inc
;
2637 emu
->x86
.R_DI
+= inc
;
2638 if (ACCESS_FLAG(F_ZF
) == 0)
2641 emu
->x86
.mode
&= ~SYSMODE_PREFIX_REPE
;
2642 } else if (emu
->x86
.mode
& SYSMODE_PREFIX_REPNE
) {
2644 /* move them until CX is ZERO. */
2645 while (emu
->x86
.R_CX
!= 0) {
2646 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
2647 val1
= fetch_data_long(emu
, emu
->x86
.R_SI
);
2648 val2
= fetch_long(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
);
2649 cmp_long(emu
, val1
, val2
);
2651 val1
= fetch_data_word(emu
, emu
->x86
.R_SI
);
2652 val2
= fetch_word(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
);
2653 cmp_word(emu
, (uint16_t) val1
, (uint16_t) val2
);
2656 emu
->x86
.R_SI
+= inc
;
2657 emu
->x86
.R_DI
+= inc
;
2658 if (ACCESS_FLAG(F_ZF
))
2659 break; /* zero flag set means equal */
2661 emu
->x86
.mode
&= ~SYSMODE_PREFIX_REPNE
;
2663 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
2664 val1
= fetch_data_long(emu
, emu
->x86
.R_SI
);
2665 val2
= fetch_long(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
);
2666 cmp_long(emu
, val1
, val2
);
2668 val1
= fetch_data_word(emu
, emu
->x86
.R_SI
);
2669 val2
= fetch_word(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
);
2670 cmp_word(emu
, (uint16_t) val1
, (uint16_t) val2
);
2672 emu
->x86
.R_SI
+= inc
;
2673 emu
->x86
.R_DI
+= inc
;
2676 /****************************************************************************
2679 ****************************************************************************/
2681 x86emuOp_test_AX_IMM(struct X86EMU
*emu
)
2683 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
2684 test_long(emu
, emu
->x86
.R_EAX
, fetch_long_imm(emu
));
2686 test_word(emu
, emu
->x86
.R_AX
, fetch_word_imm(emu
));
2689 /****************************************************************************
2692 ****************************************************************************/
2694 x86emuOp_stos_byte(struct X86EMU
*emu
)
2698 if (ACCESS_FLAG(F_DF
)) /* down */
2702 if (emu
->x86
.mode
& (SYSMODE_PREFIX_REPE
| SYSMODE_PREFIX_REPNE
)) {
2703 /* dont care whether REPE or REPNE */
2704 /* move them until CX is ZERO. */
2705 while (emu
->x86
.R_CX
!= 0) {
2706 store_byte(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
, emu
->x86
.R_AL
);
2708 emu
->x86
.R_DI
+= inc
;
2710 emu
->x86
.mode
&= ~(SYSMODE_PREFIX_REPE
| SYSMODE_PREFIX_REPNE
);
2712 store_byte(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
, emu
->x86
.R_AL
);
2713 emu
->x86
.R_DI
+= inc
;
2716 /****************************************************************************
2719 ****************************************************************************/
2721 x86emuOp_stos_word(struct X86EMU
*emu
)
2726 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
2731 if (ACCESS_FLAG(F_DF
)) /* down */
2735 if (emu
->x86
.mode
& (SYSMODE_PREFIX_REPE
| SYSMODE_PREFIX_REPNE
)) {
2736 /* dont care whether REPE or REPNE */
2737 /* move them until CX is ZERO. */
2738 count
= emu
->x86
.R_CX
;
2740 emu
->x86
.mode
&= ~(SYSMODE_PREFIX_REPE
| SYSMODE_PREFIX_REPNE
);
2743 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
2744 store_long(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
, emu
->x86
.R_EAX
);
2746 store_word(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
, emu
->x86
.R_AX
);
2748 emu
->x86
.R_DI
+= inc
;
2751 /****************************************************************************
2754 ****************************************************************************/
2756 x86emuOp_lods_byte(struct X86EMU
*emu
)
2760 if (ACCESS_FLAG(F_DF
)) /* down */
2764 if (emu
->x86
.mode
& (SYSMODE_PREFIX_REPE
| SYSMODE_PREFIX_REPNE
)) {
2765 /* dont care whether REPE or REPNE */
2766 /* move them until CX is ZERO. */
2767 while (emu
->x86
.R_CX
!= 0) {
2768 emu
->x86
.R_AL
= fetch_data_byte(emu
, emu
->x86
.R_SI
);
2770 emu
->x86
.R_SI
+= inc
;
2772 emu
->x86
.mode
&= ~(SYSMODE_PREFIX_REPE
| SYSMODE_PREFIX_REPNE
);
2774 emu
->x86
.R_AL
= fetch_data_byte(emu
, emu
->x86
.R_SI
);
2775 emu
->x86
.R_SI
+= inc
;
2778 /****************************************************************************
2781 ****************************************************************************/
2783 x86emuOp_lods_word(struct X86EMU
*emu
)
2788 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
2793 if (ACCESS_FLAG(F_DF
)) /* down */
2797 if (emu
->x86
.mode
& (SYSMODE_PREFIX_REPE
| SYSMODE_PREFIX_REPNE
)) {
2798 /* dont care whether REPE or REPNE */
2799 /* move them until CX is ZERO. */
2800 count
= emu
->x86
.R_CX
;
2802 emu
->x86
.mode
&= ~(SYSMODE_PREFIX_REPE
| SYSMODE_PREFIX_REPNE
);
2805 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
2806 emu
->x86
.R_EAX
= fetch_data_long(emu
, emu
->x86
.R_SI
);
2808 emu
->x86
.R_AX
= fetch_data_word(emu
, emu
->x86
.R_SI
);
2810 emu
->x86
.R_SI
+= inc
;
2813 /****************************************************************************
2816 ****************************************************************************/
2818 x86emuOp_scas_byte(struct X86EMU
*emu
)
2823 if (ACCESS_FLAG(F_DF
)) /* down */
2827 if (emu
->x86
.mode
& SYSMODE_PREFIX_REPE
) {
2829 /* move them until CX is ZERO. */
2830 while (emu
->x86
.R_CX
!= 0) {
2831 val2
= fetch_byte(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
);
2832 cmp_byte(emu
, emu
->x86
.R_AL
, val2
);
2834 emu
->x86
.R_DI
+= inc
;
2835 if (ACCESS_FLAG(F_ZF
) == 0)
2838 emu
->x86
.mode
&= ~SYSMODE_PREFIX_REPE
;
2839 } else if (emu
->x86
.mode
& SYSMODE_PREFIX_REPNE
) {
2841 /* move them until CX is ZERO. */
2842 while (emu
->x86
.R_CX
!= 0) {
2843 val2
= fetch_byte(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
);
2844 cmp_byte(emu
, emu
->x86
.R_AL
, val2
);
2846 emu
->x86
.R_DI
+= inc
;
2847 if (ACCESS_FLAG(F_ZF
))
2848 break; /* zero flag set means equal */
2850 emu
->x86
.mode
&= ~SYSMODE_PREFIX_REPNE
;
2852 val2
= fetch_byte(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
);
2853 cmp_byte(emu
, emu
->x86
.R_AL
, val2
);
2854 emu
->x86
.R_DI
+= inc
;
2857 /****************************************************************************
2860 ****************************************************************************/
2862 x86emuOp_scas_word(struct X86EMU
*emu
)
2867 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
2872 if (ACCESS_FLAG(F_DF
)) /* down */
2875 if (emu
->x86
.mode
& SYSMODE_PREFIX_REPE
) {
2877 /* move them until CX is ZERO. */
2878 while (emu
->x86
.R_CX
!= 0) {
2879 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
2880 val
= fetch_long(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
);
2881 cmp_long(emu
, emu
->x86
.R_EAX
, val
);
2883 val
= fetch_word(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
);
2884 cmp_word(emu
, emu
->x86
.R_AX
, (uint16_t) val
);
2887 emu
->x86
.R_DI
+= inc
;
2888 if (ACCESS_FLAG(F_ZF
) == 0)
2891 emu
->x86
.mode
&= ~SYSMODE_PREFIX_REPE
;
2892 } else if (emu
->x86
.mode
& SYSMODE_PREFIX_REPNE
) {
2894 /* move them until CX is ZERO. */
2895 while (emu
->x86
.R_CX
!= 0) {
2896 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
2897 val
= fetch_long(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
);
2898 cmp_long(emu
, emu
->x86
.R_EAX
, val
);
2900 val
= fetch_word(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
);
2901 cmp_word(emu
, emu
->x86
.R_AX
, (uint16_t) val
);
2904 emu
->x86
.R_DI
+= inc
;
2905 if (ACCESS_FLAG(F_ZF
))
2906 break; /* zero flag set means equal */
2908 emu
->x86
.mode
&= ~SYSMODE_PREFIX_REPNE
;
2910 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
2911 val
= fetch_long(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
);
2912 cmp_long(emu
, emu
->x86
.R_EAX
, val
);
2914 val
= fetch_word(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
);
2915 cmp_word(emu
, emu
->x86
.R_AX
, (uint16_t) val
);
2917 emu
->x86
.R_DI
+= inc
;
2920 /****************************************************************************
2923 ****************************************************************************/
2925 x86emuOp_mov_word_AX_IMM(struct X86EMU
*emu
)
2927 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
2928 emu
->x86
.R_EAX
= fetch_long_imm(emu
);
2930 emu
->x86
.R_AX
= fetch_word_imm(emu
);
2932 /****************************************************************************
2935 ****************************************************************************/
2937 x86emuOp_mov_word_CX_IMM(struct X86EMU
*emu
)
2939 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
2940 emu
->x86
.R_ECX
= fetch_long_imm(emu
);
2942 emu
->x86
.R_CX
= fetch_word_imm(emu
);
2944 /****************************************************************************
2947 ****************************************************************************/
2949 x86emuOp_mov_word_DX_IMM(struct X86EMU
*emu
)
2951 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
2952 emu
->x86
.R_EDX
= fetch_long_imm(emu
);
2954 emu
->x86
.R_DX
= fetch_word_imm(emu
);
2956 /****************************************************************************
2959 ****************************************************************************/
2961 x86emuOp_mov_word_BX_IMM(struct X86EMU
*emu
)
2963 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
2964 emu
->x86
.R_EBX
= fetch_long_imm(emu
);
2966 emu
->x86
.R_BX
= fetch_word_imm(emu
);
2968 /****************************************************************************
2971 ****************************************************************************/
2973 x86emuOp_mov_word_SP_IMM(struct X86EMU
*emu
)
2975 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
2976 emu
->x86
.R_ESP
= fetch_long_imm(emu
);
2978 emu
->x86
.R_SP
= fetch_word_imm(emu
);
2980 /****************************************************************************
2983 ****************************************************************************/
2985 x86emuOp_mov_word_BP_IMM(struct X86EMU
*emu
)
2987 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
2988 emu
->x86
.R_EBP
= fetch_long_imm(emu
);
2990 emu
->x86
.R_BP
= fetch_word_imm(emu
);
2992 /****************************************************************************
2995 ****************************************************************************/
2997 x86emuOp_mov_word_SI_IMM(struct X86EMU
*emu
)
2999 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
3000 emu
->x86
.R_ESI
= fetch_long_imm(emu
);
3002 emu
->x86
.R_SI
= fetch_word_imm(emu
);
3004 /****************************************************************************
3007 ****************************************************************************/
3009 x86emuOp_mov_word_DI_IMM(struct X86EMU
*emu
)
3011 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
3012 emu
->x86
.R_EDI
= fetch_long_imm(emu
);
3014 emu
->x86
.R_DI
= fetch_word_imm(emu
);
3016 /* used by opcodes c0, d0, and d2. */
3018 uint8_t(* const opcD0_byte_operation
[]) (struct X86EMU
*, uint8_t d
, uint8_t s
) =
3026 shl_byte
, /* sal_byte === shl_byte by definition */
3029 /****************************************************************************
3032 ****************************************************************************/
3034 x86emuOp_opcC0_byte_RM_MEM(struct X86EMU
*emu
)
3036 uint8_t destval
, amt
;
3039 * Yet another weirdo special case instruction format. Part of
3040 * the opcode held below in "RH". Doubly nested case would
3041 * result, except that the decoded instruction
3043 fetch_decode_modrm(emu
);
3044 /* know operation, decode the mod byte to find the addressing mode. */
3045 destval
= decode_and_fetch_byte_imm8(emu
, &amt
);
3046 destval
= (*opcD0_byte_operation
[emu
->cur_rh
]) (emu
, destval
, amt
);
3047 write_back_byte(emu
, destval
);
3049 /* used by opcodes c1, d1, and d3. */
3051 uint16_t(* const opcD1_word_operation
[]) (struct X86EMU
*, uint16_t s
, uint8_t d
) =
3059 shl_word
, /* sal_byte === shl_byte by definition */
3062 /* used by opcodes c1, d1, and d3. */
3064 uint32_t(* const opcD1_long_operation
[]) (struct X86EMU
*, uint32_t s
, uint8_t d
) =
3072 shl_long
, /* sal_byte === shl_byte by definition */
3075 /****************************************************************************
3078 ****************************************************************************/
3080 x86emuOp_opcC1_word_RM_MEM(struct X86EMU
*emu
)
3085 * Yet another weirdo special case instruction format. Part of
3086 * the opcode held below in "RH". Doubly nested case would
3087 * result, except that the decoded instruction
3089 fetch_decode_modrm(emu
);
3090 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
3093 destval
= decode_and_fetch_long_imm8(emu
, &amt
);
3094 destval
= (*opcD1_long_operation
[emu
->cur_rh
]) (emu
, destval
, amt
);
3095 write_back_long(emu
, destval
);
3099 destval
= decode_and_fetch_word_imm8(emu
, &amt
);
3100 destval
= (*opcD1_word_operation
[emu
->cur_rh
]) (emu
, destval
, amt
);
3101 write_back_word(emu
, destval
);
3104 /****************************************************************************
3107 ****************************************************************************/
3109 x86emuOp_ret_near_IMM(struct X86EMU
*emu
)
3113 imm
= fetch_word_imm(emu
);
3114 emu
->x86
.R_IP
= pop_word(emu
);
3115 emu
->x86
.R_SP
+= imm
;
3117 /****************************************************************************
3120 ****************************************************************************/
3122 x86emuOp_mov_byte_RM_IMM(struct X86EMU
*emu
)
3125 uint32_t destoffset
;
3128 fetch_decode_modrm(emu
);
3129 if (emu
->cur_rh
!= 0)
3130 X86EMU_halt_sys(emu
);
3131 if (emu
->cur_mod
!= 3) {
3132 destoffset
= decode_rl_address(emu
);
3133 imm
= fetch_byte_imm(emu
);
3134 store_data_byte(emu
, destoffset
, imm
);
3136 destreg
= decode_rl_byte_register(emu
);
3137 imm
= fetch_byte_imm(emu
);
3141 /****************************************************************************
3144 ****************************************************************************/
3146 x86emuOp32_mov_word_RM_IMM(struct X86EMU
*emu
)
3148 uint32_t destoffset
;
3149 uint32_t imm
, *destreg
;
3151 fetch_decode_modrm(emu
);
3152 if (emu
->cur_rh
!= 0)
3153 X86EMU_halt_sys(emu
);
3155 if (emu
->cur_mod
!= 3) {
3156 destoffset
= decode_rl_address(emu
);
3157 imm
= fetch_long_imm(emu
);
3158 store_data_long(emu
, destoffset
, imm
);
3160 destreg
= decode_rl_long_register(emu
);
3161 imm
= fetch_long_imm(emu
);
3167 x86emuOp16_mov_word_RM_IMM(struct X86EMU
*emu
)
3169 uint32_t destoffset
;
3170 uint16_t imm
, *destreg
;
3172 fetch_decode_modrm(emu
);
3173 if (emu
->cur_rh
!= 0)
3174 X86EMU_halt_sys(emu
);
3176 if (emu
->cur_mod
!= 3) {
3177 destoffset
= decode_rl_address(emu
);
3178 imm
= fetch_word_imm(emu
);
3179 store_data_word(emu
, destoffset
, imm
);
3181 destreg
= decode_rl_word_register(emu
);
3182 imm
= fetch_word_imm(emu
);
3188 x86emuOp_mov_word_RM_IMM(struct X86EMU
*emu
)
3190 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
3191 x86emuOp32_mov_word_RM_IMM(emu
);
3193 x86emuOp16_mov_word_RM_IMM(emu
);
3195 /****************************************************************************
3198 ****************************************************************************/
3200 x86emuOp_enter(struct X86EMU
*emu
)
3202 uint16_t local
, frame_pointer
;
3206 local
= fetch_word_imm(emu
);
3207 nesting
= fetch_byte_imm(emu
);
3208 push_word(emu
, emu
->x86
.R_BP
);
3209 frame_pointer
= emu
->x86
.R_SP
;
3211 for (i
= 1; i
< nesting
; i
++) {
3213 push_word(emu
, fetch_word(emu
, emu
->x86
.R_SS
, emu
->x86
.R_BP
));
3215 push_word(emu
, frame_pointer
);
3217 emu
->x86
.R_BP
= frame_pointer
;
3218 emu
->x86
.R_SP
= (uint16_t) (emu
->x86
.R_SP
- local
);
3220 /****************************************************************************
3223 ****************************************************************************/
3225 x86emuOp_leave(struct X86EMU
*emu
)
3227 emu
->x86
.R_SP
= emu
->x86
.R_BP
;
3228 emu
->x86
.R_BP
= pop_word(emu
);
3230 /****************************************************************************
3233 ****************************************************************************/
3235 x86emuOp_ret_far_IMM(struct X86EMU
*emu
)
3239 imm
= fetch_word_imm(emu
);
3240 emu
->x86
.R_IP
= pop_word(emu
);
3241 emu
->x86
.R_CS
= pop_word(emu
);
3242 emu
->x86
.R_SP
+= imm
;
3244 /****************************************************************************
3247 ****************************************************************************/
3249 x86emuOp_ret_far(struct X86EMU
*emu
)
3251 emu
->x86
.R_IP
= pop_word(emu
);
3252 emu
->x86
.R_CS
= pop_word(emu
);
3254 /****************************************************************************
3257 ****************************************************************************/
3259 x86emuOp_int3(struct X86EMU
*emu
)
3261 x86emu_intr_dispatch(emu
, 3);
3263 /****************************************************************************
3266 ****************************************************************************/
3268 x86emuOp_int_IMM(struct X86EMU
*emu
)
3272 intnum
= fetch_byte_imm(emu
);
3273 x86emu_intr_dispatch(emu
, intnum
);
3275 /****************************************************************************
3278 ****************************************************************************/
3280 x86emuOp_into(struct X86EMU
*emu
)
3282 if (ACCESS_FLAG(F_OF
))
3283 x86emu_intr_dispatch(emu
, 4);
3285 /****************************************************************************
3288 ****************************************************************************/
3290 x86emuOp_iret(struct X86EMU
*emu
)
3292 emu
->x86
.R_IP
= pop_word(emu
);
3293 emu
->x86
.R_CS
= pop_word(emu
);
3294 emu
->x86
.R_FLG
= pop_word(emu
);
3296 /****************************************************************************
3299 ****************************************************************************/
3301 x86emuOp_opcD0_byte_RM_1(struct X86EMU
*emu
)
3305 fetch_decode_modrm(emu
);
3306 destval
= decode_and_fetch_byte(emu
);
3307 destval
= (*opcD0_byte_operation
[emu
->cur_rh
]) (emu
, destval
, 1);
3308 write_back_byte(emu
, destval
);
3310 /****************************************************************************
3313 ****************************************************************************/
3315 x86emuOp_opcD1_word_RM_1(struct X86EMU
*emu
)
3317 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
3320 fetch_decode_modrm(emu
);
3321 destval
= decode_and_fetch_long(emu
);
3322 destval
= (*opcD1_long_operation
[emu
->cur_rh
]) (emu
, destval
, 1);
3323 write_back_long(emu
, destval
);
3327 fetch_decode_modrm(emu
);
3328 destval
= decode_and_fetch_word(emu
);
3329 destval
= (*opcD1_word_operation
[emu
->cur_rh
]) (emu
, destval
, 1);
3330 write_back_word(emu
, destval
);
3333 /****************************************************************************
3336 ****************************************************************************/
3338 x86emuOp_opcD2_byte_RM_CL(struct X86EMU
*emu
)
3342 fetch_decode_modrm(emu
);
3343 destval
= decode_and_fetch_byte(emu
);
3344 destval
= (*opcD0_byte_operation
[emu
->cur_rh
]) (emu
, destval
, emu
->x86
.R_CL
);
3345 write_back_byte(emu
, destval
);
3347 /****************************************************************************
3350 ****************************************************************************/
3352 x86emuOp_opcD3_word_RM_CL(struct X86EMU
*emu
)
3354 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
3357 fetch_decode_modrm(emu
);
3358 destval
= decode_and_fetch_long(emu
);
3359 destval
= (*opcD1_long_operation
[emu
->cur_rh
]) (emu
, destval
, emu
->x86
.R_CL
);
3360 write_back_long(emu
, destval
);
3364 fetch_decode_modrm(emu
);
3365 destval
= decode_and_fetch_word(emu
);
3366 destval
= (*opcD1_word_operation
[emu
->cur_rh
]) (emu
, destval
, emu
->x86
.R_CL
);
3367 write_back_word(emu
, destval
);
3370 /****************************************************************************
3373 ****************************************************************************/
3375 x86emuOp_aam(struct X86EMU
*emu
)
3379 a
= fetch_byte_imm(emu
); /* this is a stupid encoding. */
3381 /* fix: add base decoding aam_word(uint8_t val, int base a) */
3382 X86EMU_halt_sys(emu
);
3384 /* note the type change here --- returning AL and AH in AX. */
3385 emu
->x86
.R_AX
= aam_word(emu
, emu
->x86
.R_AL
);
3387 /****************************************************************************
3390 ****************************************************************************/
3392 x86emuOp_aad(struct X86EMU
*emu
)
3396 a
= fetch_byte_imm(emu
);
3398 /* fix: add base decoding aad_word(uint16_t val, int base a) */
3399 X86EMU_halt_sys(emu
);
3401 emu
->x86
.R_AX
= aad_word(emu
, emu
->x86
.R_AX
);
3403 /* opcode 0xd6 ILLEGAL OPCODE */
3405 /****************************************************************************
3408 ****************************************************************************/
3410 x86emuOp_xlat(struct X86EMU
*emu
)
3414 addr
= (uint16_t) (emu
->x86
.R_BX
+ (uint8_t) emu
->x86
.R_AL
);
3415 emu
->x86
.R_AL
= fetch_data_byte(emu
, addr
);
3420 x86emuOp_esc_coprocess_d8(struct X86EMU
*emu
)
3425 x86emuOp_esc_coprocess_d9(struct X86EMU
*emu
)
3427 fetch_decode_modrm(emu
);
3428 if (emu
->cur_mod
!= 3)
3429 decode_rl_address(emu
);
3433 x86emuOp_esc_coprocess_da(struct X86EMU
*emu
)
3435 fetch_decode_modrm(emu
);
3436 if (emu
->cur_mod
!= 3)
3437 decode_rl_address(emu
);
3441 x86emuOp_esc_coprocess_db(struct X86EMU
*emu
)
3443 fetch_decode_modrm(emu
);
3444 if (emu
->cur_mod
!= 3)
3445 decode_rl_address(emu
);
3449 x86emuOp_esc_coprocess_dc(struct X86EMU
*emu
)
3451 fetch_decode_modrm(emu
);
3452 if (emu
->cur_mod
!= 3)
3453 decode_rl_address(emu
);
3457 x86emuOp_esc_coprocess_dd(struct X86EMU
*emu
)
3459 fetch_decode_modrm(emu
);
3460 if (emu
->cur_mod
!= 3)
3461 decode_rl_address(emu
);
3465 x86emuOp_esc_coprocess_de(struct X86EMU
*emu
)
3467 fetch_decode_modrm(emu
);
3468 if (emu
->cur_mod
!= 3)
3469 decode_rl_address(emu
);
3473 x86emuOp_esc_coprocess_df(struct X86EMU
*emu
)
3475 fetch_decode_modrm(emu
);
3476 if (emu
->cur_mod
!= 3)
3477 decode_rl_address(emu
);
3480 /****************************************************************************
3483 ****************************************************************************/
3485 x86emuOp_loopne(struct X86EMU
*emu
)
3489 ip
= (int8_t) fetch_byte_imm(emu
);
3490 ip
+= (int16_t) emu
->x86
.R_IP
;
3492 if (emu
->x86
.R_CX
!= 0 && !ACCESS_FLAG(F_ZF
)) /* CX != 0 and !ZF */
3495 /****************************************************************************
3498 ****************************************************************************/
3500 x86emuOp_loope(struct X86EMU
*emu
)
3504 ip
= (int8_t) fetch_byte_imm(emu
);
3505 ip
+= (int16_t) emu
->x86
.R_IP
;
3507 if (emu
->x86
.R_CX
!= 0 && ACCESS_FLAG(F_ZF
)) /* CX != 0 and ZF */
3510 /****************************************************************************
3513 ****************************************************************************/
3515 x86emuOp_loop(struct X86EMU
*emu
)
3519 ip
= (int8_t) fetch_byte_imm(emu
);
3520 ip
+= (int16_t) emu
->x86
.R_IP
;
3522 if (emu
->x86
.R_CX
!= 0)
3525 /****************************************************************************
3528 ****************************************************************************/
3530 x86emuOp_jcxz(struct X86EMU
*emu
)
3535 /* jump to byte offset if overflow flag is set */
3536 offset
= (int8_t) fetch_byte_imm(emu
);
3537 target
= (uint16_t) (emu
->x86
.R_IP
+ offset
);
3538 if (emu
->x86
.R_CX
== 0)
3539 emu
->x86
.R_IP
= target
;
3541 /****************************************************************************
3544 ****************************************************************************/
3546 x86emuOp_in_byte_AL_IMM(struct X86EMU
*emu
)
3550 port
= (uint8_t) fetch_byte_imm(emu
);
3551 emu
->x86
.R_AL
= (*emu
->emu_inb
) (emu
, port
);
3553 /****************************************************************************
3556 ****************************************************************************/
3558 x86emuOp_in_word_AX_IMM(struct X86EMU
*emu
)
3562 port
= (uint8_t) fetch_byte_imm(emu
);
3563 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
3564 emu
->x86
.R_EAX
= (*emu
->emu_inl
) (emu
, port
);
3566 emu
->x86
.R_AX
= (*emu
->emu_inw
) (emu
, port
);
3569 /****************************************************************************
3572 ****************************************************************************/
3574 x86emuOp_out_byte_IMM_AL(struct X86EMU
*emu
)
3578 port
= (uint8_t) fetch_byte_imm(emu
);
3579 (*emu
->emu_outb
) (emu
, port
, emu
->x86
.R_AL
);
3581 /****************************************************************************
3584 ****************************************************************************/
3586 x86emuOp_out_word_IMM_AX(struct X86EMU
*emu
)
3590 port
= (uint8_t) fetch_byte_imm(emu
);
3591 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
3592 (*emu
->emu_outl
) (emu
, port
, emu
->x86
.R_EAX
);
3594 (*emu
->emu_outw
) (emu
, port
, emu
->x86
.R_AX
);
3597 /****************************************************************************
3600 ****************************************************************************/
3602 x86emuOp_call_near_IMM(struct X86EMU
*emu
)
3606 ip
= (int16_t) fetch_word_imm(emu
);
3607 ip
+= (int16_t) emu
->x86
.R_IP
; /* CHECK SIGN */
3608 push_word(emu
, emu
->x86
.R_IP
);
3611 /****************************************************************************
3614 ****************************************************************************/
3616 x86emuOp_jump_near_IMM(struct X86EMU
*emu
)
3620 ip
= (int16_t) fetch_word_imm(emu
);
3621 ip
+= (int16_t) emu
->x86
.R_IP
;
3622 emu
->x86
.R_IP
= (uint16_t) ip
;
3624 /****************************************************************************
3627 ****************************************************************************/
3629 x86emuOp_jump_far_IMM(struct X86EMU
*emu
)
3633 ip
= fetch_word_imm(emu
);
3634 cs
= fetch_word_imm(emu
);
3638 /****************************************************************************
3641 ****************************************************************************/
3643 x86emuOp_jump_byte_IMM(struct X86EMU
*emu
)
3648 offset
= (int8_t) fetch_byte_imm(emu
);
3649 target
= (uint16_t) (emu
->x86
.R_IP
+ offset
);
3650 emu
->x86
.R_IP
= target
;
3652 /****************************************************************************
3655 ****************************************************************************/
3657 x86emuOp_in_byte_AL_DX(struct X86EMU
*emu
)
3659 emu
->x86
.R_AL
= (*emu
->emu_inb
) (emu
, emu
->x86
.R_DX
);
3661 /****************************************************************************
3664 ****************************************************************************/
3666 x86emuOp_in_word_AX_DX(struct X86EMU
*emu
)
3668 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
3669 emu
->x86
.R_EAX
= (*emu
->emu_inl
) (emu
, emu
->x86
.R_DX
);
3671 emu
->x86
.R_AX
= (*emu
->emu_inw
) (emu
, emu
->x86
.R_DX
);
3674 /****************************************************************************
3677 ****************************************************************************/
3679 x86emuOp_out_byte_DX_AL(struct X86EMU
*emu
)
3681 (*emu
->emu_outb
) (emu
, emu
->x86
.R_DX
, emu
->x86
.R_AL
);
3683 /****************************************************************************
3686 ****************************************************************************/
3688 x86emuOp_out_word_DX_AX(struct X86EMU
*emu
)
3690 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
3691 (*emu
->emu_outl
) (emu
, emu
->x86
.R_DX
, emu
->x86
.R_EAX
);
3693 (*emu
->emu_outw
) (emu
, emu
->x86
.R_DX
, emu
->x86
.R_AX
);
3696 /****************************************************************************
3699 ****************************************************************************/
3701 x86emuOp_lock(struct X86EMU
*emu
)
3704 /*opcode 0xf1 ILLEGAL OPERATION */
3706 /****************************************************************************
3709 ****************************************************************************/
3711 x86emuOp_cmc(struct X86EMU
*emu
)
3713 if (ACCESS_FLAG(F_CF
))
3718 /****************************************************************************
3721 ****************************************************************************/
3723 x86emuOp_opcF6_byte_RM(struct X86EMU
*emu
)
3725 uint8_t destval
, srcval
;
3727 /* long, drawn out code follows. Double switch for a total of 32
3729 fetch_decode_modrm(emu
);
3730 if (emu
->cur_rh
== 1)
3731 X86EMU_halt_sys(emu
);
3733 if (emu
->cur_rh
== 0) {
3734 destval
= decode_and_fetch_byte_imm8(emu
, &srcval
);
3735 test_byte(emu
, destval
, srcval
);
3738 destval
= decode_and_fetch_byte(emu
);
3739 switch (emu
->cur_rh
) {
3742 write_back_byte(emu
, destval
);
3745 destval
= neg_byte(emu
, destval
);
3746 write_back_byte(emu
, destval
);
3749 mul_byte(emu
, destval
);
3752 imul_byte(emu
, destval
);
3755 div_byte(emu
, destval
);
3758 idiv_byte(emu
, destval
);
3762 /****************************************************************************
3765 ****************************************************************************/
3767 x86emuOp32_opcF7_word_RM(struct X86EMU
*emu
)
3769 uint32_t destval
, srcval
;
3771 /* long, drawn out code follows. Double switch for a total of 32
3773 fetch_decode_modrm(emu
);
3774 if (emu
->cur_rh
== 1)
3775 X86EMU_halt_sys(emu
);
3777 if (emu
->cur_rh
== 0) {
3778 if (emu
->cur_mod
!= 3) {
3779 uint32_t destoffset
;
3781 destoffset
= decode_rl_address(emu
);
3782 srcval
= fetch_long_imm(emu
);
3783 destval
= fetch_data_long(emu
, destoffset
);
3785 srcval
= fetch_long_imm(emu
);
3786 destval
= *decode_rl_long_register(emu
);
3788 test_long(emu
, destval
, srcval
);
3791 destval
= decode_and_fetch_long(emu
);
3792 switch (emu
->cur_rh
) {
3795 write_back_long(emu
, destval
);
3798 destval
= neg_long(emu
, destval
);
3799 write_back_long(emu
, destval
);
3802 mul_long(emu
, destval
);
3805 imul_long(emu
, destval
);
3808 div_long(emu
, destval
);
3811 idiv_long(emu
, destval
);
3816 x86emuOp16_opcF7_word_RM(struct X86EMU
*emu
)
3818 uint16_t destval
, srcval
;
3820 /* long, drawn out code follows. Double switch for a total of 32
3822 fetch_decode_modrm(emu
);
3823 if (emu
->cur_rh
== 1)
3824 X86EMU_halt_sys(emu
);
3826 if (emu
->cur_rh
== 0) {
3827 if (emu
->cur_mod
!= 3) {
3828 uint32_t destoffset
;
3830 destoffset
= decode_rl_address(emu
);
3831 srcval
= fetch_word_imm(emu
);
3832 destval
= fetch_data_word(emu
, destoffset
);
3834 srcval
= fetch_word_imm(emu
);
3835 destval
= *decode_rl_word_register(emu
);
3837 test_word(emu
, destval
, srcval
);
3840 destval
= decode_and_fetch_word(emu
);
3841 switch (emu
->cur_rh
) {
3844 write_back_word(emu
, destval
);
3847 destval
= neg_word(emu
, destval
);
3848 write_back_word(emu
, destval
);
3851 mul_word(emu
, destval
);
3854 imul_word(emu
, destval
);
3857 div_word(emu
, destval
);
3860 idiv_word(emu
, destval
);
3865 x86emuOp_opcF7_word_RM(struct X86EMU
*emu
)
3867 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
3868 x86emuOp32_opcF7_word_RM(emu
);
3870 x86emuOp16_opcF7_word_RM(emu
);
3872 /****************************************************************************
3875 ****************************************************************************/
3877 x86emuOp_opcFE_byte_RM(struct X86EMU
*emu
)
3880 uint32_t destoffset
;
3883 /* Yet another special case instruction. */
3884 fetch_decode_modrm(emu
);
3885 if (emu
->cur_mod
!= 3) {
3886 destoffset
= decode_rl_address(emu
);
3887 switch (emu
->cur_rh
) {
3888 case 0: /* inc word ptr ... */
3889 destval
= fetch_data_byte(emu
, destoffset
);
3890 destval
= inc_byte(emu
, destval
);
3891 store_data_byte(emu
, destoffset
, destval
);
3893 case 1: /* dec word ptr ... */
3894 destval
= fetch_data_byte(emu
, destoffset
);
3895 destval
= dec_byte(emu
, destval
);
3896 store_data_byte(emu
, destoffset
, destval
);
3900 destreg
= decode_rl_byte_register(emu
);
3901 switch (emu
->cur_rh
) {
3903 *destreg
= inc_byte(emu
, *destreg
);
3906 *destreg
= dec_byte(emu
, *destreg
);
3911 /****************************************************************************
3914 ****************************************************************************/
3916 x86emuOp32_opcFF_word_RM(struct X86EMU
*emu
)
3918 uint32_t destoffset
= 0;
3919 uint32_t destval
, *destreg
;
3921 if (emu
->cur_mod
!= 3) {
3922 destoffset
= decode_rl_address(emu
);
3923 destval
= fetch_data_long(emu
, destoffset
);
3924 switch (emu
->cur_rh
) {
3925 case 0: /* inc word ptr ... */
3926 destval
= inc_long(emu
, destval
);
3927 store_data_long(emu
, destoffset
, destval
);
3929 case 1: /* dec word ptr ... */
3930 destval
= dec_long(emu
, destval
);
3931 store_data_long(emu
, destoffset
, destval
);
3933 case 6: /* push word ptr ... */
3934 push_long(emu
, destval
);
3938 destreg
= decode_rl_long_register(emu
);
3939 switch (emu
->cur_rh
) {
3941 *destreg
= inc_long(emu
, *destreg
);
3944 *destreg
= dec_long(emu
, *destreg
);
3947 push_long(emu
, *destreg
);
3954 x86emuOp16_opcFF_word_RM(struct X86EMU
*emu
)
3956 uint32_t destoffset
= 0;
3960 if (emu
->cur_mod
!= 3) {
3961 destoffset
= decode_rl_address(emu
);
3962 destval
= fetch_data_word(emu
, destoffset
);
3963 switch (emu
->cur_rh
) {
3965 destval
= inc_word(emu
, destval
);
3966 store_data_word(emu
, destoffset
, destval
);
3968 case 1: /* dec word ptr ... */
3969 destval
= dec_word(emu
, destval
);
3970 store_data_word(emu
, destoffset
, destval
);
3972 case 6: /* push word ptr ... */
3973 push_word(emu
, destval
);
3977 destreg
= decode_rl_word_register(emu
);
3978 switch (emu
->cur_rh
) {
3980 *destreg
= inc_word(emu
, *destreg
);
3983 *destreg
= dec_word(emu
, *destreg
);
3986 push_word(emu
, *destreg
);
3993 x86emuOp_opcFF_word_RM(struct X86EMU
*emu
)
3995 uint32_t destoffset
= 0;
3996 uint16_t destval
, destval2
;
3998 /* Yet another special case instruction. */
3999 fetch_decode_modrm(emu
);
4000 if ((emu
->cur_mod
== 3 && (emu
->cur_rh
== 3 || emu
->cur_rh
== 5)) || emu
->cur_rh
== 7)
4001 X86EMU_halt_sys(emu
);
4002 if (emu
->cur_rh
== 0 || emu
->cur_rh
== 1 || emu
->cur_rh
== 6) {
4003 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
4004 x86emuOp32_opcFF_word_RM(emu
);
4006 x86emuOp16_opcFF_word_RM(emu
);
4010 if (emu
->cur_mod
!= 3) {
4011 destoffset
= decode_rl_address(emu
);
4012 destval
= fetch_data_word(emu
, destoffset
);
4013 switch (emu
->cur_rh
) {
4014 case 3: /* call far ptr ... */
4015 destval2
= fetch_data_word(emu
, destoffset
+ 2);
4016 push_word(emu
, emu
->x86
.R_CS
);
4017 emu
->x86
.R_CS
= destval2
;
4018 push_word(emu
, emu
->x86
.R_IP
);
4019 emu
->x86
.R_IP
= destval
;
4021 case 5: /* jmp far ptr ... */
4022 destval2
= fetch_data_word(emu
, destoffset
+ 2);
4023 emu
->x86
.R_IP
= destval
;
4024 emu
->x86
.R_CS
= destval2
;
4028 destval
= *decode_rl_word_register(emu
);
4031 switch (emu
->cur_rh
) {
4032 case 2: /* call word ptr */
4033 push_word(emu
, emu
->x86
.R_IP
);
4034 emu
->x86
.R_IP
= destval
;
4037 emu
->x86
.R_IP
= destval
;
4041 /***************************************************************************
4042 * Single byte operation code table:
4043 **************************************************************************/
4045 X86EMU_exec_one_byte(struct X86EMU
* emu
)
4049 op1
= fetch_byte_imm(emu
);
4053 common_binop_byte_rm_r(emu
, add_byte
);
4056 common_binop_word_long_rm_r(emu
, add_word
, add_long
);
4059 common_binop_byte_r_rm(emu
, add_byte
);
4062 common_binop_word_long_r_rm(emu
, add_word
, add_long
);
4065 common_binop_byte_imm(emu
, add_byte
);
4068 common_binop_word_long_imm(emu
, add_word
, add_long
);
4071 push_word(emu
, emu
->x86
.R_ES
);
4074 emu
->x86
.R_ES
= pop_word(emu
);
4078 common_binop_byte_rm_r(emu
, or_byte
);
4081 common_binop_word_long_rm_r(emu
, or_word
, or_long
);
4084 common_binop_byte_r_rm(emu
, or_byte
);
4087 common_binop_word_long_r_rm(emu
, or_word
, or_long
);
4090 common_binop_byte_imm(emu
, or_byte
);
4093 common_binop_word_long_imm(emu
, or_word
, or_long
);
4096 push_word(emu
, emu
->x86
.R_CS
);
4099 X86EMU_exec_two_byte(emu
);
4103 common_binop_byte_rm_r(emu
, adc_byte
);
4106 common_binop_word_long_rm_r(emu
, adc_word
, adc_long
);
4109 common_binop_byte_r_rm(emu
, adc_byte
);
4112 common_binop_word_long_r_rm(emu
, adc_word
, adc_long
);
4115 common_binop_byte_imm(emu
, adc_byte
);
4118 common_binop_word_long_imm(emu
, adc_word
, adc_long
);
4121 push_word(emu
, emu
->x86
.R_SS
);
4124 emu
->x86
.R_SS
= pop_word(emu
);
4128 common_binop_byte_rm_r(emu
, sbb_byte
);
4131 common_binop_word_long_rm_r(emu
, sbb_word
, sbb_long
);
4134 common_binop_byte_r_rm(emu
, sbb_byte
);
4137 common_binop_word_long_r_rm(emu
, sbb_word
, sbb_long
);
4140 common_binop_byte_imm(emu
, sbb_byte
);
4143 common_binop_word_long_imm(emu
, sbb_word
, sbb_long
);
4146 push_word(emu
, emu
->x86
.R_DS
);
4149 emu
->x86
.R_DS
= pop_word(emu
);
4153 common_binop_byte_rm_r(emu
, and_byte
);
4156 common_binop_word_long_rm_r(emu
, and_word
, and_long
);
4159 common_binop_byte_r_rm(emu
, and_byte
);
4162 common_binop_word_long_r_rm(emu
, and_word
, and_long
);
4165 common_binop_byte_imm(emu
, and_byte
);
4168 common_binop_word_long_imm(emu
, and_word
, and_long
);
4171 emu
->x86
.mode
|= SYSMODE_SEGOVR_ES
;
4174 emu
->x86
.R_AL
= daa_byte(emu
, emu
->x86
.R_AL
);
4178 common_binop_byte_rm_r(emu
, sub_byte
);
4181 common_binop_word_long_rm_r(emu
, sub_word
, sub_long
);
4184 common_binop_byte_r_rm(emu
, sub_byte
);
4187 common_binop_word_long_r_rm(emu
, sub_word
, sub_long
);
4190 common_binop_byte_imm(emu
, sub_byte
);
4193 common_binop_word_long_imm(emu
, sub_word
, sub_long
);
4196 emu
->x86
.mode
|= SYSMODE_SEGOVR_CS
;
4199 emu
->x86
.R_AL
= das_byte(emu
, emu
->x86
.R_AL
);
4203 common_binop_byte_rm_r(emu
, xor_byte
);
4206 common_binop_word_long_rm_r(emu
, xor_word
, xor_long
);
4209 common_binop_byte_r_rm(emu
, xor_byte
);
4212 common_binop_word_long_r_rm(emu
, xor_word
, xor_long
);
4215 common_binop_byte_imm(emu
, xor_byte
);
4218 common_binop_word_long_imm(emu
, xor_word
, xor_long
);
4221 emu
->x86
.mode
|= SYSMODE_SEGOVR_SS
;
4224 emu
->x86
.R_AX
= aaa_word(emu
, emu
->x86
.R_AX
);
4228 common_binop_ns_byte_rm_r(emu
, cmp_byte_no_return
);
4231 common_binop_ns_word_long_rm_r(emu
, cmp_word_no_return
,
4232 cmp_long_no_return
);
4235 x86emuOp_cmp_byte_R_RM(emu
);
4238 x86emuOp_cmp_word_R_RM(emu
);
4241 x86emuOp_cmp_byte_AL_IMM(emu
);
4244 x86emuOp_cmp_word_AX_IMM(emu
);
4247 emu
->x86
.mode
|= SYSMODE_SEGOVR_DS
;
4250 emu
->x86
.R_AX
= aas_word(emu
, emu
->x86
.R_AX
);
4254 common_inc_word_long(emu
, &emu
->x86
.register_a
);
4257 common_inc_word_long(emu
, &emu
->x86
.register_c
);
4260 common_inc_word_long(emu
, &emu
->x86
.register_d
);
4263 common_inc_word_long(emu
, &emu
->x86
.register_b
);
4266 common_inc_word_long(emu
, &emu
->x86
.register_sp
);
4269 common_inc_word_long(emu
, &emu
->x86
.register_bp
);
4272 common_inc_word_long(emu
, &emu
->x86
.register_si
);
4275 common_inc_word_long(emu
, &emu
->x86
.register_di
);
4279 common_dec_word_long(emu
, &emu
->x86
.register_a
);
4282 common_dec_word_long(emu
, &emu
->x86
.register_c
);
4285 common_dec_word_long(emu
, &emu
->x86
.register_d
);
4288 common_dec_word_long(emu
, &emu
->x86
.register_b
);
4291 common_dec_word_long(emu
, &emu
->x86
.register_sp
);
4294 common_dec_word_long(emu
, &emu
->x86
.register_bp
);
4297 common_dec_word_long(emu
, &emu
->x86
.register_si
);
4300 common_dec_word_long(emu
, &emu
->x86
.register_di
);
4304 common_push_word_long(emu
, &emu
->x86
.register_a
);
4307 common_push_word_long(emu
, &emu
->x86
.register_c
);
4310 common_push_word_long(emu
, &emu
->x86
.register_d
);
4313 common_push_word_long(emu
, &emu
->x86
.register_b
);
4316 common_push_word_long(emu
, &emu
->x86
.register_sp
);
4319 common_push_word_long(emu
, &emu
->x86
.register_bp
);
4322 common_push_word_long(emu
, &emu
->x86
.register_si
);
4325 common_push_word_long(emu
, &emu
->x86
.register_di
);
4329 common_pop_word_long(emu
, &emu
->x86
.register_a
);
4332 common_pop_word_long(emu
, &emu
->x86
.register_c
);
4335 common_pop_word_long(emu
, &emu
->x86
.register_d
);
4338 common_pop_word_long(emu
, &emu
->x86
.register_b
);
4341 common_pop_word_long(emu
, &emu
->x86
.register_sp
);
4344 common_pop_word_long(emu
, &emu
->x86
.register_bp
);
4347 common_pop_word_long(emu
, &emu
->x86
.register_si
);
4350 common_pop_word_long(emu
, &emu
->x86
.register_di
);
4354 x86emuOp_push_all(emu
);
4357 x86emuOp_pop_all(emu
);
4362 emu
->x86
.mode
|= SYSMODE_SEGOVR_FS
;
4365 emu
->x86
.mode
|= SYSMODE_SEGOVR_GS
;
4368 emu
->x86
.mode
|= SYSMODE_PREFIX_DATA
;
4371 emu
->x86
.mode
|= SYSMODE_PREFIX_ADDR
;
4375 x86emuOp_push_word_IMM(emu
);
4378 common_imul_imm(emu
, false);
4381 x86emuOp_push_byte_IMM(emu
);
4384 common_imul_imm(emu
, true);
4390 x86emuOp_ins_word(emu
);
4396 x86emuOp_outs_word(emu
);
4400 common_jmp_near(emu
, ACCESS_FLAG(F_OF
));
4403 common_jmp_near(emu
, !ACCESS_FLAG(F_OF
));
4406 common_jmp_near(emu
, ACCESS_FLAG(F_CF
));
4409 common_jmp_near(emu
, !ACCESS_FLAG(F_CF
));
4412 common_jmp_near(emu
, ACCESS_FLAG(F_ZF
));
4415 common_jmp_near(emu
, !ACCESS_FLAG(F_ZF
));
4418 common_jmp_near(emu
, ACCESS_FLAG(F_CF
) || ACCESS_FLAG(F_ZF
));
4421 common_jmp_near(emu
, !ACCESS_FLAG(F_CF
) && !ACCESS_FLAG(F_ZF
));
4425 common_jmp_near(emu
, ACCESS_FLAG(F_SF
));
4428 common_jmp_near(emu
, !ACCESS_FLAG(F_SF
));
4431 common_jmp_near(emu
, ACCESS_FLAG(F_PF
));
4434 common_jmp_near(emu
, !ACCESS_FLAG(F_PF
));
4437 x86emuOp_jump_near_L(emu
);
4440 x86emuOp_jump_near_NL(emu
);
4443 x86emuOp_jump_near_LE(emu
);
4446 x86emuOp_jump_near_NLE(emu
);
4450 x86emuOp_opc80_byte_RM_IMM(emu
);
4453 x86emuOp_opc81_word_RM_IMM(emu
);
4456 x86emuOp_opc82_byte_RM_IMM(emu
);
4459 x86emuOp_opc83_word_RM_IMM(emu
);
4462 common_binop_ns_byte_rm_r(emu
, test_byte
);
4465 common_binop_ns_word_long_rm_r(emu
, test_word
, test_long
);
4468 x86emuOp_xchg_byte_RM_R(emu
);
4471 x86emuOp_xchg_word_RM_R(emu
);
4475 x86emuOp_mov_byte_RM_R(emu
);
4478 x86emuOp_mov_word_RM_R(emu
);
4481 x86emuOp_mov_byte_R_RM(emu
);
4484 x86emuOp_mov_word_R_RM(emu
);
4487 x86emuOp_mov_word_RM_SR(emu
);
4490 x86emuOp_lea_word_R_M(emu
);
4493 x86emuOp_mov_word_SR_RM(emu
);
4496 x86emuOp_pop_RM(emu
);
4503 x86emuOp_xchg_word_AX_CX(emu
);
4506 x86emuOp_xchg_word_AX_DX(emu
);
4509 x86emuOp_xchg_word_AX_BX(emu
);
4512 x86emuOp_xchg_word_AX_SP(emu
);
4515 x86emuOp_xchg_word_AX_BP(emu
);
4518 x86emuOp_xchg_word_AX_SI(emu
);
4521 x86emuOp_xchg_word_AX_DI(emu
);
4531 x86emuOp_call_far_IMM(emu
);
4537 x86emuOp_pushf_word(emu
);
4540 x86emuOp_popf_word(emu
);
4550 x86emuOp_mov_AL_M_IMM(emu
);
4553 x86emuOp_mov_AX_M_IMM(emu
);
4556 x86emuOp_mov_M_AL_IMM(emu
);
4559 x86emuOp_mov_M_AX_IMM(emu
);
4562 x86emuOp_movs_byte(emu
);
4565 x86emuOp_movs_word(emu
);
4568 x86emuOp_cmps_byte(emu
);
4571 x86emuOp_cmps_word(emu
);
4575 test_byte(emu
, emu
->x86
.R_AL
, fetch_byte_imm(emu
));
4578 x86emuOp_test_AX_IMM(emu
);
4581 x86emuOp_stos_byte(emu
);
4584 x86emuOp_stos_word(emu
);
4587 x86emuOp_lods_byte(emu
);
4590 x86emuOp_lods_word(emu
);
4593 x86emuOp_scas_byte(emu
);
4596 x86emuOp_scas_word(emu
);
4600 emu
->x86
.R_AL
= fetch_byte_imm(emu
);
4603 emu
->x86
.R_CL
= fetch_byte_imm(emu
);
4606 emu
->x86
.R_DL
= fetch_byte_imm(emu
);
4609 emu
->x86
.R_BL
= fetch_byte_imm(emu
);
4612 emu
->x86
.R_AH
= fetch_byte_imm(emu
);
4615 emu
->x86
.R_CH
= fetch_byte_imm(emu
);
4618 emu
->x86
.R_DH
= fetch_byte_imm(emu
);
4621 emu
->x86
.R_BH
= fetch_byte_imm(emu
);
4625 x86emuOp_mov_word_AX_IMM(emu
);
4628 x86emuOp_mov_word_CX_IMM(emu
);
4631 x86emuOp_mov_word_DX_IMM(emu
);
4634 x86emuOp_mov_word_BX_IMM(emu
);
4637 x86emuOp_mov_word_SP_IMM(emu
);
4640 x86emuOp_mov_word_BP_IMM(emu
);
4643 x86emuOp_mov_word_SI_IMM(emu
);
4646 x86emuOp_mov_word_DI_IMM(emu
);
4650 x86emuOp_opcC0_byte_RM_MEM(emu
);
4653 x86emuOp_opcC1_word_RM_MEM(emu
);
4656 x86emuOp_ret_near_IMM(emu
);
4659 emu
->x86
.R_IP
= pop_word(emu
);
4662 common_load_far_pointer(emu
, &emu
->x86
.R_ES
);
4665 common_load_far_pointer(emu
, &emu
->x86
.R_DS
);
4668 x86emuOp_mov_byte_RM_IMM(emu
);
4671 x86emuOp_mov_word_RM_IMM(emu
);
4674 x86emuOp_enter(emu
);
4677 x86emuOp_leave(emu
);
4680 x86emuOp_ret_far_IMM(emu
);
4683 x86emuOp_ret_far(emu
);
4689 x86emuOp_int_IMM(emu
);
4699 x86emuOp_opcD0_byte_RM_1(emu
);
4702 x86emuOp_opcD1_word_RM_1(emu
);
4705 x86emuOp_opcD2_byte_RM_CL(emu
);
4708 x86emuOp_opcD3_word_RM_CL(emu
);
4716 /* 0xd6 Undocumented SETALC instruction */
4721 x86emuOp_esc_coprocess_d8(emu
);
4724 x86emuOp_esc_coprocess_d9(emu
);
4727 x86emuOp_esc_coprocess_da(emu
);
4730 x86emuOp_esc_coprocess_db(emu
);
4733 x86emuOp_esc_coprocess_dc(emu
);
4736 x86emuOp_esc_coprocess_dd(emu
);
4739 x86emuOp_esc_coprocess_de(emu
);
4742 x86emuOp_esc_coprocess_df(emu
);
4746 x86emuOp_loopne(emu
);
4749 x86emuOp_loope(emu
);
4758 x86emuOp_in_byte_AL_IMM(emu
);
4761 x86emuOp_in_word_AX_IMM(emu
);
4764 x86emuOp_out_byte_IMM_AL(emu
);
4767 x86emuOp_out_word_IMM_AX(emu
);
4771 x86emuOp_call_near_IMM(emu
);
4774 x86emuOp_jump_near_IMM(emu
);
4777 x86emuOp_jump_far_IMM(emu
);
4780 x86emuOp_jump_byte_IMM(emu
);
4783 x86emuOp_in_byte_AL_DX(emu
);
4786 x86emuOp_in_word_AX_DX(emu
);
4789 x86emuOp_out_byte_DX_AL(emu
);
4792 x86emuOp_out_word_DX_AX(emu
);
4799 emu
->x86
.mode
|= SYSMODE_PREFIX_REPNE
;
4802 emu
->x86
.mode
|= SYSMODE_PREFIX_REPE
;
4805 X86EMU_halt_sys(emu
);
4811 x86emuOp_opcF6_byte_RM(emu
);
4814 x86emuOp_opcF7_word_RM(emu
);
4836 x86emuOp_opcFE_byte_RM(emu
);
4839 x86emuOp_opcFF_word_RM(emu
);
4842 X86EMU_halt_sys(emu
);
4845 if (op1
!= 0x26 && op1
!= 0x2e && op1
!= 0x36 && op1
!= 0x3e &&
4847 emu
->x86
.mode
&= ~SYSMODE_CLRMASK
;
4851 common_jmp_long(struct X86EMU
*emu
, bool cond
)
4855 target
= (int16_t) fetch_word_imm(emu
);
4856 target
+= (int16_t) emu
->x86
.R_IP
;
4858 emu
->x86
.R_IP
= (uint16_t) target
;
4862 common_set_byte(struct X86EMU
*emu
, bool cond
)
4864 uint32_t destoffset
;
4865 uint8_t *destreg
, destval
;
4867 fetch_decode_modrm(emu
);
4868 destval
= cond
? 0x01 : 0x00;
4869 if (emu
->cur_mod
!= 3) {
4870 destoffset
= decode_rl_address(emu
);
4871 store_data_byte(emu
, destoffset
, destval
);
4873 destreg
= decode_rl_byte_register(emu
);
4879 common_bitstring32(struct X86EMU
*emu
, int op
)
4882 uint32_t srcval
, *shiftreg
, mask
;
4884 fetch_decode_modrm(emu
);
4885 shiftreg
= decode_rh_long_register(emu
);
4886 srcval
= decode_and_fetch_long_disp(emu
, (int16_t) *shiftreg
>> 5);
4887 bit
= *shiftreg
& 0x1F;
4889 CONDITIONAL_SET_FLAG(srcval
& mask
, F_CF
);
4895 write_back_long(emu
, srcval
| mask
);
4898 write_back_long(emu
, srcval
& ~mask
);
4901 write_back_long(emu
, srcval
^ mask
);
4907 common_bitstring16(struct X86EMU
*emu
, int op
)
4910 uint16_t srcval
, *shiftreg
, mask
;
4912 fetch_decode_modrm(emu
);
4913 shiftreg
= decode_rh_word_register(emu
);
4914 srcval
= decode_and_fetch_word_disp(emu
, (int16_t) *shiftreg
>> 4);
4915 bit
= *shiftreg
& 0xF;
4917 CONDITIONAL_SET_FLAG(srcval
& mask
, F_CF
);
4923 write_back_word(emu
, srcval
| mask
);
4926 write_back_word(emu
, srcval
& ~mask
);
4929 write_back_word(emu
, srcval
^ mask
);
4935 common_bitstring(struct X86EMU
*emu
, int op
)
4937 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
4938 common_bitstring32(emu
, op
);
4940 common_bitstring16(emu
, op
);
4944 common_bitsearch32(struct X86EMU
*emu
, int diff
)
4946 uint32_t srcval
, *dstreg
;
4948 fetch_decode_modrm(emu
);
4949 dstreg
= decode_rh_long_register(emu
);
4950 srcval
= decode_and_fetch_long(emu
);
4951 CONDITIONAL_SET_FLAG(srcval
== 0, F_ZF
);
4952 for (*dstreg
= 0; *dstreg
< 32; *dstreg
+= diff
) {
4953 if ((srcval
>> *dstreg
) & 1)
4959 common_bitsearch16(struct X86EMU
*emu
, int diff
)
4961 uint16_t srcval
, *dstreg
;
4963 fetch_decode_modrm(emu
);
4964 dstreg
= decode_rh_word_register(emu
);
4965 srcval
= decode_and_fetch_word(emu
);
4966 CONDITIONAL_SET_FLAG(srcval
== 0, F_ZF
);
4967 for (*dstreg
= 0; *dstreg
< 16; *dstreg
+= diff
) {
4968 if ((srcval
>> *dstreg
) & 1)
4974 common_bitsearch(struct X86EMU
*emu
, int diff
)
4976 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
4977 common_bitsearch32(emu
, diff
);
4979 common_bitsearch16(emu
, diff
);
4983 common_shift32(struct X86EMU
*emu
, bool shift_left
, bool use_cl
)
4986 uint32_t destval
, *shiftreg
;
4988 fetch_decode_modrm(emu
);
4989 shiftreg
= decode_rh_long_register(emu
);
4991 destval
= decode_and_fetch_long(emu
);
4992 shift
= emu
->x86
.R_CL
;
4994 destval
= decode_and_fetch_long_imm8(emu
, &shift
);
4997 destval
= shld_long(emu
, destval
, *shiftreg
, shift
);
4999 destval
= shrd_long(emu
, destval
, *shiftreg
, shift
);
5000 write_back_long(emu
, destval
);
5004 common_shift16(struct X86EMU
*emu
, bool shift_left
, bool use_cl
)
5007 uint16_t destval
, *shiftreg
;
5009 fetch_decode_modrm(emu
);
5010 shiftreg
= decode_rh_word_register(emu
);
5012 destval
= decode_and_fetch_word(emu
);
5013 shift
= emu
->x86
.R_CL
;
5015 destval
= decode_and_fetch_word_imm8(emu
, &shift
);
5018 destval
= shld_word(emu
, destval
, *shiftreg
, shift
);
5020 destval
= shrd_word(emu
, destval
, *shiftreg
, shift
);
5021 write_back_word(emu
, destval
);
5025 common_shift(struct X86EMU
*emu
, bool shift_left
, bool use_cl
)
5027 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
5028 common_shift32(emu
, shift_left
, use_cl
);
5030 common_shift16(emu
, shift_left
, use_cl
);
5033 /*----------------------------- Implementation ----------------------------*/
5034 #define xorl(a,b) ((a) && !(b)) || (!(a) && (b))
5036 /****************************************************************************
5038 Handles opcode 0x0f,0x31
5039 ****************************************************************************/
5041 x86emuOp2_rdtsc(struct X86EMU
*emu
)
5043 emu
->x86
.R_EAX
= emu
->cur_cycles
& 0xffffffff;
5044 emu
->x86
.R_EDX
= emu
->cur_cycles
>> 32;
5046 /****************************************************************************
5048 Handles opcode 0x0f,0xa0
5049 ****************************************************************************/
5051 x86emuOp2_push_FS(struct X86EMU
*emu
)
5053 push_word(emu
, emu
->x86
.R_FS
);
5055 /****************************************************************************
5057 Handles opcode 0x0f,0xa1
5058 ****************************************************************************/
5060 x86emuOp2_pop_FS(struct X86EMU
*emu
)
5062 emu
->x86
.R_FS
= pop_word(emu
);
5064 /****************************************************************************
5066 Handles opcode 0x0f,0xa1
5067 ****************************************************************************/
5068 #if defined(__i386__) || defined(__amd64__)
5070 hw_cpuid(uint32_t *a
, uint32_t *b
, uint32_t *c
, uint32_t *d
)
5072 __asm__
__volatile__("cpuid"
5073 : "=a" (*a
), "=b" (*b
),
5074 "=c" (*c
), "=d" (*d
)
5075 : "a" (*a
), "c" (*c
)
5080 x86emuOp2_cpuid(struct X86EMU
*emu
)
5082 #if defined(__i386__) || defined(__amd64__)
5083 hw_cpuid(&emu
->x86
.R_EAX
, &emu
->x86
.R_EBX
, &emu
->x86
.R_ECX
,
5086 switch (emu
->x86
.R_EAX
) {
5089 #if !defined(__i386__) && !defined(__amd64__)
5090 /* "GenuineIntel" */
5091 emu
->x86
.R_EBX
= 0x756e6547;
5092 emu
->x86
.R_EDX
= 0x49656e69;
5093 emu
->x86
.R_ECX
= 0x6c65746e;
5097 #if !defined(__i386__) && !defined(__amd64__)
5098 emu
->x86
.R_EAX
= 0x00000480;
5099 emu
->x86
.R_EBX
= emu
->x86
.R_ECX
= 0;
5100 emu
->x86
.R_EDX
= 0x00000002;
5102 emu
->x86
.R_EDX
&= 0x00000012;
5106 emu
->x86
.R_EAX
= emu
->x86
.R_EBX
= emu
->x86
.R_ECX
=
5111 /****************************************************************************
5113 Handles opcode 0x0f,0xa3
5114 ****************************************************************************/
5116 x86emuOp2_bt_R(struct X86EMU
*emu
)
5118 common_bitstring(emu
, 0);
5120 /****************************************************************************
5122 Handles opcode 0x0f,0xa4
5123 ****************************************************************************/
5125 x86emuOp2_shld_IMM(struct X86EMU
*emu
)
5127 common_shift(emu
, true, false);
5129 /****************************************************************************
5131 Handles opcode 0x0f,0xa5
5132 ****************************************************************************/
5134 x86emuOp2_shld_CL(struct X86EMU
*emu
)
5136 common_shift(emu
, true, true);
5138 /****************************************************************************
5140 Handles opcode 0x0f,0xa8
5141 ****************************************************************************/
5143 x86emuOp2_push_GS(struct X86EMU
*emu
)
5145 push_word(emu
, emu
->x86
.R_GS
);
5147 /****************************************************************************
5149 Handles opcode 0x0f,0xa9
5150 ****************************************************************************/
5152 x86emuOp2_pop_GS(struct X86EMU
*emu
)
5154 emu
->x86
.R_GS
= pop_word(emu
);
5156 /****************************************************************************
5158 Handles opcode 0x0f,0xab
5159 ****************************************************************************/
5161 x86emuOp2_bts_R(struct X86EMU
*emu
)
5163 common_bitstring(emu
, 1);
5165 /****************************************************************************
5167 Handles opcode 0x0f,0xac
5168 ****************************************************************************/
5170 x86emuOp2_shrd_IMM(struct X86EMU
*emu
)
5172 common_shift(emu
, false, false);
5174 /****************************************************************************
5176 Handles opcode 0x0f,0xad
5177 ****************************************************************************/
5179 x86emuOp2_shrd_CL(struct X86EMU
*emu
)
5181 common_shift(emu
, false, true);
5183 /****************************************************************************
5185 Handles opcode 0x0f,0xaf
5186 ****************************************************************************/
5188 x86emuOp2_32_imul_R_RM(struct X86EMU
*emu
)
5190 uint32_t *destreg
, srcval
;
5193 fetch_decode_modrm(emu
);
5194 destreg
= decode_rh_long_register(emu
);
5195 srcval
= decode_and_fetch_long(emu
);
5196 res
= (int32_t) *destreg
* (int32_t)srcval
;
5197 if (res
> 0xffffffff) {
5204 *destreg
= (uint32_t) res
;
5208 x86emuOp2_16_imul_R_RM(struct X86EMU
*emu
)
5210 uint16_t *destreg
, srcval
;
5213 fetch_decode_modrm(emu
);
5214 destreg
= decode_rh_word_register(emu
);
5215 srcval
= decode_and_fetch_word(emu
);
5216 res
= (int16_t) * destreg
* (int16_t)srcval
;
5224 *destreg
= (uint16_t) res
;
5228 x86emuOp2_imul_R_RM(struct X86EMU
*emu
)
5230 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
5231 x86emuOp2_32_imul_R_RM(emu
);
5233 x86emuOp2_16_imul_R_RM(emu
);
5235 /****************************************************************************
5237 Handles opcode 0x0f,0xb2
5238 ****************************************************************************/
5240 x86emuOp2_lss_R_IMM(struct X86EMU
*emu
)
5242 common_load_far_pointer(emu
, &emu
->x86
.R_SS
);
5244 /****************************************************************************
5246 Handles opcode 0x0f,0xb3
5247 ****************************************************************************/
5249 x86emuOp2_btr_R(struct X86EMU
*emu
)
5251 common_bitstring(emu
, 2);
5253 /****************************************************************************
5255 Handles opcode 0x0f,0xb4
5256 ****************************************************************************/
5258 x86emuOp2_lfs_R_IMM(struct X86EMU
*emu
)
5260 common_load_far_pointer(emu
, &emu
->x86
.R_FS
);
5262 /****************************************************************************
5264 Handles opcode 0x0f,0xb5
5265 ****************************************************************************/
5267 x86emuOp2_lgs_R_IMM(struct X86EMU
*emu
)
5269 common_load_far_pointer(emu
, &emu
->x86
.R_GS
);
5271 /****************************************************************************
5273 Handles opcode 0x0f,0xb6
5274 ****************************************************************************/
5276 x86emuOp2_32_movzx_byte_R_RM(struct X86EMU
*emu
)
5280 fetch_decode_modrm(emu
);
5281 destreg
= decode_rh_long_register(emu
);
5282 *destreg
= decode_and_fetch_byte(emu
);
5286 x86emuOp2_16_movzx_byte_R_RM(struct X86EMU
*emu
)
5290 fetch_decode_modrm(emu
);
5291 destreg
= decode_rh_word_register(emu
);
5292 *destreg
= decode_and_fetch_byte(emu
);
5296 x86emuOp2_movzx_byte_R_RM(struct X86EMU
*emu
)
5298 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
5299 x86emuOp2_32_movzx_byte_R_RM(emu
);
5301 x86emuOp2_16_movzx_byte_R_RM(emu
);
5303 /****************************************************************************
5305 Handles opcode 0x0f,0xb7
5306 ****************************************************************************/
5308 x86emuOp2_movzx_word_R_RM(struct X86EMU
*emu
)
5312 fetch_decode_modrm(emu
);
5313 destreg
= decode_rh_long_register(emu
);
5314 *destreg
= decode_and_fetch_word(emu
);
5316 /****************************************************************************
5318 Handles opcode 0x0f,0xba
5319 ****************************************************************************/
5321 x86emuOp2_32_btX_I(struct X86EMU
*emu
)
5324 uint32_t srcval
, mask
;
5327 fetch_decode_modrm(emu
);
5328 if (emu
->cur_rh
< 4)
5329 X86EMU_halt_sys(emu
);
5331 srcval
= decode_and_fetch_long_imm8(emu
, &shift
);
5333 mask
= (0x1 << bit
);
5335 switch (emu
->cur_rh
) {
5337 write_back_long(emu
, srcval
| mask
);
5340 write_back_long(emu
, srcval
& ~mask
);
5343 write_back_long(emu
, srcval
^ mask
);
5346 CONDITIONAL_SET_FLAG(srcval
& mask
, F_CF
);
5350 x86emuOp2_16_btX_I(struct X86EMU
*emu
)
5354 uint16_t srcval
, mask
;
5357 fetch_decode_modrm(emu
);
5358 if (emu
->cur_rh
< 4)
5359 X86EMU_halt_sys(emu
);
5361 srcval
= decode_and_fetch_word_imm8(emu
, &shift
);
5363 mask
= (0x1 << bit
);
5364 switch (emu
->cur_rh
) {
5366 write_back_word(emu
, srcval
| mask
);
5369 write_back_word(emu
, srcval
& ~mask
);
5372 write_back_word(emu
, srcval
^ mask
);
5375 CONDITIONAL_SET_FLAG(srcval
& mask
, F_CF
);
5379 x86emuOp2_btX_I(struct X86EMU
*emu
)
5381 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
5382 x86emuOp2_32_btX_I(emu
);
5384 x86emuOp2_16_btX_I(emu
);
5386 /****************************************************************************
5388 Handles opcode 0x0f,0xbb
5389 ****************************************************************************/
5391 x86emuOp2_btc_R(struct X86EMU
*emu
)
5393 common_bitstring(emu
, 3);
5395 /****************************************************************************
5397 Handles opcode 0x0f,0xbc
5398 ****************************************************************************/
5400 x86emuOp2_bsf(struct X86EMU
*emu
)
5402 common_bitsearch(emu
, +1);
5404 /****************************************************************************
5406 Handles opcode 0x0f,0xbd
5407 ****************************************************************************/
5409 x86emuOp2_bsr(struct X86EMU
*emu
)
5411 common_bitsearch(emu
, -1);
5413 /****************************************************************************
5415 Handles opcode 0x0f,0xbe
5416 ****************************************************************************/
5418 x86emuOp2_32_movsx_byte_R_RM(struct X86EMU
*emu
)
5422 destreg
= decode_rh_long_register(emu
);
5423 *destreg
= (int32_t)(int8_t)decode_and_fetch_byte(emu
);
5427 x86emuOp2_16_movsx_byte_R_RM(struct X86EMU
*emu
)
5431 fetch_decode_modrm(emu
);
5432 destreg
= decode_rh_word_register(emu
);
5433 *destreg
= (int16_t)(int8_t)decode_and_fetch_byte(emu
);
5437 x86emuOp2_movsx_byte_R_RM(struct X86EMU
*emu
)
5439 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
)
5440 x86emuOp2_32_movsx_byte_R_RM(emu
);
5442 x86emuOp2_16_movsx_byte_R_RM(emu
);
5444 /****************************************************************************
5446 Handles opcode 0x0f,0xbf
5447 ****************************************************************************/
5449 x86emuOp2_movsx_word_R_RM(struct X86EMU
*emu
)
5453 fetch_decode_modrm(emu
);
5454 destreg
= decode_rh_long_register(emu
);
5455 *destreg
= (int32_t)(int16_t)decode_and_fetch_word(emu
);
5459 X86EMU_exec_two_byte(struct X86EMU
* emu
)
5463 op2
= fetch_byte_imm(emu
);
5466 /* 0x00 Group F (ring 0 PM) */
5467 /* 0x01 Group G (ring 0 PM) */
5468 /* 0x02 lar (ring 0 PM) */
5469 /* 0x03 lsl (ring 0 PM) */
5470 /* 0x05 loadall (undocumented) */
5471 /* 0x06 clts (ring 0 PM) */
5472 /* 0x07 loadall (undocumented) */
5473 /* 0x08 invd (ring 0 PM) */
5474 /* 0x09 wbinvd (ring 0 PM) */
5476 /* 0x20 mov reg32(op2); break;creg (ring 0 PM) */
5477 /* 0x21 mov reg32(op2); break;dreg (ring 0 PM) */
5478 /* 0x22 mov creg(op2); break;reg32 (ring 0 PM) */
5479 /* 0x23 mov dreg(op2); break;reg32 (ring 0 PM) */
5480 /* 0x24 mov reg32(op2); break;treg (ring 0 PM) */
5481 /* 0x26 mov treg(op2); break;reg32 (ring 0 PM) */
5484 x86emuOp2_rdtsc(emu
);
5488 common_jmp_long(emu
, ACCESS_FLAG(F_OF
));
5491 common_jmp_long(emu
, !ACCESS_FLAG(F_OF
));
5494 common_jmp_long(emu
, ACCESS_FLAG(F_CF
));
5497 common_jmp_long(emu
, !ACCESS_FLAG(F_CF
));
5500 common_jmp_long(emu
, ACCESS_FLAG(F_ZF
));
5503 common_jmp_long(emu
, !ACCESS_FLAG(F_ZF
));
5506 common_jmp_long(emu
, ACCESS_FLAG(F_CF
) || ACCESS_FLAG(F_ZF
));
5509 common_jmp_long(emu
, !(ACCESS_FLAG(F_CF
) || ACCESS_FLAG(F_ZF
)));
5512 common_jmp_long(emu
, ACCESS_FLAG(F_SF
));
5515 common_jmp_long(emu
, !ACCESS_FLAG(F_SF
));
5518 common_jmp_long(emu
, ACCESS_FLAG(F_PF
));
5521 common_jmp_long(emu
, !ACCESS_FLAG(F_PF
));
5524 common_jmp_long(emu
, xorl(ACCESS_FLAG(F_SF
), ACCESS_FLAG(F_OF
)));
5527 common_jmp_long(emu
, !(xorl(ACCESS_FLAG(F_SF
), ACCESS_FLAG(F_OF
))));
5530 common_jmp_long(emu
,
5531 (xorl(ACCESS_FLAG(F_SF
), ACCESS_FLAG(F_OF
)) || ACCESS_FLAG(F_ZF
)));
5534 common_jmp_long(emu
,
5535 !(xorl(ACCESS_FLAG(F_SF
), ACCESS_FLAG(F_OF
)) || ACCESS_FLAG(F_ZF
)));
5539 common_set_byte(emu
, ACCESS_FLAG(F_OF
));
5542 common_set_byte(emu
, !ACCESS_FLAG(F_OF
));
5545 common_set_byte(emu
, ACCESS_FLAG(F_CF
));
5548 common_set_byte(emu
, !ACCESS_FLAG(F_CF
));
5551 common_set_byte(emu
, ACCESS_FLAG(F_ZF
));
5554 common_set_byte(emu
, !ACCESS_FLAG(F_ZF
));
5557 common_set_byte(emu
, ACCESS_FLAG(F_CF
) || ACCESS_FLAG(F_ZF
));
5560 common_set_byte(emu
, !(ACCESS_FLAG(F_CF
) || ACCESS_FLAG(F_ZF
)));
5563 common_set_byte(emu
, ACCESS_FLAG(F_SF
));
5566 common_set_byte(emu
, !ACCESS_FLAG(F_SF
));
5569 common_set_byte(emu
, ACCESS_FLAG(F_PF
));
5572 common_set_byte(emu
, !ACCESS_FLAG(F_PF
));
5575 common_set_byte(emu
, xorl(ACCESS_FLAG(F_SF
), ACCESS_FLAG(F_OF
)));
5578 common_set_byte(emu
, xorl(ACCESS_FLAG(F_SF
), ACCESS_FLAG(F_OF
)));
5581 common_set_byte(emu
,
5582 (xorl(ACCESS_FLAG(F_SF
), ACCESS_FLAG(F_OF
)) ||
5583 ACCESS_FLAG(F_ZF
)));
5586 common_set_byte(emu
,
5587 !(xorl(ACCESS_FLAG(F_SF
), ACCESS_FLAG(F_OF
)) ||
5588 ACCESS_FLAG(F_ZF
)));
5592 x86emuOp2_push_FS(emu
);
5595 x86emuOp2_pop_FS(emu
);
5598 x86emuOp2_cpuid(emu
);
5601 x86emuOp2_bt_R(emu
);
5604 x86emuOp2_shld_IMM(emu
);
5607 x86emuOp2_shld_CL(emu
);
5610 x86emuOp2_push_GS(emu
);
5613 x86emuOp2_pop_GS(emu
);
5616 x86emuOp2_bts_R(emu
);
5619 x86emuOp2_shrd_IMM(emu
);
5622 x86emuOp2_shrd_CL(emu
);
5625 x86emuOp2_imul_R_RM(emu
);
5628 /* 0xb0 TODO: cmpxchg */
5629 /* 0xb1 TODO: cmpxchg */
5631 x86emuOp2_lss_R_IMM(emu
);
5634 x86emuOp2_btr_R(emu
);
5637 x86emuOp2_lfs_R_IMM(emu
);
5640 x86emuOp2_lgs_R_IMM(emu
);
5643 x86emuOp2_movzx_byte_R_RM(emu
);
5646 x86emuOp2_movzx_word_R_RM(emu
);
5649 x86emuOp2_btX_I(emu
);
5652 x86emuOp2_btc_R(emu
);
5661 x86emuOp2_movsx_byte_R_RM(emu
);
5664 x86emuOp2_movsx_word_R_RM(emu
);
5667 /* 0xc0 TODO: xadd */
5668 /* 0xc1 TODO: xadd */
5669 /* 0xc8 TODO: bswap */
5670 /* 0xc9 TODO: bswap */
5671 /* 0xca TODO: bswap */
5672 /* 0xcb TODO: bswap */
5673 /* 0xcc TODO: bswap */
5674 /* 0xcd TODO: bswap */
5675 /* 0xce TODO: bswap */
5676 /* 0xcf TODO: bswap */
5679 X86EMU_halt_sys(emu
);
5685 * Carry Chain Calculation
5687 * This represents a somewhat expensive calculation which is
5688 * apparently required to emulate the setting of the OF and AF flag.
5689 * The latter is not so important, but the former is. The overflow
5690 * flag is the XOR of the top two bits of the carry chain for an
5691 * addition (similar for subtraction). Since we do not want to
5692 * simulate the addition in a bitwise manner, we try to calculate the
5693 * carry chain given the two operands and the result.
5695 * So, given the following table, which represents the addition of two
5696 * bits, we can derive a formula for the carry chain.
5708 * Construction of table for cout:
5712 * |------------------
5716 * By inspection, one gets: cc = ab + r'(a + b)
5718 * That represents alot of operations, but NO CHOICE....
5720 * Borrow Chain Calculation.
5722 * The following table represents the subtraction of two bits, from
5723 * which we can derive a formula for the borrow chain.
5735 * Construction of table for cout:
5739 * |------------------
5743 * By inspection, one gets: bc = a'b + r(a' + b)
5745 ****************************************************************************/
5747 /*------------------------- Global Variables ------------------------------*/
5749 static uint32_t x86emu_parity_tab
[8] =
5760 #define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
5761 #define XOR2(x) (((x) ^ ((x)>>1)) & 0x1)
5763 /****************************************************************************
5765 Implements the AAA instruction and side effects.
5766 ****************************************************************************/
5768 aaa_word(struct X86EMU
*emu
, uint16_t d
)
5771 if ((d
& 0xf) > 0x9 || ACCESS_FLAG(F_AF
)) {
5780 res
= (uint16_t) (d
& 0xFF0F);
5782 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
5783 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
5786 /****************************************************************************
5788 Implements the AAA instruction and side effects.
5789 ****************************************************************************/
5791 aas_word(struct X86EMU
*emu
, uint16_t d
)
5794 if ((d
& 0xf) > 0x9 || ACCESS_FLAG(F_AF
)) {
5803 res
= (uint16_t) (d
& 0xFF0F);
5805 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
5806 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
5809 /****************************************************************************
5811 Implements the AAD instruction and side effects.
5812 ****************************************************************************/
5814 aad_word(struct X86EMU
*emu
, uint16_t d
)
5819 hb
= (uint8_t) ((d
>> 8) & 0xff);
5820 lb
= (uint8_t) ((d
& 0xff));
5821 l
= (uint16_t) ((lb
+ 10 * hb
) & 0xFF);
5826 CONDITIONAL_SET_FLAG(l
& 0x80, F_SF
);
5827 CONDITIONAL_SET_FLAG(l
== 0, F_ZF
);
5828 CONDITIONAL_SET_FLAG(PARITY(l
& 0xff), F_PF
);
5831 /****************************************************************************
5833 Implements the AAM instruction and side effects.
5834 ****************************************************************************/
5836 aam_word(struct X86EMU
*emu
, uint8_t d
)
5840 h
= (uint16_t) (d
/ 10);
5841 l
= (uint16_t) (d
% 10);
5842 l
|= (uint16_t) (h
<< 8);
5847 CONDITIONAL_SET_FLAG(l
& 0x80, F_SF
);
5848 CONDITIONAL_SET_FLAG(l
== 0, F_ZF
);
5849 CONDITIONAL_SET_FLAG(PARITY(l
& 0xff), F_PF
);
5852 /****************************************************************************
5854 Implements the ADC instruction and side effects.
5855 ****************************************************************************/
5857 adc_byte(struct X86EMU
*emu
, uint8_t d
, uint8_t s
)
5859 uint32_t res
; /* all operands in native machine order */
5862 if (ACCESS_FLAG(F_CF
))
5867 CONDITIONAL_SET_FLAG(res
& 0x100, F_CF
);
5868 CONDITIONAL_SET_FLAG((res
& 0xff) == 0, F_ZF
);
5869 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
5870 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
5872 /* calculate the carry chain SEE NOTE AT TOP. */
5873 cc
= (s
& d
) | ((~res
) & (s
| d
));
5874 CONDITIONAL_SET_FLAG(XOR2(cc
>> 6), F_OF
);
5875 CONDITIONAL_SET_FLAG(cc
& 0x8, F_AF
);
5876 return (uint8_t) res
;
5878 /****************************************************************************
5880 Implements the ADC instruction and side effects.
5881 ****************************************************************************/
5883 adc_word(struct X86EMU
*emu
, uint16_t d
, uint16_t s
)
5885 uint32_t res
; /* all operands in native machine order */
5888 if (ACCESS_FLAG(F_CF
))
5893 CONDITIONAL_SET_FLAG(res
& 0x10000, F_CF
);
5894 CONDITIONAL_SET_FLAG((res
& 0xffff) == 0, F_ZF
);
5895 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
5896 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
5898 /* calculate the carry chain SEE NOTE AT TOP. */
5899 cc
= (s
& d
) | ((~res
) & (s
| d
));
5900 CONDITIONAL_SET_FLAG(XOR2(cc
>> 14), F_OF
);
5901 CONDITIONAL_SET_FLAG(cc
& 0x8, F_AF
);
5902 return (uint16_t) res
;
5904 /****************************************************************************
5906 Implements the ADC instruction and side effects.
5907 ****************************************************************************/
5909 adc_long(struct X86EMU
*emu
, uint32_t d
, uint32_t s
)
5911 uint32_t lo
; /* all operands in native machine order */
5916 if (ACCESS_FLAG(F_CF
)) {
5917 lo
= 1 + (d
& 0xFFFF) + (s
& 0xFFFF);
5920 lo
= (d
& 0xFFFF) + (s
& 0xFFFF);
5923 hi
= (lo
>> 16) + (d
>> 16) + (s
>> 16);
5925 CONDITIONAL_SET_FLAG(hi
& 0x10000, F_CF
);
5926 CONDITIONAL_SET_FLAG((res
& 0xffffffff) == 0, F_ZF
);
5927 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
5928 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
5930 /* calculate the carry chain SEE NOTE AT TOP. */
5931 cc
= (s
& d
) | ((~res
) & (s
| d
));
5932 CONDITIONAL_SET_FLAG(XOR2(cc
>> 30), F_OF
);
5933 CONDITIONAL_SET_FLAG(cc
& 0x8, F_AF
);
5936 /****************************************************************************
5938 Implements the ADD instruction and side effects.
5939 ****************************************************************************/
5941 add_byte(struct X86EMU
*emu
, uint8_t d
, uint8_t s
)
5943 uint32_t res
; /* all operands in native machine order */
5947 CONDITIONAL_SET_FLAG(res
& 0x100, F_CF
);
5948 CONDITIONAL_SET_FLAG((res
& 0xff) == 0, F_ZF
);
5949 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
5950 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
5952 /* calculate the carry chain SEE NOTE AT TOP. */
5953 cc
= (s
& d
) | ((~res
) & (s
| d
));
5954 CONDITIONAL_SET_FLAG(XOR2(cc
>> 6), F_OF
);
5955 CONDITIONAL_SET_FLAG(cc
& 0x8, F_AF
);
5956 return (uint8_t) res
;
5958 /****************************************************************************
5960 Implements the ADD instruction and side effects.
5961 ****************************************************************************/
5963 add_word(struct X86EMU
*emu
, uint16_t d
, uint16_t s
)
5965 uint32_t res
; /* all operands in native machine order */
5969 CONDITIONAL_SET_FLAG(res
& 0x10000, F_CF
);
5970 CONDITIONAL_SET_FLAG((res
& 0xffff) == 0, F_ZF
);
5971 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
5972 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
5974 /* calculate the carry chain SEE NOTE AT TOP. */
5975 cc
= (s
& d
) | ((~res
) & (s
| d
));
5976 CONDITIONAL_SET_FLAG(XOR2(cc
>> 14), F_OF
);
5977 CONDITIONAL_SET_FLAG(cc
& 0x8, F_AF
);
5978 return (uint16_t) res
;
5980 /****************************************************************************
5982 Implements the ADD instruction and side effects.
5983 ****************************************************************************/
5985 add_long(struct X86EMU
*emu
, uint32_t d
, uint32_t s
)
5987 uint32_t lo
; /* all operands in native machine order */
5992 lo
= (d
& 0xFFFF) + (s
& 0xFFFF);
5994 hi
= (lo
>> 16) + (d
>> 16) + (s
>> 16);
5996 CONDITIONAL_SET_FLAG(hi
& 0x10000, F_CF
);
5997 CONDITIONAL_SET_FLAG((res
& 0xffffffff) == 0, F_ZF
);
5998 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
5999 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
6001 /* calculate the carry chain SEE NOTE AT TOP. */
6002 cc
= (s
& d
) | ((~res
) & (s
| d
));
6003 CONDITIONAL_SET_FLAG(XOR2(cc
>> 30), F_OF
);
6004 CONDITIONAL_SET_FLAG(cc
& 0x8, F_AF
);
6008 /****************************************************************************
6010 Implements the AND instruction and side effects.
6011 ****************************************************************************/
6013 and_byte(struct X86EMU
*emu
, uint8_t d
, uint8_t s
)
6015 uint8_t res
; /* all operands in native machine order */
6023 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
6024 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
6025 CONDITIONAL_SET_FLAG(PARITY(res
), F_PF
);
6028 /****************************************************************************
6030 Implements the AND instruction and side effects.
6031 ****************************************************************************/
6033 and_word(struct X86EMU
*emu
, uint16_t d
, uint16_t s
)
6035 uint16_t res
; /* all operands in native machine order */
6043 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
6044 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
6045 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
6048 /****************************************************************************
6050 Implements the AND instruction and side effects.
6051 ****************************************************************************/
6053 and_long(struct X86EMU
*emu
, uint32_t d
, uint32_t s
)
6055 uint32_t res
; /* all operands in native machine order */
6063 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
6064 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
6065 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
6068 /****************************************************************************
6070 Implements the CMP instruction and side effects.
6071 ****************************************************************************/
6073 cmp_byte(struct X86EMU
*emu
, uint8_t d
, uint8_t s
)
6075 uint32_t res
; /* all operands in native machine order */
6080 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
6081 CONDITIONAL_SET_FLAG((res
& 0xff) == 0, F_ZF
);
6082 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
6084 /* calculate the borrow chain. See note at top */
6085 bc
= (res
& (~d
| s
)) | (~d
& s
);
6086 CONDITIONAL_SET_FLAG(bc
& 0x80, F_CF
);
6087 CONDITIONAL_SET_FLAG(XOR2(bc
>> 6), F_OF
);
6088 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
6093 cmp_byte_no_return(struct X86EMU
*emu
, uint8_t d
, uint8_t s
)
6095 cmp_byte(emu
, d
, s
);
6097 /****************************************************************************
6099 Implements the CMP instruction and side effects.
6100 ****************************************************************************/
6102 cmp_word(struct X86EMU
*emu
, uint16_t d
, uint16_t s
)
6104 uint32_t res
; /* all operands in native machine order */
6108 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
6109 CONDITIONAL_SET_FLAG((res
& 0xffff) == 0, F_ZF
);
6110 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
6112 /* calculate the borrow chain. See note at top */
6113 bc
= (res
& (~d
| s
)) | (~d
& s
);
6114 CONDITIONAL_SET_FLAG(bc
& 0x8000, F_CF
);
6115 CONDITIONAL_SET_FLAG(XOR2(bc
>> 14), F_OF
);
6116 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
6121 cmp_word_no_return(struct X86EMU
*emu
, uint16_t d
, uint16_t s
)
6123 cmp_word(emu
, d
, s
);
6125 /****************************************************************************
6127 Implements the CMP instruction and side effects.
6128 ****************************************************************************/
6130 cmp_long(struct X86EMU
*emu
, uint32_t d
, uint32_t s
)
6132 uint32_t res
; /* all operands in native machine order */
6136 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
6137 CONDITIONAL_SET_FLAG((res
& 0xffffffff) == 0, F_ZF
);
6138 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
6140 /* calculate the borrow chain. See note at top */
6141 bc
= (res
& (~d
| s
)) | (~d
& s
);
6142 CONDITIONAL_SET_FLAG(bc
& 0x80000000, F_CF
);
6143 CONDITIONAL_SET_FLAG(XOR2(bc
>> 30), F_OF
);
6144 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
6149 cmp_long_no_return(struct X86EMU
*emu
, uint32_t d
, uint32_t s
)
6151 cmp_long(emu
, d
, s
);
6153 /****************************************************************************
6155 Implements the DAA instruction and side effects.
6156 ****************************************************************************/
6158 daa_byte(struct X86EMU
*emu
, uint8_t d
)
6161 if ((d
& 0xf) > 9 || ACCESS_FLAG(F_AF
)) {
6165 if (res
> 0x9F || ACCESS_FLAG(F_CF
)) {
6169 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
6170 CONDITIONAL_SET_FLAG((res
& 0xFF) == 0, F_ZF
);
6171 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
6172 return (uint8_t) res
;
6174 /****************************************************************************
6176 Implements the DAS instruction and side effects.
6177 ****************************************************************************/
6179 das_byte(struct X86EMU
*emu
, uint8_t d
)
6181 if ((d
& 0xf) > 9 || ACCESS_FLAG(F_AF
)) {
6185 if (d
> 0x9F || ACCESS_FLAG(F_CF
)) {
6189 CONDITIONAL_SET_FLAG(d
& 0x80, F_SF
);
6190 CONDITIONAL_SET_FLAG(d
== 0, F_ZF
);
6191 CONDITIONAL_SET_FLAG(PARITY(d
& 0xff), F_PF
);
6194 /****************************************************************************
6196 Implements the DEC instruction and side effects.
6197 ****************************************************************************/
6199 dec_byte(struct X86EMU
*emu
, uint8_t d
)
6201 uint32_t res
; /* all operands in native machine order */
6205 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
6206 CONDITIONAL_SET_FLAG((res
& 0xff) == 0, F_ZF
);
6207 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
6209 /* calculate the borrow chain. See note at top */
6210 /* based on sub_byte, uses s==1. */
6211 bc
= (res
& (~d
| 1)) | (~d
& 1);
6212 /* carry flag unchanged */
6213 CONDITIONAL_SET_FLAG(XOR2(bc
>> 6), F_OF
);
6214 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
6215 return (uint8_t) res
;
6217 /****************************************************************************
6219 Implements the DEC instruction and side effects.
6220 ****************************************************************************/
6222 dec_word(struct X86EMU
*emu
, uint16_t d
)
6224 uint32_t res
; /* all operands in native machine order */
6228 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
6229 CONDITIONAL_SET_FLAG((res
& 0xffff) == 0, F_ZF
);
6230 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
6232 /* calculate the borrow chain. See note at top */
6233 /* based on the sub_byte routine, with s==1 */
6234 bc
= (res
& (~d
| 1)) | (~d
& 1);
6235 /* carry flag unchanged */
6236 CONDITIONAL_SET_FLAG(XOR2(bc
>> 14), F_OF
);
6237 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
6238 return (uint16_t) res
;
6240 /****************************************************************************
6242 Implements the DEC instruction and side effects.
6243 ****************************************************************************/
6245 dec_long(struct X86EMU
*emu
, uint32_t d
)
6247 uint32_t res
; /* all operands in native machine order */
6252 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
6253 CONDITIONAL_SET_FLAG((res
& 0xffffffff) == 0, F_ZF
);
6254 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
6256 /* calculate the borrow chain. See note at top */
6257 bc
= (res
& (~d
| 1)) | (~d
& 1);
6258 /* carry flag unchanged */
6259 CONDITIONAL_SET_FLAG(XOR2(bc
>> 30), F_OF
);
6260 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
6263 /****************************************************************************
6265 Implements the INC instruction and side effects.
6266 ****************************************************************************/
6268 inc_byte(struct X86EMU
*emu
, uint8_t d
)
6270 uint32_t res
; /* all operands in native machine order */
6274 CONDITIONAL_SET_FLAG((res
& 0xff) == 0, F_ZF
);
6275 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
6276 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
6278 /* calculate the carry chain SEE NOTE AT TOP. */
6279 cc
= ((1 & d
) | (~res
)) & (1 | d
);
6280 CONDITIONAL_SET_FLAG(XOR2(cc
>> 6), F_OF
);
6281 CONDITIONAL_SET_FLAG(cc
& 0x8, F_AF
);
6282 return (uint8_t) res
;
6284 /****************************************************************************
6286 Implements the INC instruction and side effects.
6287 ****************************************************************************/
6289 inc_word(struct X86EMU
*emu
, uint16_t d
)
6291 uint32_t res
; /* all operands in native machine order */
6295 CONDITIONAL_SET_FLAG((res
& 0xffff) == 0, F_ZF
);
6296 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
6297 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
6299 /* calculate the carry chain SEE NOTE AT TOP. */
6300 cc
= (1 & d
) | ((~res
) & (1 | d
));
6301 CONDITIONAL_SET_FLAG(XOR2(cc
>> 14), F_OF
);
6302 CONDITIONAL_SET_FLAG(cc
& 0x8, F_AF
);
6303 return (uint16_t) res
;
6305 /****************************************************************************
6307 Implements the INC instruction and side effects.
6308 ****************************************************************************/
6310 inc_long(struct X86EMU
*emu
, uint32_t d
)
6312 uint32_t res
; /* all operands in native machine order */
6316 CONDITIONAL_SET_FLAG((res
& 0xffffffff) == 0, F_ZF
);
6317 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
6318 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
6320 /* calculate the carry chain SEE NOTE AT TOP. */
6321 cc
= (1 & d
) | ((~res
) & (1 | d
));
6322 CONDITIONAL_SET_FLAG(XOR2(cc
>> 30), F_OF
);
6323 CONDITIONAL_SET_FLAG(cc
& 0x8, F_AF
);
6326 /****************************************************************************
6328 Implements the OR instruction and side effects.
6329 ****************************************************************************/
6331 or_byte(struct X86EMU
*emu
, uint8_t d
, uint8_t s
)
6333 uint8_t res
; /* all operands in native machine order */
6339 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
6340 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
6341 CONDITIONAL_SET_FLAG(PARITY(res
), F_PF
);
6344 /****************************************************************************
6346 Implements the OR instruction and side effects.
6347 ****************************************************************************/
6349 or_word(struct X86EMU
*emu
, uint16_t d
, uint16_t s
)
6351 uint16_t res
; /* all operands in native machine order */
6354 /* set the carry flag to be bit 8 */
6358 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
6359 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
6360 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
6363 /****************************************************************************
6365 Implements the OR instruction and side effects.
6366 ****************************************************************************/
6368 or_long(struct X86EMU
*emu
, uint32_t d
, uint32_t s
)
6370 uint32_t res
; /* all operands in native machine order */
6374 /* set the carry flag to be bit 8 */
6378 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
6379 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
6380 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
6383 /****************************************************************************
6385 Implements the OR instruction and side effects.
6386 ****************************************************************************/
6388 neg_byte(struct X86EMU
*emu
, uint8_t s
)
6393 CONDITIONAL_SET_FLAG(s
!= 0, F_CF
);
6394 res
= (uint8_t) - s
;
6395 CONDITIONAL_SET_FLAG((res
& 0xff) == 0, F_ZF
);
6396 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
6397 CONDITIONAL_SET_FLAG(PARITY(res
), F_PF
);
6398 /* calculate the borrow chain --- modified such that d=0.
6399 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for
6400 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6401 * res&0xfff... == res. Similarly ~d&s == s. So the simplified
6404 CONDITIONAL_SET_FLAG(XOR2(bc
>> 6), F_OF
);
6405 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
6408 /****************************************************************************
6410 Implements the OR instruction and side effects.
6411 ****************************************************************************/
6413 neg_word(struct X86EMU
*emu
, uint16_t s
)
6418 CONDITIONAL_SET_FLAG(s
!= 0, F_CF
);
6419 res
= (uint16_t) - s
;
6420 CONDITIONAL_SET_FLAG((res
& 0xffff) == 0, F_ZF
);
6421 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
6422 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
6424 /* calculate the borrow chain --- modified such that d=0.
6425 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for
6426 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6427 * res&0xfff... == res. Similarly ~d&s == s. So the simplified
6430 CONDITIONAL_SET_FLAG(XOR2(bc
>> 14), F_OF
);
6431 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
6434 /****************************************************************************
6436 Implements the OR instruction and side effects.
6437 ****************************************************************************/
6439 neg_long(struct X86EMU
*emu
, uint32_t s
)
6444 CONDITIONAL_SET_FLAG(s
!= 0, F_CF
);
6445 res
= (uint32_t) - s
;
6446 CONDITIONAL_SET_FLAG((res
& 0xffffffff) == 0, F_ZF
);
6447 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
6448 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
6450 /* calculate the borrow chain --- modified such that d=0.
6451 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for
6452 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6453 * res&0xfff... == res. Similarly ~d&s == s. So the simplified
6456 CONDITIONAL_SET_FLAG(XOR2(bc
>> 30), F_OF
);
6457 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
6460 /****************************************************************************
6462 Implements the RCL instruction and side effects.
6463 ****************************************************************************/
6465 rcl_byte(struct X86EMU
*emu
, uint8_t d
, uint8_t s
)
6467 unsigned int res
, cnt
, mask
, cf
;
6469 /* s is the rotate distance. It varies from 0 - 8. */
6472 * CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
6474 * want to rotate through the carry by "s" bits. We could loop, but
6475 * that's inefficient. So the width is 9, and we split into three
6478 * The new carry flag (was B_n) the stuff in B_n-1 .. B_0 the stuff in
6481 * The new rotate is done mod 9, and given this, for a rotation of n bits
6482 * (mod 9) the new carry flag is then located n bits from the MSB.
6483 * The low part is then shifted up cnt bits, and the high part is or'd
6484 * in. Using CAPS for new values, and lowercase for the original
6485 * values, this can be expressed as:
6487 * IF n > 0 1) CF <- b_(8-n) 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0
6488 * 3) B_(n-1) <- cf 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */
6490 if ((cnt
= s
% 9) != 0) {
6491 /* extract the new CARRY FLAG. */
6493 cf
= (d
>> (8 - cnt
)) & 0x1;
6495 /* get the low stuff which rotated into the range B_7 .. B_cnt */
6496 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 */
6497 /* note that the right hand side done by the mask */
6498 res
= (d
<< cnt
) & 0xff;
6500 /* now the high stuff which rotated around into the positions
6502 /* B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */
6503 /* shift it downward, 7-(n-2) = 9-n positions. and mask off
6504 * the result before or'ing in. */
6505 mask
= (1 << (cnt
- 1)) - 1;
6506 res
|= (d
>> (9 - cnt
)) & mask
;
6508 /* if the carry flag was set, or it in. */
6509 if (ACCESS_FLAG(F_CF
)) { /* carry flag is set */
6511 res
|= 1 << (cnt
- 1);
6513 /* set the new carry flag, based on the variable "cf" */
6514 CONDITIONAL_SET_FLAG(cf
, F_CF
);
6515 /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and
6516 * the most significant bit. Blecck. */
6517 /* parenthesized this expression since it appears to be
6518 * causing OF to be misset */
6519 CONDITIONAL_SET_FLAG(cnt
== 1 && XOR2(cf
+ ((res
>> 6) & 0x2)),
6523 return (uint8_t) res
;
6525 /****************************************************************************
6527 Implements the RCL instruction and side effects.
6528 ****************************************************************************/
6530 rcl_word(struct X86EMU
*emu
, uint16_t d
, uint8_t s
)
6532 unsigned int res
, cnt
, mask
, cf
;
6535 if ((cnt
= s
% 17) != 0) {
6536 cf
= (d
>> (16 - cnt
)) & 0x1;
6537 res
= (d
<< cnt
) & 0xffff;
6538 mask
= (1 << (cnt
- 1)) - 1;
6539 res
|= (d
>> (17 - cnt
)) & mask
;
6540 if (ACCESS_FLAG(F_CF
)) {
6541 res
|= 1 << (cnt
- 1);
6543 CONDITIONAL_SET_FLAG(cf
, F_CF
);
6544 CONDITIONAL_SET_FLAG(cnt
== 1 && XOR2(cf
+ ((res
>> 14) & 0x2)),
6547 return (uint16_t) res
;
6549 /****************************************************************************
6551 Implements the RCL instruction and side effects.
6552 ****************************************************************************/
6554 rcl_long(struct X86EMU
*emu
, uint32_t d
, uint8_t s
)
6556 uint32_t res
, cnt
, mask
, cf
;
6559 if ((cnt
= s
% 33) != 0) {
6560 cf
= (d
>> (32 - cnt
)) & 0x1;
6561 res
= (d
<< cnt
) & 0xffffffff;
6562 mask
= (1 << (cnt
- 1)) - 1;
6563 res
|= (d
>> (33 - cnt
)) & mask
;
6564 if (ACCESS_FLAG(F_CF
)) { /* carry flag is set */
6565 res
|= 1 << (cnt
- 1);
6567 CONDITIONAL_SET_FLAG(cf
, F_CF
);
6568 CONDITIONAL_SET_FLAG(cnt
== 1 && XOR2(cf
+ ((res
>> 30) & 0x2)),
6573 /****************************************************************************
6575 Implements the RCR instruction and side effects.
6576 ****************************************************************************/
6578 rcr_byte(struct X86EMU
*emu
, uint8_t d
, uint8_t s
)
6581 uint32_t mask
, cf
, ocf
= 0;
6583 /* rotate right through carry */
6584 /* s is the rotate distance. It varies from 0 - 8. d is the byte
6589 * CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
6591 * The new rotate is done mod 9, and given this, for a rotation of n bits
6592 * (mod 9) the new carry flag is then located n bits from the LSB.
6593 * The low part is then shifted up cnt bits, and the high part is or'd
6594 * in. Using CAPS for new values, and lowercase for the original
6595 * values, this can be expressed as:
6597 * IF n > 0 1) CF <- b_(n-1) 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
6598 * 3) B_(8-n) <- cf 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */
6600 if ((cnt
= s
% 9) != 0) {
6601 /* extract the new CARRY FLAG. */
6605 /* note hackery here. Access_flag(..) evaluates to
6606 * either 0 if flag not set non-zero if flag is set.
6607 * doing access_flag(..) != 0 casts that into either
6608 * 0..1 in any representation of the flags register
6609 * (i.e. packed bit array or unpacked.) */
6610 ocf
= ACCESS_FLAG(F_CF
) != 0;
6612 cf
= (d
>> (cnt
- 1)) & 0x1;
6614 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */
6615 /* note that the right hand side done by the mask This is
6616 * effectively done by shifting the object to the right. The
6617 * result must be masked, in case the object came in and was
6618 * treated as a negative number. Needed??? */
6620 mask
= (1 << (8 - cnt
)) - 1;
6621 res
= (d
>> cnt
) & mask
;
6623 /* now the high stuff which rotated around into the positions
6625 /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */
6626 /* shift it downward, 7-(n-2) = 9-n positions. and mask off
6627 * the result before or'ing in. */
6628 res
|= (d
<< (9 - cnt
));
6630 /* if the carry flag was set, or it in. */
6631 if (ACCESS_FLAG(F_CF
)) { /* carry flag is set */
6633 res
|= 1 << (8 - cnt
);
6635 /* set the new carry flag, based on the variable "cf" */
6636 CONDITIONAL_SET_FLAG(cf
, F_CF
);
6637 /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and
6638 * the most significant bit. Blecck. */
6639 /* parenthesized... */
6641 CONDITIONAL_SET_FLAG(XOR2(ocf
+ ((d
>> 6) & 0x2)),
6645 return (uint8_t) res
;
6647 /****************************************************************************
6649 Implements the RCR instruction and side effects.
6650 ****************************************************************************/
6652 rcr_word(struct X86EMU
*emu
, uint16_t d
, uint8_t s
)
6655 uint32_t mask
, cf
, ocf
= 0;
6657 /* rotate right through carry */
6659 if ((cnt
= s
% 17) != 0) {
6662 ocf
= ACCESS_FLAG(F_CF
) != 0;
6664 cf
= (d
>> (cnt
- 1)) & 0x1;
6665 mask
= (1 << (16 - cnt
)) - 1;
6666 res
= (d
>> cnt
) & mask
;
6667 res
|= (d
<< (17 - cnt
));
6668 if (ACCESS_FLAG(F_CF
)) {
6669 res
|= 1 << (16 - cnt
);
6671 CONDITIONAL_SET_FLAG(cf
, F_CF
);
6673 CONDITIONAL_SET_FLAG(XOR2(ocf
+ ((d
>> 14) & 0x2)),
6677 return (uint16_t) res
;
6679 /****************************************************************************
6681 Implements the RCR instruction and side effects.
6682 ****************************************************************************/
6684 rcr_long(struct X86EMU
*emu
, uint32_t d
, uint8_t s
)
6687 uint32_t mask
, cf
, ocf
= 0;
6689 /* rotate right through carry */
6691 if ((cnt
= s
% 33) != 0) {
6694 ocf
= ACCESS_FLAG(F_CF
) != 0;
6696 cf
= (d
>> (cnt
- 1)) & 0x1;
6697 mask
= (1 << (32 - cnt
)) - 1;
6698 res
= (d
>> cnt
) & mask
;
6700 res
|= (d
<< (33 - cnt
));
6701 if (ACCESS_FLAG(F_CF
)) { /* carry flag is set */
6702 res
|= 1 << (32 - cnt
);
6704 CONDITIONAL_SET_FLAG(cf
, F_CF
);
6706 CONDITIONAL_SET_FLAG(XOR2(ocf
+ ((d
>> 30) & 0x2)),
6712 /****************************************************************************
6714 Implements the ROL instruction and side effects.
6715 ****************************************************************************/
6717 rol_byte(struct X86EMU
*emu
, uint8_t d
, uint8_t s
)
6719 unsigned int res
, cnt
, mask
;
6722 /* s is the rotate distance. It varies from 0 - 8. d is the byte
6729 * The new rotate is done mod 8. Much simpler than the "rcl" or "rcr"
6732 * IF n > 0 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) 2) B_(n-1) ..
6733 * B_(0) <- b_(7) .. b_(8-n) */
6735 if ((cnt
= s
% 8) != 0) {
6736 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */
6739 /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */
6740 mask
= (1 << cnt
) - 1;
6741 res
|= (d
>> (8 - cnt
)) & mask
;
6743 /* set the new carry flag, Note that it is the low order bit
6744 * of the result!!! */
6745 CONDITIONAL_SET_FLAG(res
& 0x1, F_CF
);
6746 /* OVERFLOW is set *IFF* s==1, then it is the xor of CF and
6747 * the most significant bit. Blecck. */
6748 CONDITIONAL_SET_FLAG(s
== 1 &&
6749 XOR2((res
& 0x1) + ((res
>> 6) & 0x2)),
6752 /* set the new carry flag, Note that it is the low order bit
6753 * of the result!!! */
6754 CONDITIONAL_SET_FLAG(res
& 0x1, F_CF
);
6756 return (uint8_t) res
;
6758 /****************************************************************************
6760 Implements the ROL instruction and side effects.
6761 ****************************************************************************/
6763 rol_word(struct X86EMU
*emu
, uint16_t d
, uint8_t s
)
6765 unsigned int res
, cnt
, mask
;
6768 if ((cnt
= s
% 16) != 0) {
6770 mask
= (1 << cnt
) - 1;
6771 res
|= (d
>> (16 - cnt
)) & mask
;
6772 CONDITIONAL_SET_FLAG(res
& 0x1, F_CF
);
6773 CONDITIONAL_SET_FLAG(s
== 1 &&
6774 XOR2((res
& 0x1) + ((res
>> 14) & 0x2)),
6777 /* set the new carry flag, Note that it is the low order bit
6778 * of the result!!! */
6779 CONDITIONAL_SET_FLAG(res
& 0x1, F_CF
);
6781 return (uint16_t) res
;
6783 /****************************************************************************
6785 Implements the ROL instruction and side effects.
6786 ****************************************************************************/
6788 rol_long(struct X86EMU
*emu
, uint32_t d
, uint8_t s
)
6790 uint32_t res
, cnt
, mask
;
6793 if ((cnt
= s
% 32) != 0) {
6795 mask
= (1 << cnt
) - 1;
6796 res
|= (d
>> (32 - cnt
)) & mask
;
6797 CONDITIONAL_SET_FLAG(res
& 0x1, F_CF
);
6798 CONDITIONAL_SET_FLAG(s
== 1 &&
6799 XOR2((res
& 0x1) + ((res
>> 30) & 0x2)),
6802 /* set the new carry flag, Note that it is the low order bit
6803 * of the result!!! */
6804 CONDITIONAL_SET_FLAG(res
& 0x1, F_CF
);
6808 /****************************************************************************
6810 Implements the ROR instruction and side effects.
6811 ****************************************************************************/
6813 ror_byte(struct X86EMU
*emu
, uint8_t d
, uint8_t s
)
6815 unsigned int res
, cnt
, mask
;
6818 /* s is the rotate distance. It varies from 0 - 8. d is the byte
6825 * The rotate is done mod 8.
6827 * IF n > 0 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) 2) B_(7) ..
6828 * B_(8-n) <- b_(n-1) .. b_(0) */
6830 if ((cnt
= s
% 8) != 0) { /* not a typo, do nada if cnt==0 */
6831 /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */
6832 res
= (d
<< (8 - cnt
));
6834 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */
6835 mask
= (1 << (8 - cnt
)) - 1;
6836 res
|= (d
>> (cnt
)) & mask
;
6838 /* set the new carry flag, Note that it is the low order bit
6839 * of the result!!! */
6840 CONDITIONAL_SET_FLAG(res
& 0x80, F_CF
);
6841 /* OVERFLOW is set *IFF* s==1, then it is the xor of the two
6842 * most significant bits. Blecck. */
6843 CONDITIONAL_SET_FLAG(s
== 1 && XOR2(res
>> 6), F_OF
);
6844 } else if (s
!= 0) {
6845 /* set the new carry flag, Note that it is the low order bit
6846 * of the result!!! */
6847 CONDITIONAL_SET_FLAG(res
& 0x80, F_CF
);
6849 return (uint8_t) res
;
6851 /****************************************************************************
6853 Implements the ROR instruction and side effects.
6854 ****************************************************************************/
6856 ror_word(struct X86EMU
*emu
, uint16_t d
, uint8_t s
)
6858 unsigned int res
, cnt
, mask
;
6861 if ((cnt
= s
% 16) != 0) {
6862 res
= (d
<< (16 - cnt
));
6863 mask
= (1 << (16 - cnt
)) - 1;
6864 res
|= (d
>> (cnt
)) & mask
;
6865 CONDITIONAL_SET_FLAG(res
& 0x8000, F_CF
);
6866 CONDITIONAL_SET_FLAG(s
== 1 && XOR2(res
>> 14), F_OF
);
6867 } else if (s
!= 0) {
6868 /* set the new carry flag, Note that it is the low order bit
6869 * of the result!!! */
6870 CONDITIONAL_SET_FLAG(res
& 0x8000, F_CF
);
6872 return (uint16_t) res
;
6874 /****************************************************************************
6876 Implements the ROR instruction and side effects.
6877 ****************************************************************************/
6879 ror_long(struct X86EMU
*emu
, uint32_t d
, uint8_t s
)
6881 uint32_t res
, cnt
, mask
;
6884 if ((cnt
= s
% 32) != 0) {
6885 res
= (d
<< (32 - cnt
));
6886 mask
= (1 << (32 - cnt
)) - 1;
6887 res
|= (d
>> (cnt
)) & mask
;
6888 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_CF
);
6889 CONDITIONAL_SET_FLAG(s
== 1 && XOR2(res
>> 30), F_OF
);
6890 } else if (s
!= 0) {
6891 /* set the new carry flag, Note that it is the low order bit
6892 * of the result!!! */
6893 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_CF
);
6897 /****************************************************************************
6899 Implements the SHL instruction and side effects.
6900 ****************************************************************************/
6902 shl_byte(struct X86EMU
*emu
, uint8_t d
, uint8_t s
)
6904 unsigned int cnt
, res
, cf
;
6909 /* last bit shifted out goes into carry flag */
6912 cf
= d
& (1 << (8 - cnt
));
6913 CONDITIONAL_SET_FLAG(cf
, F_CF
);
6914 CONDITIONAL_SET_FLAG((res
& 0xff) == 0, F_ZF
);
6915 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
6916 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
6922 /* Needs simplification. */
6923 CONDITIONAL_SET_FLAG(
6924 (((res
& 0x80) == 0x80) ^
6925 (ACCESS_FLAG(F_CF
) != 0)),
6926 /* was (emu->x86.R_FLG&F_CF)==F_CF)), */
6933 CONDITIONAL_SET_FLAG((d
<< (s
- 1)) & 0x80, F_CF
);
6939 return (uint8_t) res
;
6941 /****************************************************************************
6943 Implements the SHL instruction and side effects.
6944 ****************************************************************************/
6946 shl_word(struct X86EMU
*emu
, uint16_t d
, uint8_t s
)
6948 unsigned int cnt
, res
, cf
;
6954 cf
= d
& (1 << (16 - cnt
));
6955 CONDITIONAL_SET_FLAG(cf
, F_CF
);
6956 CONDITIONAL_SET_FLAG((res
& 0xffff) == 0, F_ZF
);
6957 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
6958 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
6964 CONDITIONAL_SET_FLAG(
6965 (((res
& 0x8000) == 0x8000) ^
6966 (ACCESS_FLAG(F_CF
) != 0)),
6973 CONDITIONAL_SET_FLAG((d
<< (s
- 1)) & 0x8000, F_CF
);
6979 return (uint16_t) res
;
6981 /****************************************************************************
6983 Implements the SHL instruction and side effects.
6984 ****************************************************************************/
6986 shl_long(struct X86EMU
*emu
, uint32_t d
, uint8_t s
)
6988 unsigned int cnt
, res
, cf
;
6994 cf
= d
& (1 << (32 - cnt
));
6995 CONDITIONAL_SET_FLAG(cf
, F_CF
);
6996 CONDITIONAL_SET_FLAG((res
& 0xffffffff) == 0, F_ZF
);
6997 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
6998 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
7003 CONDITIONAL_SET_FLAG((((res
& 0x80000000) == 0x80000000) ^
7004 (ACCESS_FLAG(F_CF
) != 0)), F_OF
);
7010 CONDITIONAL_SET_FLAG((d
<< (s
- 1)) & 0x80000000, F_CF
);
7018 /****************************************************************************
7020 Implements the SHR instruction and side effects.
7021 ****************************************************************************/
7023 shr_byte(struct X86EMU
*emu
, uint8_t d
, uint8_t s
)
7025 unsigned int cnt
, res
, cf
;
7030 cf
= d
& (1 << (cnt
- 1));
7032 CONDITIONAL_SET_FLAG(cf
, F_CF
);
7033 CONDITIONAL_SET_FLAG((res
& 0xff) == 0, F_ZF
);
7034 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
7035 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
7041 CONDITIONAL_SET_FLAG(XOR2(res
>> 6), F_OF
);
7047 CONDITIONAL_SET_FLAG((d
>> (s
- 1)) & 0x1, F_CF
);
7053 return (uint8_t) res
;
7055 /****************************************************************************
7057 Implements the SHR instruction and side effects.
7058 ****************************************************************************/
7060 shr_word(struct X86EMU
*emu
, uint16_t d
, uint8_t s
)
7062 unsigned int cnt
, res
, cf
;
7067 cf
= d
& (1 << (cnt
- 1));
7069 CONDITIONAL_SET_FLAG(cf
, F_CF
);
7070 CONDITIONAL_SET_FLAG((res
& 0xffff) == 0, F_ZF
);
7071 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
7072 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
7078 CONDITIONAL_SET_FLAG(XOR2(res
>> 14), F_OF
);
7090 return (uint16_t) res
;
7092 /****************************************************************************
7094 Implements the SHR instruction and side effects.
7095 ****************************************************************************/
7097 shr_long(struct X86EMU
*emu
, uint32_t d
, uint8_t s
)
7099 unsigned int cnt
, res
, cf
;
7104 cf
= d
& (1 << (cnt
- 1));
7106 CONDITIONAL_SET_FLAG(cf
, F_CF
);
7107 CONDITIONAL_SET_FLAG((res
& 0xffffffff) == 0, F_ZF
);
7108 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
7109 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
7114 CONDITIONAL_SET_FLAG(XOR2(res
>> 30), F_OF
);
7128 /****************************************************************************
7130 Implements the SAR instruction and side effects.
7131 ****************************************************************************/
7133 sar_byte(struct X86EMU
*emu
, uint8_t d
, uint8_t s
)
7135 unsigned int cnt
, res
, cf
, mask
, sf
;
7140 if (cnt
> 0 && cnt
< 8) {
7141 mask
= (1 << (8 - cnt
)) - 1;
7142 cf
= d
& (1 << (cnt
- 1));
7143 res
= (d
>> cnt
) & mask
;
7144 CONDITIONAL_SET_FLAG(cf
, F_CF
);
7148 CONDITIONAL_SET_FLAG((res
& 0xff) == 0, F_ZF
);
7149 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
7150 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
7151 } else if (cnt
>= 8) {
7166 return (uint8_t) res
;
7168 /****************************************************************************
7170 Implements the SAR instruction and side effects.
7171 ****************************************************************************/
7173 sar_word(struct X86EMU
*emu
, uint16_t d
, uint8_t s
)
7175 unsigned int cnt
, res
, cf
, mask
, sf
;
7180 if (cnt
> 0 && cnt
< 16) {
7181 mask
= (1 << (16 - cnt
)) - 1;
7182 cf
= d
& (1 << (cnt
- 1));
7183 res
= (d
>> cnt
) & mask
;
7184 CONDITIONAL_SET_FLAG(cf
, F_CF
);
7188 CONDITIONAL_SET_FLAG((res
& 0xffff) == 0, F_ZF
);
7189 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
7190 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
7191 } else if (cnt
>= 16) {
7206 return (uint16_t) res
;
7208 /****************************************************************************
7210 Implements the SAR instruction and side effects.
7211 ****************************************************************************/
7213 sar_long(struct X86EMU
*emu
, uint32_t d
, uint8_t s
)
7215 uint32_t cnt
, res
, cf
, mask
, sf
;
7217 sf
= d
& 0x80000000;
7220 if (cnt
> 0 && cnt
< 32) {
7221 mask
= (1 << (32 - cnt
)) - 1;
7222 cf
= d
& (1 << (cnt
- 1));
7223 res
= (d
>> cnt
) & mask
;
7224 CONDITIONAL_SET_FLAG(cf
, F_CF
);
7228 CONDITIONAL_SET_FLAG((res
& 0xffffffff) == 0, F_ZF
);
7229 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
7230 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
7231 } else if (cnt
>= 32) {
7248 /****************************************************************************
7250 Implements the SHLD instruction and side effects.
7251 ****************************************************************************/
7253 shld_word(struct X86EMU
*emu
, uint16_t d
, uint16_t fill
, uint8_t s
)
7255 unsigned int cnt
, res
, cf
;
7260 res
= (d
<< cnt
) | (fill
>> (16 - cnt
));
7261 cf
= d
& (1 << (16 - cnt
));
7262 CONDITIONAL_SET_FLAG(cf
, F_CF
);
7263 CONDITIONAL_SET_FLAG((res
& 0xffff) == 0, F_ZF
);
7264 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
7265 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
7270 CONDITIONAL_SET_FLAG((((res
& 0x8000) == 0x8000) ^
7271 (ACCESS_FLAG(F_CF
) != 0)), F_OF
);
7277 CONDITIONAL_SET_FLAG((d
<< (s
- 1)) & 0x8000, F_CF
);
7283 return (uint16_t) res
;
7285 /****************************************************************************
7287 Implements the SHLD instruction and side effects.
7288 ****************************************************************************/
7290 shld_long(struct X86EMU
*emu
, uint32_t d
, uint32_t fill
, uint8_t s
)
7292 unsigned int cnt
, res
, cf
;
7297 res
= (d
<< cnt
) | (fill
>> (32 - cnt
));
7298 cf
= d
& (1 << (32 - cnt
));
7299 CONDITIONAL_SET_FLAG(cf
, F_CF
);
7300 CONDITIONAL_SET_FLAG((res
& 0xffffffff) == 0, F_ZF
);
7301 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
7302 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
7307 CONDITIONAL_SET_FLAG((((res
& 0x80000000) == 0x80000000) ^
7308 (ACCESS_FLAG(F_CF
) != 0)), F_OF
);
7314 CONDITIONAL_SET_FLAG((d
<< (s
- 1)) & 0x80000000, F_CF
);
7322 /****************************************************************************
7324 Implements the SHRD instruction and side effects.
7325 ****************************************************************************/
7327 shrd_word(struct X86EMU
*emu
, uint16_t d
, uint16_t fill
, uint8_t s
)
7329 unsigned int cnt
, res
, cf
;
7334 cf
= d
& (1 << (cnt
- 1));
7335 res
= (d
>> cnt
) | (fill
<< (16 - cnt
));
7336 CONDITIONAL_SET_FLAG(cf
, F_CF
);
7337 CONDITIONAL_SET_FLAG((res
& 0xffff) == 0, F_ZF
);
7338 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
7339 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
7345 CONDITIONAL_SET_FLAG(XOR2(res
>> 14), F_OF
);
7357 return (uint16_t) res
;
7359 /****************************************************************************
7361 Implements the SHRD instruction and side effects.
7362 ****************************************************************************/
7364 shrd_long(struct X86EMU
*emu
, uint32_t d
, uint32_t fill
, uint8_t s
)
7366 unsigned int cnt
, res
, cf
;
7371 cf
= d
& (1 << (cnt
- 1));
7372 res
= (d
>> cnt
) | (fill
<< (32 - cnt
));
7373 CONDITIONAL_SET_FLAG(cf
, F_CF
);
7374 CONDITIONAL_SET_FLAG((res
& 0xffffffff) == 0, F_ZF
);
7375 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
7376 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
7381 CONDITIONAL_SET_FLAG(XOR2(res
>> 30), F_OF
);
7395 /****************************************************************************
7397 Implements the SBB instruction and side effects.
7398 ****************************************************************************/
7400 sbb_byte(struct X86EMU
*emu
, uint8_t d
, uint8_t s
)
7402 uint32_t res
; /* all operands in native machine order */
7405 if (ACCESS_FLAG(F_CF
))
7409 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
7410 CONDITIONAL_SET_FLAG((res
& 0xff) == 0, F_ZF
);
7411 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
7413 /* calculate the borrow chain. See note at top */
7414 bc
= (res
& (~d
| s
)) | (~d
& s
);
7415 CONDITIONAL_SET_FLAG(bc
& 0x80, F_CF
);
7416 CONDITIONAL_SET_FLAG(XOR2(bc
>> 6), F_OF
);
7417 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
7418 return (uint8_t) res
;
7420 /****************************************************************************
7422 Implements the SBB instruction and side effects.
7423 ****************************************************************************/
7425 sbb_word(struct X86EMU
*emu
, uint16_t d
, uint16_t s
)
7427 uint32_t res
; /* all operands in native machine order */
7430 if (ACCESS_FLAG(F_CF
))
7434 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
7435 CONDITIONAL_SET_FLAG((res
& 0xffff) == 0, F_ZF
);
7436 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
7438 /* calculate the borrow chain. See note at top */
7439 bc
= (res
& (~d
| s
)) | (~d
& s
);
7440 CONDITIONAL_SET_FLAG(bc
& 0x8000, F_CF
);
7441 CONDITIONAL_SET_FLAG(XOR2(bc
>> 14), F_OF
);
7442 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
7443 return (uint16_t) res
;
7445 /****************************************************************************
7447 Implements the SBB instruction and side effects.
7448 ****************************************************************************/
7450 sbb_long(struct X86EMU
*emu
, uint32_t d
, uint32_t s
)
7452 uint32_t res
; /* all operands in native machine order */
7455 if (ACCESS_FLAG(F_CF
))
7459 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
7460 CONDITIONAL_SET_FLAG((res
& 0xffffffff) == 0, F_ZF
);
7461 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
7463 /* calculate the borrow chain. See note at top */
7464 bc
= (res
& (~d
| s
)) | (~d
& s
);
7465 CONDITIONAL_SET_FLAG(bc
& 0x80000000, F_CF
);
7466 CONDITIONAL_SET_FLAG(XOR2(bc
>> 30), F_OF
);
7467 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
7470 /****************************************************************************
7472 Implements the SUB instruction and side effects.
7473 ****************************************************************************/
7475 sub_byte(struct X86EMU
*emu
, uint8_t d
, uint8_t s
)
7477 uint32_t res
; /* all operands in native machine order */
7481 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
7482 CONDITIONAL_SET_FLAG((res
& 0xff) == 0, F_ZF
);
7483 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
7485 /* calculate the borrow chain. See note at top */
7486 bc
= (res
& (~d
| s
)) | (~d
& s
);
7487 CONDITIONAL_SET_FLAG(bc
& 0x80, F_CF
);
7488 CONDITIONAL_SET_FLAG(XOR2(bc
>> 6), F_OF
);
7489 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
7490 return (uint8_t) res
;
7492 /****************************************************************************
7494 Implements the SUB instruction and side effects.
7495 ****************************************************************************/
7497 sub_word(struct X86EMU
*emu
, uint16_t d
, uint16_t s
)
7499 uint32_t res
; /* all operands in native machine order */
7503 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
7504 CONDITIONAL_SET_FLAG((res
& 0xffff) == 0, F_ZF
);
7505 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
7507 /* calculate the borrow chain. See note at top */
7508 bc
= (res
& (~d
| s
)) | (~d
& s
);
7509 CONDITIONAL_SET_FLAG(bc
& 0x8000, F_CF
);
7510 CONDITIONAL_SET_FLAG(XOR2(bc
>> 14), F_OF
);
7511 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
7512 return (uint16_t) res
;
7514 /****************************************************************************
7516 Implements the SUB instruction and side effects.
7517 ****************************************************************************/
7519 sub_long(struct X86EMU
*emu
, uint32_t d
, uint32_t s
)
7521 uint32_t res
; /* all operands in native machine order */
7525 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
7526 CONDITIONAL_SET_FLAG((res
& 0xffffffff) == 0, F_ZF
);
7527 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
7529 /* calculate the borrow chain. See note at top */
7530 bc
= (res
& (~d
| s
)) | (~d
& s
);
7531 CONDITIONAL_SET_FLAG(bc
& 0x80000000, F_CF
);
7532 CONDITIONAL_SET_FLAG(XOR2(bc
>> 30), F_OF
);
7533 CONDITIONAL_SET_FLAG(bc
& 0x8, F_AF
);
7536 /****************************************************************************
7538 Implements the TEST instruction and side effects.
7539 ****************************************************************************/
7541 test_byte(struct X86EMU
*emu
, uint8_t d
, uint8_t s
)
7543 uint32_t res
; /* all operands in native machine order */
7548 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
7549 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
7550 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
7551 /* AF == dont care */
7554 /****************************************************************************
7556 Implements the TEST instruction and side effects.
7557 ****************************************************************************/
7559 test_word(struct X86EMU
*emu
, uint16_t d
, uint16_t s
)
7561 uint32_t res
; /* all operands in native machine order */
7566 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
7567 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
7568 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
7569 /* AF == dont care */
7572 /****************************************************************************
7574 Implements the TEST instruction and side effects.
7575 ****************************************************************************/
7577 test_long(struct X86EMU
*emu
, uint32_t d
, uint32_t s
)
7579 uint32_t res
; /* all operands in native machine order */
7584 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
7585 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
7586 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
7587 /* AF == dont care */
7590 /****************************************************************************
7592 Implements the XOR instruction and side effects.
7593 ****************************************************************************/
7595 xor_byte(struct X86EMU
*emu
, uint8_t d
, uint8_t s
)
7597 uint8_t res
; /* all operands in native machine order */
7601 CONDITIONAL_SET_FLAG(res
& 0x80, F_SF
);
7602 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
7603 CONDITIONAL_SET_FLAG(PARITY(res
), F_PF
);
7608 /****************************************************************************
7610 Implements the XOR instruction and side effects.
7611 ****************************************************************************/
7613 xor_word(struct X86EMU
*emu
, uint16_t d
, uint16_t s
)
7615 uint16_t res
; /* all operands in native machine order */
7619 CONDITIONAL_SET_FLAG(res
& 0x8000, F_SF
);
7620 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
7621 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
7626 /****************************************************************************
7628 Implements the XOR instruction and side effects.
7629 ****************************************************************************/
7631 xor_long(struct X86EMU
*emu
, uint32_t d
, uint32_t s
)
7633 uint32_t res
; /* all operands in native machine order */
7637 CONDITIONAL_SET_FLAG(res
& 0x80000000, F_SF
);
7638 CONDITIONAL_SET_FLAG(res
== 0, F_ZF
);
7639 CONDITIONAL_SET_FLAG(PARITY(res
& 0xff), F_PF
);
7644 /****************************************************************************
7646 Implements the IMUL instruction and side effects.
7647 ****************************************************************************/
7649 imul_byte(struct X86EMU
*emu
, uint8_t s
)
7651 int16_t res
= (int16_t) ((int8_t) emu
->x86
.R_AL
* (int8_t) s
);
7653 emu
->x86
.R_AX
= res
;
7654 if (((emu
->x86
.R_AL
& 0x80) == 0 && emu
->x86
.R_AH
== 0x00) ||
7655 ((emu
->x86
.R_AL
& 0x80) != 0 && emu
->x86
.R_AH
== 0xFF)) {
7663 /****************************************************************************
7665 Implements the IMUL instruction and side effects.
7666 ****************************************************************************/
7668 imul_word(struct X86EMU
*emu
, uint16_t s
)
7670 int32_t res
= (int16_t) emu
->x86
.R_AX
* (int16_t) s
;
7672 emu
->x86
.R_AX
= (uint16_t) res
;
7673 emu
->x86
.R_DX
= (uint16_t) (res
>> 16);
7674 if (((emu
->x86
.R_AX
& 0x8000) == 0 && emu
->x86
.R_DX
== 0x00) ||
7675 ((emu
->x86
.R_AX
& 0x8000) != 0 && emu
->x86
.R_DX
== 0xFF)) {
7683 /****************************************************************************
7685 Implements the IMUL instruction and side effects.
7686 ****************************************************************************/
7688 imul_long(struct X86EMU
*emu
, uint32_t s
)
7692 res
= (int64_t)(int32_t)emu
->x86
.R_EAX
* (int32_t)s
;
7693 emu
->x86
.R_EAX
= (uint32_t)res
;
7694 emu
->x86
.R_EDX
= ((uint64_t)res
) >> 32;
7695 if (((emu
->x86
.R_EAX
& 0x80000000) == 0 && emu
->x86
.R_EDX
== 0x00) ||
7696 ((emu
->x86
.R_EAX
& 0x80000000) != 0 && emu
->x86
.R_EDX
== 0xFF)) {
7704 /****************************************************************************
7706 Implements the MUL instruction and side effects.
7707 ****************************************************************************/
7709 mul_byte(struct X86EMU
*emu
, uint8_t s
)
7711 uint16_t res
= (uint16_t) (emu
->x86
.R_AL
* s
);
7713 emu
->x86
.R_AX
= res
;
7714 if (emu
->x86
.R_AH
== 0) {
7722 /****************************************************************************
7724 Implements the MUL instruction and side effects.
7725 ****************************************************************************/
7727 mul_word(struct X86EMU
*emu
, uint16_t s
)
7729 uint32_t res
= emu
->x86
.R_AX
* s
;
7731 emu
->x86
.R_AX
= (uint16_t) res
;
7732 emu
->x86
.R_DX
= (uint16_t) (res
>> 16);
7733 if (emu
->x86
.R_DX
== 0) {
7741 /****************************************************************************
7743 Implements the MUL instruction and side effects.
7744 ****************************************************************************/
7746 mul_long(struct X86EMU
*emu
, uint32_t s
)
7748 uint64_t res
= (uint64_t) emu
->x86
.R_EAX
* s
;
7750 emu
->x86
.R_EAX
= (uint32_t) res
;
7751 emu
->x86
.R_EDX
= (uint32_t) (res
>> 32);
7753 if (emu
->x86
.R_EDX
== 0) {
7761 /****************************************************************************
7763 Implements the IDIV instruction and side effects.
7764 ****************************************************************************/
7766 idiv_byte(struct X86EMU
*emu
, uint8_t s
)
7768 int32_t dvd
, div
, mod
;
7770 dvd
= (int16_t) emu
->x86
.R_AX
;
7772 x86emu_intr_raise(emu
, 8);
7775 div
= dvd
/ (int8_t) s
;
7776 mod
= dvd
% (int8_t) s
;
7777 if (div
> 0x7f || div
< -0x7f) {
7778 x86emu_intr_raise(emu
, 8);
7781 emu
->x86
.R_AL
= (int8_t) div
;
7782 emu
->x86
.R_AH
= (int8_t) mod
;
7784 /****************************************************************************
7786 Implements the IDIV instruction and side effects.
7787 ****************************************************************************/
7789 idiv_word(struct X86EMU
*emu
, uint16_t s
)
7791 int32_t dvd
, div
, mod
;
7793 dvd
= (((int32_t) emu
->x86
.R_DX
) << 16) | emu
->x86
.R_AX
;
7795 x86emu_intr_raise(emu
, 8);
7798 div
= dvd
/ (int16_t) s
;
7799 mod
= dvd
% (int16_t) s
;
7800 if (div
> 0x7fff || div
< -0x7fff) {
7801 x86emu_intr_raise(emu
, 8);
7806 CONDITIONAL_SET_FLAG(div
== 0, F_ZF
);
7807 CONDITIONAL_SET_FLAG(PARITY(mod
& 0xff), F_PF
);
7809 emu
->x86
.R_AX
= (uint16_t) div
;
7810 emu
->x86
.R_DX
= (uint16_t) mod
;
7812 /****************************************************************************
7814 Implements the IDIV instruction and side effects.
7815 ****************************************************************************/
7817 idiv_long(struct X86EMU
*emu
, uint32_t s
)
7819 int64_t dvd
, div
, mod
;
7821 dvd
= (((int64_t) emu
->x86
.R_EDX
) << 32) | emu
->x86
.R_EAX
;
7823 x86emu_intr_raise(emu
, 8);
7826 div
= dvd
/ (int32_t) s
;
7827 mod
= dvd
% (int32_t) s
;
7828 if (div
> 0x7fffffff || div
< -0x7fffffff) {
7829 x86emu_intr_raise(emu
, 8);
7836 CONDITIONAL_SET_FLAG(PARITY(mod
& 0xff), F_PF
);
7838 emu
->x86
.R_EAX
= (uint32_t) div
;
7839 emu
->x86
.R_EDX
= (uint32_t) mod
;
7841 /****************************************************************************
7843 Implements the DIV instruction and side effects.
7844 ****************************************************************************/
7846 div_byte(struct X86EMU
*emu
, uint8_t s
)
7848 uint32_t dvd
, div
, mod
;
7850 dvd
= emu
->x86
.R_AX
;
7852 x86emu_intr_raise(emu
, 8);
7855 div
= dvd
/ (uint8_t) s
;
7856 mod
= dvd
% (uint8_t) s
;
7858 x86emu_intr_raise(emu
, 8);
7861 emu
->x86
.R_AL
= (uint8_t) div
;
7862 emu
->x86
.R_AH
= (uint8_t) mod
;
7864 /****************************************************************************
7866 Implements the DIV instruction and side effects.
7867 ****************************************************************************/
7869 div_word(struct X86EMU
*emu
, uint16_t s
)
7871 uint32_t dvd
, div
, mod
;
7873 dvd
= (((uint32_t) emu
->x86
.R_DX
) << 16) | emu
->x86
.R_AX
;
7875 x86emu_intr_raise(emu
, 8);
7878 div
= dvd
/ (uint16_t) s
;
7879 mod
= dvd
% (uint16_t) s
;
7881 x86emu_intr_raise(emu
, 8);
7886 CONDITIONAL_SET_FLAG(div
== 0, F_ZF
);
7887 CONDITIONAL_SET_FLAG(PARITY(mod
& 0xff), F_PF
);
7889 emu
->x86
.R_AX
= (uint16_t) div
;
7890 emu
->x86
.R_DX
= (uint16_t) mod
;
7892 /****************************************************************************
7894 Implements the DIV instruction and side effects.
7895 ****************************************************************************/
7897 div_long(struct X86EMU
*emu
, uint32_t s
)
7899 uint64_t dvd
, div
, mod
;
7901 dvd
= (((uint64_t) emu
->x86
.R_EDX
) << 32) | emu
->x86
.R_EAX
;
7903 x86emu_intr_raise(emu
, 8);
7906 div
= dvd
/ (uint32_t) s
;
7907 mod
= dvd
% (uint32_t) s
;
7908 if (div
> 0xffffffff) {
7909 x86emu_intr_raise(emu
, 8);
7916 CONDITIONAL_SET_FLAG(PARITY(mod
& 0xff), F_PF
);
7918 emu
->x86
.R_EAX
= (uint32_t) div
;
7919 emu
->x86
.R_EDX
= (uint32_t) mod
;
7921 /****************************************************************************
7923 Implements the IN string instruction and side effects.
7924 ****************************************************************************/
7926 ins(struct X86EMU
*emu
, int size
)
7930 if (ACCESS_FLAG(F_DF
)) {
7933 if (emu
->x86
.mode
& (SYSMODE_PREFIX_REPE
| SYSMODE_PREFIX_REPNE
)) {
7934 /* dont care whether REPE or REPNE */
7935 /* in until CX is ZERO. */
7936 uint32_t count
= ((emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) ?
7937 emu
->x86
.R_ECX
: emu
->x86
.R_CX
);
7941 store_byte(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
,
7942 (*emu
->emu_inb
) (emu
, emu
->x86
.R_DX
));
7943 emu
->x86
.R_DI
+= inc
;
7949 store_word(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
,
7950 (*emu
->emu_inw
) (emu
, emu
->x86
.R_DX
));
7951 emu
->x86
.R_DI
+= inc
;
7956 store_long(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
,
7957 (*emu
->emu_inl
) (emu
, emu
->x86
.R_DX
));
7958 emu
->x86
.R_DI
+= inc
;
7963 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
7966 emu
->x86
.mode
&= ~(SYSMODE_PREFIX_REPE
| SYSMODE_PREFIX_REPNE
);
7970 store_byte(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
,
7971 (*emu
->emu_inb
) (emu
, emu
->x86
.R_DX
));
7974 store_word(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
,
7975 (*emu
->emu_inw
) (emu
, emu
->x86
.R_DX
));
7978 store_long(emu
, emu
->x86
.R_ES
, emu
->x86
.R_DI
,
7979 (*emu
->emu_inl
) (emu
, emu
->x86
.R_DX
));
7982 emu
->x86
.R_DI
+= inc
;
7985 /****************************************************************************
7987 Implements the OUT string instruction and side effects.
7988 ****************************************************************************/
7990 outs(struct X86EMU
*emu
, int size
)
7994 if (ACCESS_FLAG(F_DF
)) {
7997 if (emu
->x86
.mode
& (SYSMODE_PREFIX_REPE
| SYSMODE_PREFIX_REPNE
)) {
7998 /* dont care whether REPE or REPNE */
7999 /* out until CX is ZERO. */
8000 uint32_t count
= ((emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) ?
8001 emu
->x86
.R_ECX
: emu
->x86
.R_CX
);
8005 (*emu
->emu_outb
) (emu
, emu
->x86
.R_DX
,
8006 fetch_byte(emu
, emu
->x86
.R_ES
, emu
->x86
.R_SI
));
8007 emu
->x86
.R_SI
+= inc
;
8013 (*emu
->emu_outw
) (emu
, emu
->x86
.R_DX
,
8014 fetch_word(emu
, emu
->x86
.R_ES
, emu
->x86
.R_SI
));
8015 emu
->x86
.R_SI
+= inc
;
8020 (*emu
->emu_outl
) (emu
, emu
->x86
.R_DX
,
8021 fetch_long(emu
, emu
->x86
.R_ES
, emu
->x86
.R_SI
));
8022 emu
->x86
.R_SI
+= inc
;
8027 if (emu
->x86
.mode
& SYSMODE_PREFIX_DATA
) {
8030 emu
->x86
.mode
&= ~(SYSMODE_PREFIX_REPE
| SYSMODE_PREFIX_REPNE
);
8034 (*emu
->emu_outb
) (emu
, emu
->x86
.R_DX
,
8035 fetch_byte(emu
, emu
->x86
.R_ES
, emu
->x86
.R_SI
));
8038 (*emu
->emu_outw
) (emu
, emu
->x86
.R_DX
,
8039 fetch_word(emu
, emu
->x86
.R_ES
, emu
->x86
.R_SI
));
8042 (*emu
->emu_outl
) (emu
, emu
->x86
.R_DX
,
8043 fetch_long(emu
, emu
->x86
.R_ES
, emu
->x86
.R_SI
));
8046 emu
->x86
.R_SI
+= inc
;
8049 /****************************************************************************
8051 Pushes a word onto the stack.
8053 NOTE: Do not inline this, as (*emu->emu_wrX) is already inline!
8054 ****************************************************************************/
8056 push_word(struct X86EMU
*emu
, uint16_t w
)
8059 store_word(emu
, emu
->x86
.R_SS
, emu
->x86
.R_SP
, w
);
8061 /****************************************************************************
8063 Pushes a long onto the stack.
8065 NOTE: Do not inline this, as (*emu->emu_wrX) is already inline!
8066 ****************************************************************************/
8068 push_long(struct X86EMU
*emu
, uint32_t w
)
8071 store_long(emu
, emu
->x86
.R_SS
, emu
->x86
.R_SP
, w
);
8073 /****************************************************************************
8075 Pops a word from the stack.
8077 NOTE: Do not inline this, as (*emu->emu_rdX) is already inline!
8078 ****************************************************************************/
8080 pop_word(struct X86EMU
*emu
)
8084 res
= fetch_word(emu
, emu
->x86
.R_SS
, emu
->x86
.R_SP
);
8088 /****************************************************************************
8090 Pops a long from the stack.
8092 NOTE: Do not inline this, as (*emu->emu_rdX) is already inline!
8093 ****************************************************************************/
8095 pop_long(struct X86EMU
*emu
)
8099 res
= fetch_long(emu
, emu
->x86
.R_SS
, emu
->x86
.R_SP
);