1 /* $OpenBSD: x86emu.c,v 1.5 2010/02/17 15:09:47 pirofti Exp $ */
2 /* $NetBSD: x86emu.c,v 1.7 2009/02/03 19:26:29 joerg Exp $ */
6 * Realmode X86 Emulator Library
8 * Copyright (C) 1996-1999 SciTech Software, Inc.
9 * Copyright (C) David Mosberger-Tang
10 * Copyright (C) 1999 Egbert Eich
11 * Copyright (C) 2007 Joerg Sonnenberger
13 * ========================================================================
15 * Permission to use, copy, modify, distribute, and sell this software and
16 * its documentation for any purpose is hereby granted without fee,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of the authors not be used
20 * in advertising or publicity pertaining to distribution of the software
21 * without specific, written prior permission. The authors makes no
22 * representations about the suitability of this software for any purpose.
23 * It is provided "as is" without express or implied warranty.
25 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
26 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
27 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
28 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
29 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
30 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
31 * PERFORMANCE OF THIS SOFTWARE.
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
38 #include <contrib/x86emu/x86emu.h>
39 #include <contrib/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 *, u_int 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 *);
177 * Handles any pending asychronous interrupts.
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);
209 * intrnum - Interrupt number to raise
212 * Raise the specified interrupt to be handled before the execution of the
216 x86emu_intr_raise(struct x86emu *emu, uint8_t intrnum)
218 emu->x86.intno = intrnum;
219 emu->x86.intr |= INTR_SYNCH;
224 * Main execution loop for the emulator. We return from here when the system
225 * halts, which is normally caused by a stack fault when we return from the
226 * original real mode call.
229 x86emu_exec(struct x86emu *emu)
233 if (setjmp(emu->exec_state))
238 if (((emu->x86.intr & INTR_SYNCH) &&
239 (emu->x86.intno == 0 || emu->x86.intno == 2)) ||
240 !ACCESS_FLAG(F_IF)) {
241 x86emu_intr_handle(emu);
244 if (emu->x86.R_CS == 0 && emu->x86.R_IP == 0)
246 x86emu_exec_one_byte(emu);
252 x86emu_exec_call(struct x86emu *emu, uint16_t seg, uint16_t off)
263 x86emu_exec_intr(struct x86emu *emu, uint8_t intr)
265 push_word(emu, emu->x86.R_FLG);
270 emu->x86.R_CS = (*emu->emu_rdw)(emu, intr * 4 + 2);
271 emu->x86.R_IP = (*emu->emu_rdw)(emu, intr * 4);
279 * Halts the system by setting the halted system flag.
282 x86emu_halt_sys(struct x86emu *emu)
284 longjmp(emu->exec_state, 1);
289 * mod - Mod value from decoded byte
290 * regh - Reg h value from decoded byte
291 * regl - Reg l value from decoded byte
294 * Raise the specified interrupt to be handled before the execution of the
297 * NOTE: Do not inline this function, as (*emu->emu_rdb) is already inline!
300 fetch_decode_modrm(struct x86emu *emu)
304 fetched = fetch_byte_imm(emu);
305 emu->cur_mod = (fetched >> 6) & 0x03;
306 emu->cur_rh = (fetched >> 3) & 0x07;
307 emu->cur_rl = (fetched >> 0) & 0x07;
312 * Immediate byte value read from instruction queue
315 * This function returns the immediate byte from the instruction queue, and
316 * moves the instruction pointer to the next value.
318 * NOTE: Do not inline this function, as (*emu->emu_rdb) is already inline!
321 fetch_byte_imm(struct x86emu *emu)
325 fetched = fetch_byte(emu, emu->x86.R_CS, emu->x86.R_IP);
332 * Immediate word value read from instruction queue
335 * This function returns the immediate byte from the instruction queue, and
336 * moves the instruction pointer to the next value.
338 * NOTE: Do not inline this function, as (*emu->emu_rdw) is already inline!
341 fetch_word_imm(struct x86emu *emu)
345 fetched = fetch_word(emu, emu->x86.R_CS, emu->x86.R_IP);
352 * Immediate lone value read from instruction queue
355 * This function returns the immediate byte from the instruction queue, and
356 * moves the instruction pointer to the next value.
358 * NOTE: Do not inline this function, as (*emu->emu_rdw) is already inline!
361 fetch_long_imm(struct x86emu *emu)
365 fetched = fetch_long(emu, emu->x86.R_CS, emu->x86.R_IP);
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)
388 * cs segment override
389 * ds segment override
390 * es segment override
391 * fs segment override
392 * gs segment override
393 * ss segment override
395 * ds/ss select (in absense of override)
397 * Each of the above 7 items are handled with a bit in the mode field.
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);
430 * offset - Offset to load data from
433 * Byte value read from the absolute memory location.
435 * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
438 fetch_data_byte(struct x86emu *emu, uint32_t offset)
440 return fetch_byte(emu, get_data_segment(emu), offset);
445 * offset - Offset to load data from
448 * Word value read from the absolute memory location.
450 * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
453 fetch_data_word(struct x86emu *emu, uint32_t offset)
455 return fetch_word(emu, get_data_segment(emu), offset);
460 * offset - Offset to load data from
463 * Long value read from the absolute memory location.
465 * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
468 fetch_data_long(struct x86emu *emu, uint32_t offset)
470 return fetch_long(emu, get_data_segment(emu), offset);
475 * segment - Segment to load data from
476 * offset - Offset to load data from
479 * Byte value read from the absolute memory location.
481 * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
484 fetch_byte(struct x86emu *emu, uint32_t segment, uint32_t offset)
486 return (*emu->emu_rdb) (emu, ((uint32_t) segment << 4) + offset);
491 * segment - Segment to load data from
492 * offset - Offset to load data from
495 * Word value read from the absolute memory location.
497 * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
500 fetch_word(struct x86emu *emu, uint32_t segment, uint32_t offset)
502 return (*emu->emu_rdw) (emu, ((uint32_t) segment << 4) + offset);
507 * segment - Segment to load data from
508 * offset - Offset to load data from
511 * Long value read from the absolute memory location.
513 * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
516 fetch_long(struct x86emu *emu, uint32_t segment, uint32_t offset)
518 return (*emu->emu_rdl) (emu, ((uint32_t) segment << 4) + offset);
523 * offset - Offset to store data at
524 * val - Value to store
527 * Writes a word value to an segmented memory location. The segment used is
528 * the current 'default' segment, which may have been overridden.
530 * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
533 store_data_byte(struct x86emu *emu, uint32_t offset, uint8_t val)
535 store_byte(emu, get_data_segment(emu), offset, val);
540 * offset - Offset to store data at
541 * val - Value to store
544 * Writes a word value to an segmented memory location. The segment used is
545 * the current 'default' segment, which may have been overridden.
547 * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
550 store_data_word(struct x86emu *emu, uint32_t offset, uint16_t val)
552 store_word(emu, get_data_segment(emu), offset, val);
557 * offset - Offset to store data at
558 * val - Value to store
561 * Writes a long value to an segmented memory location. The segment used is
562 * the current 'default' segment, which may have been overridden.
564 * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
567 store_data_long(struct x86emu *emu, uint32_t offset, uint32_t val)
569 store_long(emu, get_data_segment(emu), offset, val);
574 * segment - Segment to store data at
575 * offset - Offset to store data at
576 * val - Value to store
579 * Writes a byte value to an absolute memory location.
581 * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
584 store_byte(struct x86emu *emu, uint32_t segment, uint32_t offset, uint8_t val)
586 (*emu->emu_wrb) (emu, ((uint32_t) segment << 4) + offset, val);
591 * segment - Segment to store data at
592 * offset - Offset to store data at
593 * val - Value to store
596 * Writes a word value to an absolute memory location.
598 * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
601 store_word(struct x86emu *emu, uint32_t segment, uint32_t offset, uint16_t val)
603 (*emu->emu_wrw) (emu, ((uint32_t) segment << 4) + offset, val);
608 * segment - Segment to store data at
609 * offset - Offset to store data at
610 * val - Value to store
613 * Writes a long value to an absolute memory location.
615 * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
618 store_long(struct x86emu *emu, uint32_t segment, uint32_t offset, uint32_t val)
620 (*emu->emu_wrl) (emu, ((uint32_t) segment << 4) + offset, val);
625 * reg - Register to decode
628 * Pointer to the appropriate register
631 * Return a pointer to the register given by the R/RM field of the
632 * modrm byte, for byte operands. Also enables the decoding of instructions.
635 decode_rm_byte_register(struct x86emu *emu, int reg)
639 return &emu->x86.R_AL;
641 return &emu->x86.R_CL;
643 return &emu->x86.R_DL;
645 return &emu->x86.R_BL;
647 return &emu->x86.R_AH;
649 return &emu->x86.R_CH;
651 return &emu->x86.R_DH;
653 return &emu->x86.R_BH;
655 x86emu_halt_sys(emu);
660 decode_rl_byte_register(struct x86emu *emu)
662 return decode_rm_byte_register(emu, emu->cur_rl);
666 decode_rh_byte_register(struct x86emu *emu)
668 return decode_rm_byte_register(emu, emu->cur_rh);
673 * reg - Register to decode
676 * Pointer to the appropriate register
679 * Return a pointer to the register given by the R/RM field of the
680 * modrm byte, for word operands. Also enables the decoding of instructions.
683 decode_rm_word_register(struct x86emu *emu, int reg)
687 return &emu->x86.R_AX;
689 return &emu->x86.R_CX;
691 return &emu->x86.R_DX;
693 return &emu->x86.R_BX;
695 return &emu->x86.R_SP;
697 return &emu->x86.R_BP;
699 return &emu->x86.R_SI;
701 return &emu->x86.R_DI;
703 x86emu_halt_sys(emu);
708 decode_rl_word_register(struct x86emu *emu)
710 return decode_rm_word_register(emu, emu->cur_rl);
714 decode_rh_word_register(struct x86emu *emu)
716 return decode_rm_word_register(emu, emu->cur_rh);
721 * reg - Register to decode
724 * Pointer to the appropriate register
727 * Return a pointer to the register given by the R/RM field of the
728 * modrm byte, for dword operands. Also enables the decoding of instructions.
731 decode_rm_long_register(struct x86emu *emu, int reg)
735 return &emu->x86.R_EAX;
737 return &emu->x86.R_ECX;
739 return &emu->x86.R_EDX;
741 return &emu->x86.R_EBX;
743 return &emu->x86.R_ESP;
745 return &emu->x86.R_EBP;
747 return &emu->x86.R_ESI;
749 return &emu->x86.R_EDI;
751 x86emu_halt_sys(emu);
756 decode_rl_long_register(struct x86emu *emu)
758 return decode_rm_long_register(emu, emu->cur_rl);
762 decode_rh_long_register(struct x86emu *emu)
764 return decode_rm_long_register(emu, emu->cur_rh);
770 * reg - Register to decode
773 * Pointer to the appropriate register
776 * Return a pointer to the register given by the R/RM field of the
777 * modrm byte, for word operands, modified from above for the weirdo
778 * special case of segreg operands. Also enables the decoding of instructions.
781 decode_rh_seg_register(struct x86emu *emu)
783 switch (emu->cur_rh) {
785 return &emu->x86.R_ES;
787 return &emu->x86.R_CS;
789 return &emu->x86.R_SS;
791 return &emu->x86.R_DS;
793 return &emu->x86.R_FS;
795 return &emu->x86.R_GS;
797 x86emu_halt_sys(emu);
802 * Return offset from the SIB Byte.
805 decode_sib_address(struct x86emu *emu, int sib, int mod)
807 uint32_t base = 0, i = 0, scale = 1;
809 switch (sib & 0x07) {
811 base = emu->x86.R_EAX;
814 base = emu->x86.R_ECX;
818 base = emu->x86.R_EDX;
821 base = emu->x86.R_EBX;
824 base = emu->x86.R_ESP;
825 emu->x86.mode |= SYSMODE_SEG_DS_SS;
829 base = fetch_long_imm(emu);
831 base = emu->x86.R_EBP;
832 emu->x86.mode |= SYSMODE_SEG_DS_SS;
836 base = emu->x86.R_ESI;
839 base = emu->x86.R_EDI;
842 switch ((sib >> 3) & 0x07) {
868 scale = 1 << ((sib >> 6) & 0x03);
869 return base + (i * scale);
874 * rm - RM value to decode
877 * Offset in memory for the address decoding
880 * Return the offset given by mod=00, mod=01 or mod=10 addressing.
881 * Also enables the decoding of instructions.
884 decode_rl_address(struct x86emu *emu)
886 if (emu->x86.mode & SYSMODE_PREFIX_ADDR) {
887 uint32_t offset, sib;
888 /* 32-bit addressing */
889 switch (emu->cur_rl) {
891 offset = emu->x86.R_EAX;
894 offset = emu->x86.R_ECX;
897 offset = emu->x86.R_EDX;
900 offset = emu->x86.R_EBX;
903 sib = fetch_byte_imm(emu);
904 offset = decode_sib_address(emu, sib, 0);
907 if (emu->cur_mod == 0) {
908 offset = fetch_long_imm(emu);
910 emu->x86.mode |= SYSMODE_SEG_DS_SS;
911 offset = emu->x86.R_EBP;
915 offset = emu->x86.R_ESI;
918 offset = emu->x86.R_EDI;
921 x86emu_halt_sys(emu);
923 if (emu->cur_mod == 1)
924 offset += (int8_t)fetch_byte_imm(emu);
925 else if (emu->cur_mod == 2)
926 offset += fetch_long_imm(emu);
931 /* 16-bit addressing */
932 switch (emu->cur_rl) {
934 offset = emu->x86.R_BX + emu->x86.R_SI;
937 offset = emu->x86.R_BX + emu->x86.R_DI;
940 emu->x86.mode |= SYSMODE_SEG_DS_SS;
941 offset = emu->x86.R_BP + emu->x86.R_SI;
944 emu->x86.mode |= SYSMODE_SEG_DS_SS;
945 offset = emu->x86.R_BP + emu->x86.R_DI;
948 offset = emu->x86.R_SI;
951 offset = emu->x86.R_DI;
954 if (emu->cur_mod == 0) {
955 offset = fetch_word_imm(emu);
957 emu->x86.mode |= SYSMODE_SEG_DS_SS;
958 offset = emu->x86.R_BP;
962 offset = emu->x86.R_BX;
965 x86emu_halt_sys(emu);
967 if (emu->cur_mod == 1)
968 offset += (int8_t)fetch_byte_imm(emu);
969 else if (emu->cur_mod == 2)
970 offset += fetch_word_imm(emu);
976 decode_and_fetch_byte(struct x86emu *emu)
978 if (emu->cur_mod != 3) {
979 emu->cur_offset = decode_rl_address(emu);
980 return fetch_data_byte(emu, emu->cur_offset);
982 return *decode_rl_byte_register(emu);
987 decode_and_fetch_word_disp(struct x86emu *emu, int16_t disp)
989 if (emu->cur_mod != 3) {
990 /* TODO: A20 gate emulation */
991 emu->cur_offset = decode_rl_address(emu) + disp;
992 if ((emu->x86.mode & SYSMODE_PREFIX_ADDR) == 0)
993 emu->cur_offset &= 0xffff;
994 return fetch_data_word(emu, emu->cur_offset);
996 return *decode_rl_word_register(emu);
1001 decode_and_fetch_long_disp(struct x86emu *emu, int16_t disp)
1003 if (emu->cur_mod != 3) {
1004 /* TODO: A20 gate emulation */
1005 emu->cur_offset = decode_rl_address(emu) + disp;
1006 if ((emu->x86.mode & SYSMODE_PREFIX_ADDR) == 0)
1007 emu->cur_offset &= 0xffff;
1008 return fetch_data_long(emu, emu->cur_offset);
1010 return *decode_rl_long_register(emu);
1015 decode_and_fetch_word(struct x86emu *emu)
1017 return decode_and_fetch_word_disp(emu, 0);
1021 decode_and_fetch_long(struct x86emu *emu)
1023 return decode_and_fetch_long_disp(emu, 0);
1027 decode_and_fetch_byte_imm8(struct x86emu *emu, uint8_t *imm)
1029 if (emu->cur_mod != 3) {
1030 emu->cur_offset = decode_rl_address(emu);
1031 *imm = fetch_byte_imm(emu);
1032 return fetch_data_byte(emu, emu->cur_offset);
1034 *imm = fetch_byte_imm(emu);
1035 return *decode_rl_byte_register(emu);
1040 decode_and_fetch_word_imm8(struct x86emu *emu, uint8_t *imm)
1042 if (emu->cur_mod != 3) {
1043 emu->cur_offset = decode_rl_address(emu);
1044 *imm = fetch_byte_imm(emu);
1045 return fetch_data_word(emu, emu->cur_offset);
1047 *imm = fetch_byte_imm(emu);
1048 return *decode_rl_word_register(emu);
1053 decode_and_fetch_long_imm8(struct x86emu *emu, uint8_t *imm)
1055 if (emu->cur_mod != 3) {
1056 emu->cur_offset = decode_rl_address(emu);
1057 *imm = fetch_byte_imm(emu);
1058 return fetch_data_long(emu, emu->cur_offset);
1060 *imm = fetch_byte_imm(emu);
1061 return *decode_rl_long_register(emu);
1066 write_back_byte(struct x86emu *emu, uint8_t val)
1068 if (emu->cur_mod != 3)
1069 store_data_byte(emu, emu->cur_offset, val);
1071 *decode_rl_byte_register(emu) = val;
1075 write_back_word(struct x86emu *emu, uint16_t val)
1077 if (emu->cur_mod != 3)
1078 store_data_word(emu, emu->cur_offset, val);
1080 *decode_rl_word_register(emu) = val;
1084 write_back_long(struct x86emu *emu, uint32_t val)
1086 if (emu->cur_mod != 3)
1087 store_data_long(emu, emu->cur_offset, val);
1089 *decode_rl_long_register(emu) = val;
1093 common_inc_word_long(struct x86emu *emu, union x86emu_register *reg)
1095 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1096 reg->I32_reg.e_reg = inc_long(emu, reg->I32_reg.e_reg);
1098 reg->I16_reg.x_reg = inc_word(emu, reg->I16_reg.x_reg);
1102 common_dec_word_long(struct x86emu *emu, union x86emu_register *reg)
1104 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1105 reg->I32_reg.e_reg = dec_long(emu, reg->I32_reg.e_reg);
1107 reg->I16_reg.x_reg = dec_word(emu, reg->I16_reg.x_reg);
1111 common_binop_byte_rm_r(struct x86emu *emu,
1112 uint8_t (*binop)(struct x86emu *, uint8_t, uint8_t))
1114 uint32_t destoffset;
1115 uint8_t *destreg, 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);
1123 destval = (*binop)(emu, destval, srcval);
1124 store_data_byte(emu, destoffset, destval);
1126 destreg = decode_rl_byte_register(emu);
1127 *destreg = (*binop)(emu, *destreg, srcval);
1132 common_binop_ns_byte_rm_r(struct x86emu *emu,
1133 void (*binop)(struct x86emu *, uint8_t, uint8_t))
1135 uint32_t destoffset;
1136 uint8_t destval, srcval;
1138 fetch_decode_modrm(emu);
1139 srcval = *decode_rh_byte_register(emu);
1140 if (emu->cur_mod != 3) {
1141 destoffset = decode_rl_address(emu);
1142 destval = fetch_data_byte(emu, destoffset);
1144 destval = *decode_rl_byte_register(emu);
1146 (*binop)(emu, destval, srcval);
1150 common_binop_word_rm_r(struct x86emu *emu,
1151 uint16_t (*binop)(struct x86emu *, uint16_t, uint16_t))
1153 uint32_t destoffset;
1154 uint16_t destval, *destreg, srcval;
1156 fetch_decode_modrm(emu);
1157 srcval = *decode_rh_word_register(emu);
1158 if (emu->cur_mod != 3) {
1159 destoffset = decode_rl_address(emu);
1160 destval = fetch_data_word(emu, destoffset);
1161 destval = (*binop)(emu, destval, srcval);
1162 store_data_word(emu, destoffset, destval);
1164 destreg = decode_rl_word_register(emu);
1165 *destreg = (*binop)(emu, *destreg, srcval);
1170 common_binop_byte_r_rm(struct x86emu *emu,
1171 uint8_t (*binop)(struct x86emu *, uint8_t, uint8_t))
1173 uint8_t *destreg, srcval;
1176 fetch_decode_modrm(emu);
1177 destreg = decode_rh_byte_register(emu);
1178 if (emu->cur_mod != 3) {
1179 srcoffset = decode_rl_address(emu);
1180 srcval = fetch_data_byte(emu, srcoffset);
1182 srcval = *decode_rl_byte_register(emu);
1184 *destreg = (*binop)(emu, *destreg, srcval);
1188 common_binop_long_rm_r(struct x86emu *emu,
1189 uint32_t (*binop)(struct x86emu *, uint32_t, uint32_t))
1191 uint32_t destoffset;
1192 uint32_t destval, *destreg, srcval;
1194 fetch_decode_modrm(emu);
1195 srcval = *decode_rh_long_register(emu);
1196 if (emu->cur_mod != 3) {
1197 destoffset = decode_rl_address(emu);
1198 destval = fetch_data_long(emu, destoffset);
1199 destval = (*binop)(emu, destval, srcval);
1200 store_data_long(emu, destoffset, destval);
1202 destreg = decode_rl_long_register(emu);
1203 *destreg = (*binop)(emu, *destreg, srcval);
1208 common_binop_word_long_rm_r(struct x86emu *emu,
1209 uint16_t (*binop16)(struct x86emu *, uint16_t, uint16_t),
1210 uint32_t (*binop32)(struct x86emu *, uint32_t, uint32_t))
1212 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1213 common_binop_long_rm_r(emu, binop32);
1215 common_binop_word_rm_r(emu, binop16);
1219 common_binop_ns_word_rm_r(struct x86emu *emu,
1220 void (*binop)(struct x86emu *, uint16_t, uint16_t))
1222 uint32_t destoffset;
1223 uint16_t destval, srcval;
1225 fetch_decode_modrm(emu);
1226 srcval = *decode_rh_word_register(emu);
1227 if (emu->cur_mod != 3) {
1228 destoffset = decode_rl_address(emu);
1229 destval = fetch_data_word(emu, destoffset);
1231 destval = *decode_rl_word_register(emu);
1233 (*binop)(emu, destval, srcval);
1238 common_binop_ns_long_rm_r(struct x86emu *emu,
1239 void (*binop)(struct x86emu *, uint32_t, uint32_t))
1241 uint32_t destoffset;
1242 uint32_t destval, srcval;
1244 fetch_decode_modrm(emu);
1245 srcval = *decode_rh_long_register(emu);
1246 if (emu->cur_mod != 3) {
1247 destoffset = decode_rl_address(emu);
1248 destval = fetch_data_long(emu, destoffset);
1250 destval = *decode_rl_long_register(emu);
1252 (*binop)(emu, destval, srcval);
1256 common_binop_ns_word_long_rm_r(struct x86emu *emu,
1257 void (*binop16)(struct x86emu *, uint16_t, uint16_t),
1258 void (*binop32)(struct x86emu *, uint32_t, uint32_t))
1260 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1261 common_binop_ns_long_rm_r(emu, binop32);
1263 common_binop_ns_word_rm_r(emu, binop16);
1267 common_binop_long_r_rm(struct x86emu *emu,
1268 uint32_t (*binop)(struct x86emu *, uint32_t, uint32_t))
1271 uint32_t *destreg, srcval;
1273 fetch_decode_modrm(emu);
1274 destreg = decode_rh_long_register(emu);
1275 if (emu->cur_mod != 3) {
1276 srcoffset = decode_rl_address(emu);
1277 srcval = fetch_data_long(emu, srcoffset);
1279 srcval = *decode_rl_long_register(emu);
1281 *destreg = (*binop)(emu, *destreg, srcval);
1285 common_binop_word_r_rm(struct x86emu *emu,
1286 uint16_t (*binop)(struct x86emu *, uint16_t, uint16_t))
1289 uint16_t *destreg, srcval;
1291 fetch_decode_modrm(emu);
1292 destreg = decode_rh_word_register(emu);
1293 if (emu->cur_mod != 3) {
1294 srcoffset = decode_rl_address(emu);
1295 srcval = fetch_data_word(emu, srcoffset);
1297 srcval = *decode_rl_word_register(emu);
1299 *destreg = (*binop)(emu, *destreg, srcval);
1303 common_binop_word_long_r_rm(struct x86emu *emu,
1304 uint16_t (*binop16)(struct x86emu *, uint16_t, uint16_t),
1305 uint32_t (*binop32)(struct x86emu *, uint32_t, uint32_t))
1307 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1308 common_binop_long_r_rm(emu, binop32);
1310 common_binop_word_r_rm(emu, binop16);
1314 common_binop_byte_imm(struct x86emu *emu,
1315 uint8_t (*binop)(struct x86emu *, uint8_t, uint8_t))
1319 srcval = fetch_byte_imm(emu);
1320 emu->x86.R_AL = (*binop)(emu, emu->x86.R_AL, srcval);
1324 common_binop_word_long_imm(struct x86emu *emu,
1325 uint16_t (*binop16)(struct x86emu *, uint16_t, uint16_t),
1326 uint32_t (*binop32)(struct x86emu *, uint32_t, uint32_t))
1328 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1331 srcval = fetch_long_imm(emu);
1332 emu->x86.R_EAX = (*binop32)(emu, emu->x86.R_EAX, srcval);
1336 srcval = fetch_word_imm(emu);
1337 emu->x86.R_AX = (*binop16)(emu, emu->x86.R_AX, srcval);
1342 common_push_word_long(struct x86emu *emu, union x86emu_register *reg)
1344 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1345 push_long(emu, reg->I32_reg.e_reg);
1347 push_word(emu, reg->I16_reg.x_reg);
1351 common_pop_word_long(struct x86emu *emu, union x86emu_register *reg)
1353 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1354 reg->I32_reg.e_reg = pop_long(emu);
1356 reg->I16_reg.x_reg = pop_word(emu);
1360 common_imul_long_IMM(struct x86emu *emu, int byte_imm)
1363 uint32_t *destreg, srcval;
1367 fetch_decode_modrm(emu);
1368 destreg = decode_rh_long_register(emu);
1369 if (emu->cur_mod != 3) {
1370 srcoffset = decode_rl_address(emu);
1371 srcval = fetch_data_long(emu, srcoffset);
1373 srcval = *decode_rl_long_register(emu);
1377 imm = (int8_t)fetch_byte_imm(emu);
1379 imm = fetch_long_imm(emu);
1380 res = (int32_t)srcval * imm;
1382 if (res > 0xffffffff) {
1389 *destreg = (uint32_t)res;
1393 common_imul_word_IMM(struct x86emu *emu, int byte_imm)
1396 uint16_t *destreg, srcval;
1400 fetch_decode_modrm(emu);
1401 destreg = decode_rh_word_register(emu);
1402 if (emu->cur_mod != 3) {
1403 srcoffset = decode_rl_address(emu);
1404 srcval = fetch_data_word(emu, srcoffset);
1406 srcval = *decode_rl_word_register(emu);
1410 imm = (int8_t)fetch_byte_imm(emu);
1412 imm = fetch_word_imm(emu);
1413 res = (int16_t)srcval * imm;
1422 *destreg = (uint16_t) res;
1426 common_imul_imm(struct x86emu *emu, int byte_imm)
1428 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1429 common_imul_long_IMM(emu, byte_imm);
1431 common_imul_word_IMM(emu, byte_imm);
1435 common_jmp_near(struct x86emu *emu, int cond)
1440 offset = (int8_t) fetch_byte_imm(emu);
1441 target = (uint16_t) (emu->x86.R_IP + (int16_t) offset);
1443 emu->x86.R_IP = target;
1447 common_load_far_pointer(struct x86emu *emu, uint16_t *seg)
1452 fetch_decode_modrm(emu);
1453 if (emu->cur_mod == 3)
1454 x86emu_halt_sys(emu);
1456 dstreg = decode_rh_word_register(emu);
1457 srcoffset = decode_rl_address(emu);
1458 *dstreg = fetch_data_word(emu, srcoffset);
1459 *seg = fetch_data_word(emu, srcoffset + 2);
1462 /* Implementation */
1466 * Handles opcode 0x3a
1469 x86emuOp_cmp_byte_R_RM(struct x86emu *emu)
1471 uint8_t *destreg, srcval;
1473 fetch_decode_modrm(emu);
1474 destreg = decode_rh_byte_register(emu);
1475 srcval = decode_and_fetch_byte(emu);
1476 cmp_byte(emu, *destreg, srcval);
1482 * Handles opcode 0x3b
1485 x86emuOp32_cmp_word_R_RM(struct x86emu *emu)
1487 uint32_t srcval, *destreg;
1489 fetch_decode_modrm(emu);
1490 destreg = decode_rh_long_register(emu);
1491 srcval = decode_and_fetch_long(emu);
1492 cmp_long(emu, *destreg, srcval);
1496 x86emuOp16_cmp_word_R_RM(struct x86emu *emu)
1498 uint16_t srcval, *destreg;
1500 fetch_decode_modrm(emu);
1501 destreg = decode_rh_word_register(emu);
1502 srcval = decode_and_fetch_word(emu);
1503 cmp_word(emu, *destreg, srcval);
1507 x86emuOp_cmp_word_R_RM(struct x86emu *emu)
1509 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1510 x86emuOp32_cmp_word_R_RM(emu);
1512 x86emuOp16_cmp_word_R_RM(emu);
1517 * Handles opcode 0x3c
1520 x86emuOp_cmp_byte_AL_IMM(struct x86emu *emu)
1524 srcval = fetch_byte_imm(emu);
1525 cmp_byte(emu, emu->x86.R_AL, srcval);
1530 * Handles opcode 0x3d
1533 x86emuOp32_cmp_word_AX_IMM(struct x86emu *emu)
1537 srcval = fetch_long_imm(emu);
1538 cmp_long(emu, emu->x86.R_EAX, srcval);
1542 x86emuOp16_cmp_word_AX_IMM(struct x86emu *emu)
1546 srcval = fetch_word_imm(emu);
1547 cmp_word(emu, emu->x86.R_AX, srcval);
1551 x86emuOp_cmp_word_AX_IMM(struct x86emu *emu)
1553 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1554 x86emuOp32_cmp_word_AX_IMM(emu);
1556 x86emuOp16_cmp_word_AX_IMM(emu);
1561 * Handles opcode 0x60
1564 x86emuOp_push_all(struct x86emu *emu)
1566 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1567 uint32_t old_sp = emu->x86.R_ESP;
1569 push_long(emu, emu->x86.R_EAX);
1570 push_long(emu, emu->x86.R_ECX);
1571 push_long(emu, emu->x86.R_EDX);
1572 push_long(emu, emu->x86.R_EBX);
1573 push_long(emu, old_sp);
1574 push_long(emu, emu->x86.R_EBP);
1575 push_long(emu, emu->x86.R_ESI);
1576 push_long(emu, emu->x86.R_EDI);
1578 uint16_t old_sp = emu->x86.R_SP;
1580 push_word(emu, emu->x86.R_AX);
1581 push_word(emu, emu->x86.R_CX);
1582 push_word(emu, emu->x86.R_DX);
1583 push_word(emu, emu->x86.R_BX);
1584 push_word(emu, old_sp);
1585 push_word(emu, emu->x86.R_BP);
1586 push_word(emu, emu->x86.R_SI);
1587 push_word(emu, emu->x86.R_DI);
1593 * Handles opcode 0x61
1596 x86emuOp_pop_all(struct x86emu *emu)
1598 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1599 emu->x86.R_EDI = pop_long(emu);
1600 emu->x86.R_ESI = pop_long(emu);
1601 emu->x86.R_EBP = pop_long(emu);
1602 emu->x86.R_ESP += 4; /* skip ESP */
1603 emu->x86.R_EBX = pop_long(emu);
1604 emu->x86.R_EDX = pop_long(emu);
1605 emu->x86.R_ECX = pop_long(emu);
1606 emu->x86.R_EAX = pop_long(emu);
1608 emu->x86.R_DI = pop_word(emu);
1609 emu->x86.R_SI = pop_word(emu);
1610 emu->x86.R_BP = pop_word(emu);
1611 emu->x86.R_SP += 2;/* skip SP */
1612 emu->x86.R_BX = pop_word(emu);
1613 emu->x86.R_DX = pop_word(emu);
1614 emu->x86.R_CX = pop_word(emu);
1615 emu->x86.R_AX = pop_word(emu);
1618 /*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */
1619 /*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */
1624 * Handles opcode 0x68
1627 x86emuOp_push_word_IMM(struct x86emu *emu)
1629 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1632 imm = fetch_long_imm(emu);
1633 push_long(emu, imm);
1637 imm = fetch_word_imm(emu);
1638 push_word(emu, imm);
1644 * Handles opcode 0x6a
1647 x86emuOp_push_byte_IMM(struct x86emu *emu)
1651 imm = (int8_t) fetch_byte_imm(emu);
1652 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1653 push_long(emu, (int32_t) imm);
1655 push_word(emu, imm);
1661 * Handles opcode 0x6c and 0x6d
1664 x86emuOp_ins_word(struct x86emu *emu)
1666 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1675 * Handles opcode 0x6f
1678 x86emuOp_outs_word(struct x86emu *emu)
1680 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1689 * Handles opcode 0x7c
1692 x86emuOp_jump_near_L(struct x86emu *emu)
1696 sf = ACCESS_FLAG(F_SF) != 0;
1697 of = ACCESS_FLAG(F_OF) != 0;
1699 common_jmp_near(emu, sf != of);
1704 * Handles opcode 0x7d
1707 x86emuOp_jump_near_NL(struct x86emu *emu)
1711 sf = ACCESS_FLAG(F_SF) != 0;
1712 of = ACCESS_FLAG(F_OF) != 0;
1714 common_jmp_near(emu, sf == of);
1719 * Handles opcode 0x7e
1722 x86emuOp_jump_near_LE(struct x86emu *emu)
1726 sf = ACCESS_FLAG(F_SF) != 0;
1727 of = ACCESS_FLAG(F_OF) != 0;
1729 common_jmp_near(emu, sf != of || ACCESS_FLAG(F_ZF));
1734 * Handles opcode 0x7f
1737 x86emuOp_jump_near_NLE(struct x86emu *emu)
1741 sf = ACCESS_FLAG(F_SF) != 0;
1742 of = ACCESS_FLAG(F_OF) != 0;
1744 common_jmp_near(emu, sf == of && !ACCESS_FLAG(F_ZF));
1748 uint8_t(*const opc80_byte_operation[]) (struct x86emu *, uint8_t d, uint8_t s) =
1762 * Handles opcode 0x80
1765 x86emuOp_opc80_byte_RM_IMM(struct x86emu *emu)
1767 uint8_t imm, destval;
1770 * Weirdo special case instruction format. Part of the opcode
1771 * held below in "RH". Doubly nested case would result, except
1772 * that the decoded instruction
1774 fetch_decode_modrm(emu);
1775 destval = decode_and_fetch_byte(emu);
1776 imm = fetch_byte_imm(emu);
1777 destval = (*opc80_byte_operation[emu->cur_rh]) (emu, destval, imm);
1778 if (emu->cur_rh != 7)
1779 write_back_byte(emu, destval);
1783 uint16_t(* const opc81_word_operation[])
1784 (struct x86emu *, uint16_t d, uint16_t s) =
1797 uint32_t(* const opc81_long_operation[])
1798 (struct x86emu *, uint32_t d, uint32_t s) =
1812 * Handles opcode 0x81
1815 x86emuOp32_opc81_word_RM_IMM(struct x86emu *emu)
1817 uint32_t destval, imm;
1820 * Weirdo special case instruction format. Part of the opcode
1821 * held below in "RH". Doubly nested case would result, except
1822 * that the decoded instruction
1824 fetch_decode_modrm(emu);
1825 destval = decode_and_fetch_long(emu);
1826 imm = fetch_long_imm(emu);
1827 destval = (*opc81_long_operation[emu->cur_rh]) (emu, destval, imm);
1828 if (emu->cur_rh != 7)
1829 write_back_long(emu, destval);
1833 x86emuOp16_opc81_word_RM_IMM(struct x86emu *emu)
1835 uint16_t destval, imm;
1838 * Weirdo special case instruction format. Part of the opcode
1839 * held below in "RH". Doubly nested case would result, except
1840 * that the decoded instruction
1842 fetch_decode_modrm(emu);
1843 destval = decode_and_fetch_word(emu);
1844 imm = fetch_word_imm(emu);
1845 destval = (*opc81_word_operation[emu->cur_rh]) (emu, destval, imm);
1846 if (emu->cur_rh != 7)
1847 write_back_word(emu, destval);
1851 x86emuOp_opc81_word_RM_IMM(struct x86emu *emu)
1853 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1854 x86emuOp32_opc81_word_RM_IMM(emu);
1856 x86emuOp16_opc81_word_RM_IMM(emu);
1860 uint8_t(* const opc82_byte_operation[])
1861 (struct x86emu *, uint8_t s, uint8_t d) =
1864 or_byte, /* 01 *//* YYY UNUSED ???? */
1867 and_byte, /* 04 *//* YYY UNUSED ???? */
1869 xor_byte, /* 06 *//* YYY UNUSED ???? */
1875 * Handles opcode 0x82
1878 x86emuOp_opc82_byte_RM_IMM(struct x86emu *emu)
1880 uint8_t imm, destval;
1883 * Weirdo special case instruction format. Part of the opcode
1884 * held below in "RH". Doubly nested case would result, except
1885 * that the decoded instruction Similar to opcode 81, except that
1886 * the immediate byte is sign extended to a word length.
1888 fetch_decode_modrm(emu);
1889 destval = decode_and_fetch_byte(emu);
1890 imm = fetch_byte_imm(emu);
1891 destval = (*opc82_byte_operation[emu->cur_rh]) (emu, destval, imm);
1892 if (emu->cur_rh != 7)
1893 write_back_byte(emu, destval);
1897 uint16_t(* const opc83_word_operation[])
1898 (struct x86emu *, uint16_t s, uint16_t d) =
1901 or_word, /* 01 *//* YYY UNUSED ???? */
1904 and_word, /* 04 *//* YYY UNUSED ???? */
1906 xor_word, /* 06 *//* YYY UNUSED ???? */
1911 uint32_t(* const opc83_long_operation[])
1912 (struct x86emu *, uint32_t s, uint32_t d) =
1915 or_long, /* 01 *//* YYY UNUSED ???? */
1918 and_long, /* 04 *//* YYY UNUSED ???? */
1920 xor_long, /* 06 *//* YYY UNUSED ???? */
1926 * Handles opcode 0x83
1929 x86emuOp32_opc83_word_RM_IMM(struct x86emu *emu)
1931 uint32_t destval, imm;
1933 fetch_decode_modrm(emu);
1934 destval = decode_and_fetch_long(emu);
1935 imm = (int8_t) fetch_byte_imm(emu);
1936 destval = (*opc83_long_operation[emu->cur_rh]) (emu, destval, imm);
1937 if (emu->cur_rh != 7)
1938 write_back_long(emu, destval);
1942 x86emuOp16_opc83_word_RM_IMM(struct x86emu *emu)
1944 uint16_t destval, imm;
1946 fetch_decode_modrm(emu);
1947 destval = decode_and_fetch_word(emu);
1948 imm = (int8_t) fetch_byte_imm(emu);
1949 destval = (*opc83_word_operation[emu->cur_rh]) (emu, destval, imm);
1950 if (emu->cur_rh != 7)
1951 write_back_word(emu, destval);
1955 x86emuOp_opc83_word_RM_IMM(struct x86emu *emu)
1957 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1958 x86emuOp32_opc83_word_RM_IMM(emu);
1960 x86emuOp16_opc83_word_RM_IMM(emu);
1965 * Handles opcode 0x86
1968 x86emuOp_xchg_byte_RM_R(struct x86emu *emu)
1970 uint8_t *srcreg, destval, tmp;
1972 fetch_decode_modrm(emu);
1973 destval = decode_and_fetch_byte(emu);
1974 srcreg = decode_rh_byte_register(emu);
1978 write_back_byte(emu, destval);
1983 * Handles opcode 0x87
1986 x86emuOp32_xchg_word_RM_R(struct x86emu *emu)
1988 uint32_t *srcreg, destval, tmp;
1990 fetch_decode_modrm(emu);
1991 destval = decode_and_fetch_long(emu);
1992 srcreg = decode_rh_long_register(emu);
1996 write_back_long(emu, destval);
2000 x86emuOp16_xchg_word_RM_R(struct x86emu *emu)
2002 uint16_t *srcreg, destval, tmp;
2004 fetch_decode_modrm(emu);
2005 destval = decode_and_fetch_word(emu);
2006 srcreg = decode_rh_word_register(emu);
2010 write_back_word(emu, destval);
2014 x86emuOp_xchg_word_RM_R(struct x86emu *emu)
2016 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2017 x86emuOp32_xchg_word_RM_R(emu);
2019 x86emuOp16_xchg_word_RM_R(emu);
2024 * Handles opcode 0x88
2027 x86emuOp_mov_byte_RM_R(struct x86emu *emu)
2029 uint8_t *destreg, *srcreg;
2030 uint32_t destoffset;
2032 fetch_decode_modrm(emu);
2033 srcreg = decode_rh_byte_register(emu);
2034 if (emu->cur_mod != 3) {
2035 destoffset = decode_rl_address(emu);
2036 store_data_byte(emu, destoffset, *srcreg);
2038 destreg = decode_rl_byte_register(emu);
2045 * Handles opcode 0x89
2048 x86emuOp32_mov_word_RM_R(struct x86emu *emu)
2050 uint32_t destoffset;
2051 uint32_t *destreg, srcval;
2053 fetch_decode_modrm(emu);
2054 srcval = *decode_rh_long_register(emu);
2055 if (emu->cur_mod != 3) {
2056 destoffset = decode_rl_address(emu);
2057 store_data_long(emu, destoffset, srcval);
2059 destreg = decode_rl_long_register(emu);
2065 x86emuOp16_mov_word_RM_R(struct x86emu *emu)
2067 uint32_t destoffset;
2068 uint16_t *destreg, srcval;
2070 fetch_decode_modrm(emu);
2071 srcval = *decode_rh_word_register(emu);
2072 if (emu->cur_mod != 3) {
2073 destoffset = decode_rl_address(emu);
2074 store_data_word(emu, destoffset, srcval);
2076 destreg = decode_rl_word_register(emu);
2082 x86emuOp_mov_word_RM_R(struct x86emu *emu)
2084 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2085 x86emuOp32_mov_word_RM_R(emu);
2087 x86emuOp16_mov_word_RM_R(emu);
2092 * Handles opcode 0x8a
2095 x86emuOp_mov_byte_R_RM(struct x86emu *emu)
2099 fetch_decode_modrm(emu);
2100 destreg = decode_rh_byte_register(emu);
2101 *destreg = decode_and_fetch_byte(emu);
2106 * Handles opcode 0x8b
2109 x86emuOp_mov_word_R_RM(struct x86emu *emu)
2111 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2114 fetch_decode_modrm(emu);
2115 destreg = decode_rh_long_register(emu);
2116 *destreg = decode_and_fetch_long(emu);
2120 fetch_decode_modrm(emu);
2121 destreg = decode_rh_word_register(emu);
2122 *destreg = decode_and_fetch_word(emu);
2128 * Handles opcode 0x8c
2131 x86emuOp_mov_word_RM_SR(struct x86emu *emu)
2133 uint16_t *destreg, srcval;
2134 uint32_t destoffset;
2136 fetch_decode_modrm(emu);
2137 srcval = *decode_rh_seg_register(emu);
2138 if (emu->cur_mod != 3) {
2139 destoffset = decode_rl_address(emu);
2140 store_data_word(emu, destoffset, srcval);
2142 destreg = decode_rl_word_register(emu);
2149 * Handles opcode 0x8d
2152 x86emuOp_lea_word_R_M(struct x86emu *emu)
2155 uint32_t destoffset;
2158 * TODO: Need to handle address size prefix!
2160 * lea eax,[eax+ebx*2] ??
2162 fetch_decode_modrm(emu);
2163 if (emu->cur_mod == 3)
2164 x86emu_halt_sys(emu);
2166 srcreg = decode_rh_word_register(emu);
2167 destoffset = decode_rl_address(emu);
2168 *srcreg = (uint16_t) destoffset;
2173 * Handles opcode 0x8e
2176 x86emuOp_mov_word_SR_RM(struct x86emu *emu)
2180 fetch_decode_modrm(emu);
2181 destreg = decode_rh_seg_register(emu);
2182 *destreg = decode_and_fetch_word(emu);
2184 * Clean up, and reset all the R_xSP pointers to the correct
2185 * locations. This is about 3x too much overhead (doing all the
2186 * segreg ptrs when only one is needed, but this instruction
2187 * *cannot* be that common, and this isn't too much work anyway.
2193 * Handles opcode 0x8f
2196 x86emuOp32_pop_RM(struct x86emu *emu)
2198 uint32_t destoffset;
2199 uint32_t destval, *destreg;
2201 fetch_decode_modrm(emu);
2202 if (emu->cur_mod != 3) {
2203 destoffset = decode_rl_address(emu);
2204 destval = pop_long(emu);
2205 store_data_long(emu, destoffset, destval);
2207 destreg = decode_rl_long_register(emu);
2208 *destreg = pop_long(emu);
2213 x86emuOp16_pop_RM(struct x86emu *emu)
2215 uint32_t destoffset;
2216 uint16_t destval, *destreg;
2218 fetch_decode_modrm(emu);
2219 if (emu->cur_mod != 3) {
2220 destoffset = decode_rl_address(emu);
2221 destval = pop_word(emu);
2222 store_data_word(emu, destoffset, destval);
2224 destreg = decode_rl_word_register(emu);
2225 *destreg = pop_word(emu);
2230 x86emuOp_pop_RM(struct x86emu *emu)
2232 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2233 x86emuOp32_pop_RM(emu);
2235 x86emuOp16_pop_RM(emu);
2240 * Handles opcode 0x91
2243 x86emuOp_xchg_word_AX_CX(struct x86emu *emu)
2247 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2248 tmp = emu->x86.R_EAX;
2249 emu->x86.R_EAX = emu->x86.R_ECX;
2250 emu->x86.R_ECX = tmp;
2252 tmp = emu->x86.R_AX;
2253 emu->x86.R_AX = emu->x86.R_CX;
2254 emu->x86.R_CX = (uint16_t) tmp;
2260 * Handles opcode 0x92
2263 x86emuOp_xchg_word_AX_DX(struct x86emu *emu)
2267 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2268 tmp = emu->x86.R_EAX;
2269 emu->x86.R_EAX = emu->x86.R_EDX;
2270 emu->x86.R_EDX = tmp;
2272 tmp = emu->x86.R_AX;
2273 emu->x86.R_AX = emu->x86.R_DX;
2274 emu->x86.R_DX = (uint16_t) tmp;
2280 * Handles opcode 0x93
2283 x86emuOp_xchg_word_AX_BX(struct x86emu *emu)
2287 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2288 tmp = emu->x86.R_EAX;
2289 emu->x86.R_EAX = emu->x86.R_EBX;
2290 emu->x86.R_EBX = tmp;
2292 tmp = emu->x86.R_AX;
2293 emu->x86.R_AX = emu->x86.R_BX;
2294 emu->x86.R_BX = (uint16_t) tmp;
2300 * Handles opcode 0x94
2303 x86emuOp_xchg_word_AX_SP(struct x86emu *emu)
2307 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2308 tmp = emu->x86.R_EAX;
2309 emu->x86.R_EAX = emu->x86.R_ESP;
2310 emu->x86.R_ESP = tmp;
2312 tmp = emu->x86.R_AX;
2313 emu->x86.R_AX = emu->x86.R_SP;
2314 emu->x86.R_SP = (uint16_t) tmp;
2320 * Handles opcode 0x95
2323 x86emuOp_xchg_word_AX_BP(struct x86emu *emu)
2327 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2328 tmp = emu->x86.R_EAX;
2329 emu->x86.R_EAX = emu->x86.R_EBP;
2330 emu->x86.R_EBP = tmp;
2332 tmp = emu->x86.R_AX;
2333 emu->x86.R_AX = emu->x86.R_BP;
2334 emu->x86.R_BP = (uint16_t) tmp;
2340 * Handles opcode 0x96
2343 x86emuOp_xchg_word_AX_SI(struct x86emu *emu)
2347 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2348 tmp = emu->x86.R_EAX;
2349 emu->x86.R_EAX = emu->x86.R_ESI;
2350 emu->x86.R_ESI = tmp;
2352 tmp = emu->x86.R_AX;
2353 emu->x86.R_AX = emu->x86.R_SI;
2354 emu->x86.R_SI = (uint16_t) tmp;
2360 * Handles opcode 0x97
2363 x86emuOp_xchg_word_AX_DI(struct x86emu *emu)
2367 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2368 tmp = emu->x86.R_EAX;
2369 emu->x86.R_EAX = emu->x86.R_EDI;
2370 emu->x86.R_EDI = tmp;
2372 tmp = emu->x86.R_AX;
2373 emu->x86.R_AX = emu->x86.R_DI;
2374 emu->x86.R_DI = (uint16_t) tmp;
2380 * Handles opcode 0x98
2383 x86emuOp_cbw(struct x86emu *emu)
2385 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2386 if (emu->x86.R_AX & 0x8000) {
2387 emu->x86.R_EAX |= 0xffff0000;
2389 emu->x86.R_EAX &= 0x0000ffff;
2392 if (emu->x86.R_AL & 0x80) {
2393 emu->x86.R_AH = 0xff;
2395 emu->x86.R_AH = 0x0;
2402 * Handles opcode 0x99
2405 x86emuOp_cwd(struct x86emu *emu)
2407 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2408 if (emu->x86.R_EAX & 0x80000000) {
2409 emu->x86.R_EDX = 0xffffffff;
2411 emu->x86.R_EDX = 0x0;
2414 if (emu->x86.R_AX & 0x8000) {
2415 emu->x86.R_DX = 0xffff;
2417 emu->x86.R_DX = 0x0;
2424 * Handles opcode 0x9a
2427 x86emuOp_call_far_IMM(struct x86emu *emu)
2429 uint16_t farseg, faroff;
2431 faroff = fetch_word_imm(emu);
2432 farseg = fetch_word_imm(emu);
2435 * Hooked interrupt vectors calling into our "BIOS" will cause problems
2436 * unless all intersegment stuff is checked for BIOS access. Check
2437 * needed here. For moment, let it alone. */
2438 push_word(emu, emu->x86.R_CS);
2439 emu->x86.R_CS = farseg;
2440 push_word(emu, emu->x86.R_IP);
2441 emu->x86.R_IP = faroff;
2446 * Handles opcode 0x9c
2449 x86emuOp_pushf_word(struct x86emu *emu)
2453 /* clear out *all* bits not representing flags, and turn on real bits */
2454 flags = (emu->x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
2455 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2456 push_long(emu, flags);
2458 push_word(emu, (uint16_t) flags);
2464 * Handles opcode 0x9d
2467 x86emuOp_popf_word(struct x86emu *emu)
2469 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2470 emu->x86.R_EFLG = pop_long(emu);
2472 emu->x86.R_FLG = pop_word(emu);
2478 * Handles opcode 0x9e
2481 x86emuOp_sahf(struct x86emu *emu)
2483 /* clear the lower bits of the flag register */
2484 emu->x86.R_FLG &= 0xffffff00;
2485 /* or in the AH register into the flags register */
2486 emu->x86.R_FLG |= emu->x86.R_AH;
2491 * Handles opcode 0x9f
2494 x86emuOp_lahf(struct x86emu *emu)
2496 emu->x86.R_AH = (uint8_t) (emu->x86.R_FLG & 0xff);
2497 /* undocumented TC++ behavior??? Nope. It's documented, but you have
2498 * too look real hard to notice it. */
2499 emu->x86.R_AH |= 0x2;
2504 * Handles opcode 0xa0
2507 x86emuOp_mov_AL_M_IMM(struct x86emu *emu)
2511 offset = fetch_word_imm(emu);
2512 emu->x86.R_AL = fetch_data_byte(emu, offset);
2517 * Handles opcode 0xa1
2520 x86emuOp_mov_AX_M_IMM(struct x86emu *emu)
2524 offset = fetch_word_imm(emu);
2525 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2526 emu->x86.R_EAX = fetch_data_long(emu, offset);
2528 emu->x86.R_AX = fetch_data_word(emu, offset);
2534 * Handles opcode 0xa2
2537 x86emuOp_mov_M_AL_IMM(struct x86emu *emu)
2541 offset = fetch_word_imm(emu);
2542 store_data_byte(emu, offset, emu->x86.R_AL);
2547 * Handles opcode 0xa3
2550 x86emuOp_mov_M_AX_IMM(struct x86emu *emu)
2554 offset = fetch_word_imm(emu);
2555 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2556 store_data_long(emu, offset, emu->x86.R_EAX);
2558 store_data_word(emu, offset, emu->x86.R_AX);
2564 * Handles opcode 0xa4
2567 x86emuOp_movs_byte(struct x86emu *emu)
2573 if (ACCESS_FLAG(F_DF)) /* down */
2578 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2579 /* dont care whether REPE or REPNE */
2580 /* move them until CX is ZERO. */
2581 count = emu->x86.R_CX;
2583 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2586 val = fetch_data_byte(emu, emu->x86.R_SI);
2587 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, val);
2588 emu->x86.R_SI += inc;
2589 emu->x86.R_DI += inc;
2595 * Handles opcode 0xa5
2598 x86emuOp_movs_word(struct x86emu *emu)
2604 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2609 if (ACCESS_FLAG(F_DF)) /* down */
2613 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2614 /* dont care whether REPE or REPNE */
2615 /* move them until CX is ZERO. */
2616 count = emu->x86.R_CX;
2618 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2621 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2622 val = fetch_data_long(emu, emu->x86.R_SI);
2623 store_long(emu, emu->x86.R_ES, emu->x86.R_DI, val);
2625 val = fetch_data_word(emu, emu->x86.R_SI);
2626 store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
2629 emu->x86.R_SI += inc;
2630 emu->x86.R_DI += inc;
2636 * Handles opcode 0xa6
2639 x86emuOp_cmps_byte(struct x86emu *emu)
2644 if (ACCESS_FLAG(F_DF)) /* down */
2649 if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2651 /* move them until CX is ZERO. */
2652 while (emu->x86.R_CX != 0) {
2653 val1 = fetch_data_byte(emu, emu->x86.R_SI);
2654 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2655 cmp_byte(emu, val1, val2);
2657 emu->x86.R_SI += inc;
2658 emu->x86.R_DI += inc;
2659 if (ACCESS_FLAG(F_ZF) == 0)
2662 emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2663 } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2665 /* move them until CX is ZERO. */
2666 while (emu->x86.R_CX != 0) {
2667 val1 = fetch_data_byte(emu, emu->x86.R_SI);
2668 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2669 cmp_byte(emu, val1, val2);
2671 emu->x86.R_SI += inc;
2672 emu->x86.R_DI += inc;
2673 if (ACCESS_FLAG(F_ZF))
2674 break; /* zero flag set means equal */
2676 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2678 val1 = fetch_data_byte(emu, emu->x86.R_SI);
2679 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2680 cmp_byte(emu, val1, val2);
2681 emu->x86.R_SI += inc;
2682 emu->x86.R_DI += inc;
2688 * Handles opcode 0xa7
2691 x86emuOp_cmps_word(struct x86emu *emu)
2693 uint32_t val1, val2;
2696 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2697 if (ACCESS_FLAG(F_DF)) /* down */
2702 if (ACCESS_FLAG(F_DF)) /* down */
2707 if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2709 /* move them until CX is ZERO. */
2710 while (emu->x86.R_CX != 0) {
2711 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2712 val1 = fetch_data_long(emu, emu->x86.R_SI);
2713 val2 = fetch_long(emu, emu->x86.R_ES,
2715 cmp_long(emu, val1, val2);
2717 val1 = fetch_data_word(emu, emu->x86.R_SI);
2718 val2 = fetch_word(emu, emu->x86.R_ES,
2720 cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
2723 emu->x86.R_SI += inc;
2724 emu->x86.R_DI += inc;
2725 if (ACCESS_FLAG(F_ZF) == 0)
2728 emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2729 } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2731 /* move them until CX is ZERO. */
2732 while (emu->x86.R_CX != 0) {
2733 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2734 val1 = fetch_data_long(emu, emu->x86.R_SI);
2735 val2 = fetch_long(emu, emu->x86.R_ES,
2737 cmp_long(emu, val1, val2);
2739 val1 = fetch_data_word(emu, emu->x86.R_SI);
2740 val2 = fetch_word(emu, emu->x86.R_ES,
2742 cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
2745 emu->x86.R_SI += inc;
2746 emu->x86.R_DI += inc;
2747 if (ACCESS_FLAG(F_ZF))
2748 break; /* zero flag set means equal */
2750 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2752 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2753 val1 = fetch_data_long(emu, emu->x86.R_SI);
2754 val2 = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
2755 cmp_long(emu, val1, val2);
2757 val1 = fetch_data_word(emu, emu->x86.R_SI);
2758 val2 = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
2759 cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
2761 emu->x86.R_SI += inc;
2762 emu->x86.R_DI += inc;
2768 * Handles opcode 0xa9
2771 x86emuOp_test_AX_IMM(struct x86emu *emu)
2773 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2774 test_long(emu, emu->x86.R_EAX, fetch_long_imm(emu));
2776 test_word(emu, emu->x86.R_AX, fetch_word_imm(emu));
2782 * Handles opcode 0xaa
2785 x86emuOp_stos_byte(struct x86emu *emu)
2789 if (ACCESS_FLAG(F_DF)) /* down */
2793 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2794 /* dont care whether REPE or REPNE */
2795 /* move them until CX is ZERO. */
2796 while (emu->x86.R_CX != 0) {
2797 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
2800 emu->x86.R_DI += inc;
2802 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2804 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_AL);
2805 emu->x86.R_DI += inc;
2811 * Handles opcode 0xab
2814 x86emuOp_stos_word(struct x86emu *emu)
2819 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2824 if (ACCESS_FLAG(F_DF)) /* down */
2828 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2829 /* dont care whether REPE or REPNE */
2830 /* move them until CX is ZERO. */
2831 count = emu->x86.R_CX;
2833 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2836 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2837 store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
2840 store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
2843 emu->x86.R_DI += inc;
2849 * Handles opcode 0xac
2852 x86emuOp_lods_byte(struct x86emu *emu)
2856 if (ACCESS_FLAG(F_DF)) /* down */
2860 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2861 /* dont care whether REPE or REPNE */
2862 /* move them until CX is ZERO. */
2863 while (emu->x86.R_CX != 0) {
2864 emu->x86.R_AL = fetch_data_byte(emu, emu->x86.R_SI);
2866 emu->x86.R_SI += inc;
2868 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2870 emu->x86.R_AL = fetch_data_byte(emu, emu->x86.R_SI);
2871 emu->x86.R_SI += inc;
2877 * Handles opcode 0xad
2880 x86emuOp_lods_word(struct x86emu *emu)
2885 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2890 if (ACCESS_FLAG(F_DF)) /* down */
2894 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2895 /* dont care whether REPE or REPNE */
2896 /* move them until CX is ZERO. */
2897 count = emu->x86.R_CX;
2899 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2902 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2903 emu->x86.R_EAX = fetch_data_long(emu, emu->x86.R_SI);
2905 emu->x86.R_AX = fetch_data_word(emu, emu->x86.R_SI);
2907 emu->x86.R_SI += inc;
2913 * Handles opcode 0xae
2916 x86emuOp_scas_byte(struct x86emu *emu)
2921 if (ACCESS_FLAG(F_DF)) /* down */
2925 if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2927 /* move them until CX is ZERO. */
2928 while (emu->x86.R_CX != 0) {
2929 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2930 cmp_byte(emu, emu->x86.R_AL, val2);
2932 emu->x86.R_DI += inc;
2933 if (ACCESS_FLAG(F_ZF) == 0)
2936 emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2937 } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2939 /* move them until CX is ZERO. */
2940 while (emu->x86.R_CX != 0) {
2941 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2942 cmp_byte(emu, emu->x86.R_AL, val2);
2944 emu->x86.R_DI += inc;
2945 if (ACCESS_FLAG(F_ZF))
2946 break; /* zero flag set means equal */
2948 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2950 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2951 cmp_byte(emu, emu->x86.R_AL, val2);
2952 emu->x86.R_DI += inc;
2958 * Handles opcode 0xaf
2961 x86emuOp_scas_word(struct x86emu *emu)
2966 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2971 if (ACCESS_FLAG(F_DF)) /* down */
2974 if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2976 /* move them until CX is ZERO. */
2977 while (emu->x86.R_CX != 0) {
2978 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2979 val = fetch_long(emu, emu->x86.R_ES,
2981 cmp_long(emu, emu->x86.R_EAX, val);
2983 val = fetch_word(emu, emu->x86.R_ES,
2985 cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
2988 emu->x86.R_DI += inc;
2989 if (ACCESS_FLAG(F_ZF) == 0)
2992 emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2993 } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2995 /* move them until CX is ZERO. */
2996 while (emu->x86.R_CX != 0) {
2997 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2998 val = fetch_long(emu, emu->x86.R_ES,
3000 cmp_long(emu, emu->x86.R_EAX, val);
3002 val = fetch_word(emu, emu->x86.R_ES,
3004 cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
3007 emu->x86.R_DI += inc;
3008 if (ACCESS_FLAG(F_ZF))
3009 break; /* zero flag set means equal */
3011 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
3013 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3014 val = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
3015 cmp_long(emu, emu->x86.R_EAX, val);
3017 val = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
3018 cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
3020 emu->x86.R_DI += inc;
3026 * Handles opcode 0xb8
3029 x86emuOp_mov_word_AX_IMM(struct x86emu *emu)
3031 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3032 emu->x86.R_EAX = fetch_long_imm(emu);
3034 emu->x86.R_AX = fetch_word_imm(emu);
3039 * Handles opcode 0xb9
3042 x86emuOp_mov_word_CX_IMM(struct x86emu *emu)
3044 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3045 emu->x86.R_ECX = fetch_long_imm(emu);
3047 emu->x86.R_CX = fetch_word_imm(emu);
3052 * Handles opcode 0xba
3055 x86emuOp_mov_word_DX_IMM(struct x86emu *emu)
3057 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3058 emu->x86.R_EDX = fetch_long_imm(emu);
3060 emu->x86.R_DX = fetch_word_imm(emu);
3065 * Handles opcode 0xbb
3068 x86emuOp_mov_word_BX_IMM(struct x86emu *emu)
3070 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3071 emu->x86.R_EBX = fetch_long_imm(emu);
3073 emu->x86.R_BX = fetch_word_imm(emu);
3078 * Handles opcode 0xbc
3081 x86emuOp_mov_word_SP_IMM(struct x86emu *emu)
3083 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3084 emu->x86.R_ESP = fetch_long_imm(emu);
3086 emu->x86.R_SP = fetch_word_imm(emu);
3091 * Handles opcode 0xbd
3094 x86emuOp_mov_word_BP_IMM(struct x86emu *emu)
3096 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3097 emu->x86.R_EBP = fetch_long_imm(emu);
3099 emu->x86.R_BP = fetch_word_imm(emu);
3104 * Handles opcode 0xbe
3107 x86emuOp_mov_word_SI_IMM(struct x86emu *emu)
3109 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3110 emu->x86.R_ESI = fetch_long_imm(emu);
3112 emu->x86.R_SI = fetch_word_imm(emu);
3117 * Handles opcode 0xbf
3120 x86emuOp_mov_word_DI_IMM(struct x86emu *emu)
3122 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3123 emu->x86.R_EDI = fetch_long_imm(emu);
3125 emu->x86.R_DI = fetch_word_imm(emu);
3127 /* used by opcodes c0, d0, and d2. */
3129 uint8_t(* const opcD0_byte_operation[])
3130 (struct x86emu *, uint8_t d, uint8_t s) =
3138 shl_byte, /* sal_byte === shl_byte by definition */
3144 * Handles opcode 0xc0
3147 x86emuOp_opcC0_byte_RM_MEM(struct x86emu *emu)
3149 uint8_t destval, amt;
3152 * Yet another weirdo special case instruction format. Part of
3153 * the opcode held below in "RH". Doubly nested case would
3154 * result, except that the decoded instruction
3156 fetch_decode_modrm(emu);
3157 /* know operation, decode the mod byte to find the addressing mode. */
3158 destval = decode_and_fetch_byte_imm8(emu, &amt);
3159 destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, amt);
3160 write_back_byte(emu, destval);
3162 /* used by opcodes c1, d1, and d3. */
3164 uint16_t(* const opcD1_word_operation[])
3165 (struct x86emu *, uint16_t s, uint8_t d) =
3173 shl_word, /* sal_byte === shl_byte by definition */
3176 /* used by opcodes c1, d1, and d3. */
3178 uint32_t(* const opcD1_long_operation[])
3179 (struct x86emu *, uint32_t s, uint8_t d) =
3187 shl_long, /* sal_byte === shl_byte by definition */
3193 * Handles opcode 0xc1
3196 x86emuOp_opcC1_word_RM_MEM(struct x86emu *emu)
3201 * Yet another weirdo special case instruction format. Part of
3202 * the opcode held below in "RH". Doubly nested case would
3203 * result, except that the decoded instruction
3205 fetch_decode_modrm(emu);
3206 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3209 destval = decode_and_fetch_long_imm8(emu, &amt);
3210 destval = (*opcD1_long_operation[emu->cur_rh])
3211 (emu, destval, amt);
3212 write_back_long(emu, destval);
3216 destval = decode_and_fetch_word_imm8(emu, &amt);
3217 destval = (*opcD1_word_operation[emu->cur_rh])
3218 (emu, destval, amt);
3219 write_back_word(emu, destval);
3225 * Handles opcode 0xc2
3228 x86emuOp_ret_near_IMM(struct x86emu *emu)
3232 imm = fetch_word_imm(emu);
3233 emu->x86.R_IP = pop_word(emu);
3234 emu->x86.R_SP += imm;
3239 * Handles opcode 0xc6
3242 x86emuOp_mov_byte_RM_IMM(struct x86emu *emu)
3245 uint32_t destoffset;
3248 fetch_decode_modrm(emu);
3249 if (emu->cur_rh != 0)
3250 x86emu_halt_sys(emu);
3251 if (emu->cur_mod != 3) {
3252 destoffset = decode_rl_address(emu);
3253 imm = fetch_byte_imm(emu);
3254 store_data_byte(emu, destoffset, imm);
3256 destreg = decode_rl_byte_register(emu);
3257 imm = fetch_byte_imm(emu);
3264 * Handles opcode 0xc7
3267 x86emuOp32_mov_word_RM_IMM(struct x86emu *emu)
3269 uint32_t destoffset;
3270 uint32_t imm, *destreg;
3272 fetch_decode_modrm(emu);
3273 if (emu->cur_rh != 0)
3274 x86emu_halt_sys(emu);
3276 if (emu->cur_mod != 3) {
3277 destoffset = decode_rl_address(emu);
3278 imm = fetch_long_imm(emu);
3279 store_data_long(emu, destoffset, imm);
3281 destreg = decode_rl_long_register(emu);
3282 imm = fetch_long_imm(emu);
3288 x86emuOp16_mov_word_RM_IMM(struct x86emu *emu)
3290 uint32_t destoffset;
3291 uint16_t imm, *destreg;
3293 fetch_decode_modrm(emu);
3294 if (emu->cur_rh != 0)
3295 x86emu_halt_sys(emu);
3297 if (emu->cur_mod != 3) {
3298 destoffset = decode_rl_address(emu);
3299 imm = fetch_word_imm(emu);
3300 store_data_word(emu, destoffset, imm);
3302 destreg = decode_rl_word_register(emu);
3303 imm = fetch_word_imm(emu);
3309 x86emuOp_mov_word_RM_IMM(struct x86emu *emu)
3311 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3312 x86emuOp32_mov_word_RM_IMM(emu);
3314 x86emuOp16_mov_word_RM_IMM(emu);
3319 * Handles opcode 0xc8
3322 x86emuOp_enter(struct x86emu *emu)
3324 uint16_t local, frame_pointer;
3328 local = fetch_word_imm(emu);
3329 nesting = fetch_byte_imm(emu);
3330 push_word(emu, emu->x86.R_BP);
3331 frame_pointer = emu->x86.R_SP;
3333 for (i = 1; i < nesting; i++) {
3335 push_word(emu, fetch_word(emu, emu->x86.R_SS,
3338 push_word(emu, frame_pointer);
3340 emu->x86.R_BP = frame_pointer;
3341 emu->x86.R_SP = (uint16_t) (emu->x86.R_SP - local);
3346 * Handles opcode 0xc9
3349 x86emuOp_leave(struct x86emu *emu)
3351 emu->x86.R_SP = emu->x86.R_BP;
3352 emu->x86.R_BP = pop_word(emu);
3357 * Handles opcode 0xca
3360 x86emuOp_ret_far_IMM(struct x86emu *emu)
3364 imm = fetch_word_imm(emu);
3365 emu->x86.R_IP = pop_word(emu);
3366 emu->x86.R_CS = pop_word(emu);
3367 emu->x86.R_SP += imm;
3372 * Handles opcode 0xcb
3375 x86emuOp_ret_far(struct x86emu *emu)
3377 emu->x86.R_IP = pop_word(emu);
3378 emu->x86.R_CS = pop_word(emu);
3383 * Handles opcode 0xcc
3386 x86emuOp_int3(struct x86emu *emu)
3388 x86emu_intr_dispatch(emu, 3);
3393 * Handles opcode 0xcd
3396 x86emuOp_int_IMM(struct x86emu *emu)
3400 intnum = fetch_byte_imm(emu);
3401 x86emu_intr_dispatch(emu, intnum);
3406 * Handles opcode 0xce
3409 x86emuOp_into(struct x86emu *emu)
3411 if (ACCESS_FLAG(F_OF))
3412 x86emu_intr_dispatch(emu, 4);
3417 * Handles opcode 0xcf
3420 x86emuOp_iret(struct x86emu *emu)
3422 emu->x86.R_IP = pop_word(emu);
3423 emu->x86.R_CS = pop_word(emu);
3424 emu->x86.R_FLG = pop_word(emu);
3429 * Handles opcode 0xd0
3432 x86emuOp_opcD0_byte_RM_1(struct x86emu *emu)
3436 fetch_decode_modrm(emu);
3437 destval = decode_and_fetch_byte(emu);
3438 destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, 1);
3439 write_back_byte(emu, destval);
3444 * Handles opcode 0xd1
3447 x86emuOp_opcD1_word_RM_1(struct x86emu *emu)
3449 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3452 fetch_decode_modrm(emu);
3453 destval = decode_and_fetch_long(emu);
3454 destval = (*opcD1_long_operation[emu->cur_rh])(emu, destval, 1);
3455 write_back_long(emu, destval);
3459 fetch_decode_modrm(emu);
3460 destval = decode_and_fetch_word(emu);
3461 destval = (*opcD1_word_operation[emu->cur_rh])(emu, destval, 1);
3462 write_back_word(emu, destval);
3468 * Handles opcode 0xd2
3471 x86emuOp_opcD2_byte_RM_CL(struct x86emu *emu)
3475 fetch_decode_modrm(emu);
3476 destval = decode_and_fetch_byte(emu);
3477 destval = (*opcD0_byte_operation[emu->cur_rh])
3478 (emu, destval, emu->x86.R_CL);
3479 write_back_byte(emu, destval);
3484 * Handles opcode 0xd3
3487 x86emuOp_opcD3_word_RM_CL(struct x86emu *emu)
3489 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3492 fetch_decode_modrm(emu);
3493 destval = decode_and_fetch_long(emu);
3494 destval = (*opcD1_long_operation[emu->cur_rh])
3495 (emu, destval, emu->x86.R_CL);
3496 write_back_long(emu, destval);
3500 fetch_decode_modrm(emu);
3501 destval = decode_and_fetch_word(emu);
3502 destval = (*opcD1_word_operation[emu->cur_rh])
3503 (emu, destval, emu->x86.R_CL);
3504 write_back_word(emu, destval);
3510 * Handles opcode 0xd4
3513 x86emuOp_aam(struct x86emu *emu)
3517 a = fetch_byte_imm(emu); /* this is a stupid encoding. */
3519 /* fix: add base decoding aam_word(uint8_t val, int base a) */
3520 x86emu_halt_sys(emu);
3522 /* note the type change here --- returning AL and AH in AX. */
3523 emu->x86.R_AX = aam_word(emu, emu->x86.R_AL);
3528 * Handles opcode 0xd5
3531 x86emuOp_aad(struct x86emu *emu)
3535 a = fetch_byte_imm(emu);
3537 /* fix: add base decoding aad_word(uint16_t val, int base a) */
3538 x86emu_halt_sys(emu);
3540 emu->x86.R_AX = aad_word(emu, emu->x86.R_AX);
3542 /* opcode 0xd6 ILLEGAL OPCODE */
3547 * Handles opcode 0xd7
3550 x86emuOp_xlat(struct x86emu *emu)
3554 addr = (uint16_t) (emu->x86.R_BX + (uint8_t) emu->x86.R_AL);
3555 emu->x86.R_AL = fetch_data_byte(emu, addr);
3560 x86emuOp_esc_coprocess_d8(struct x86emu *emu)
3565 x86emuOp_esc_coprocess_d9(struct x86emu *emu)
3567 fetch_decode_modrm(emu);
3568 if (emu->cur_mod != 3)
3569 decode_rl_address(emu);
3573 x86emuOp_esc_coprocess_da(struct x86emu *emu)
3575 fetch_decode_modrm(emu);
3576 if (emu->cur_mod != 3)
3577 decode_rl_address(emu);
3581 x86emuOp_esc_coprocess_db(struct x86emu *emu)
3583 fetch_decode_modrm(emu);
3584 if (emu->cur_mod != 3)
3585 decode_rl_address(emu);
3589 x86emuOp_esc_coprocess_dc(struct x86emu *emu)
3591 fetch_decode_modrm(emu);
3592 if (emu->cur_mod != 3)
3593 decode_rl_address(emu);
3597 x86emuOp_esc_coprocess_dd(struct x86emu *emu)
3599 fetch_decode_modrm(emu);
3600 if (emu->cur_mod != 3)
3601 decode_rl_address(emu);
3605 x86emuOp_esc_coprocess_de(struct x86emu *emu)
3607 fetch_decode_modrm(emu);
3608 if (emu->cur_mod != 3)
3609 decode_rl_address(emu);
3613 x86emuOp_esc_coprocess_df(struct x86emu *emu)
3615 fetch_decode_modrm(emu);
3616 if (emu->cur_mod != 3)
3617 decode_rl_address(emu);
3623 * Handles opcode 0xe0
3626 x86emuOp_loopne(struct x86emu *emu)
3630 ip = (int8_t) fetch_byte_imm(emu);
3631 ip += (int16_t) emu->x86.R_IP;
3633 if (emu->x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */
3639 * Handles opcode 0xe1
3642 x86emuOp_loope(struct x86emu *emu)
3646 ip = (int8_t) fetch_byte_imm(emu);
3647 ip += (int16_t) emu->x86.R_IP;
3649 if (emu->x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */
3655 * Handles opcode 0xe2
3658 x86emuOp_loop(struct x86emu *emu)
3662 ip = (int8_t) fetch_byte_imm(emu);
3663 ip += (int16_t) emu->x86.R_IP;
3665 if (emu->x86.R_CX != 0)
3671 * Handles opcode 0xe3
3674 x86emuOp_jcxz(struct x86emu *emu)
3679 /* jump to byte offset if overflow flag is set */
3680 offset = (int8_t) fetch_byte_imm(emu);
3681 target = (uint16_t) (emu->x86.R_IP + offset);
3682 if (emu->x86.R_CX == 0)
3683 emu->x86.R_IP = target;
3688 * Handles opcode 0xe4
3691 x86emuOp_in_byte_AL_IMM(struct x86emu *emu)
3695 port = (uint8_t) fetch_byte_imm(emu);
3696 emu->x86.R_AL = (*emu->emu_inb) (emu, port);
3701 * Handles opcode 0xe5
3704 x86emuOp_in_word_AX_IMM(struct x86emu *emu)
3708 port = (uint8_t) fetch_byte_imm(emu);
3709 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3710 emu->x86.R_EAX = (*emu->emu_inl) (emu, port);
3712 emu->x86.R_AX = (*emu->emu_inw) (emu, port);
3718 * Handles opcode 0xe6
3721 x86emuOp_out_byte_IMM_AL(struct x86emu *emu)
3725 port = (uint8_t) fetch_byte_imm(emu);
3726 (*emu->emu_outb) (emu, port, emu->x86.R_AL);
3731 * Handles opcode 0xe7
3734 x86emuOp_out_word_IMM_AX(struct x86emu *emu)
3738 port = (uint8_t) fetch_byte_imm(emu);
3739 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3740 (*emu->emu_outl) (emu, port, emu->x86.R_EAX);
3742 (*emu->emu_outw) (emu, port, emu->x86.R_AX);
3748 * Handles opcode 0xe8
3751 x86emuOp_call_near_IMM(struct x86emu *emu)
3755 ip = (int16_t) fetch_word_imm(emu);
3756 ip += (int16_t) emu->x86.R_IP; /* CHECK SIGN */
3757 push_word(emu, emu->x86.R_IP);
3763 * Handles opcode 0xe9
3766 x86emuOp_jump_near_IMM(struct x86emu *emu)
3770 ip = (int16_t) fetch_word_imm(emu);
3771 ip += (int16_t) emu->x86.R_IP;
3772 emu->x86.R_IP = (uint16_t) ip;
3777 * Handles opcode 0xea
3780 x86emuOp_jump_far_IMM(struct x86emu *emu)
3784 ip = fetch_word_imm(emu);
3785 cs = fetch_word_imm(emu);
3792 * Handles opcode 0xeb
3795 x86emuOp_jump_byte_IMM(struct x86emu *emu)
3800 offset = (int8_t) fetch_byte_imm(emu);
3801 target = (uint16_t) (emu->x86.R_IP + offset);
3802 emu->x86.R_IP = target;
3807 * Handles opcode 0xec
3810 x86emuOp_in_byte_AL_DX(struct x86emu *emu)
3812 emu->x86.R_AL = (*emu->emu_inb) (emu, emu->x86.R_DX);
3817 * Handles opcode 0xed
3820 x86emuOp_in_word_AX_DX(struct x86emu *emu)
3822 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3823 emu->x86.R_EAX = (*emu->emu_inl) (emu, emu->x86.R_DX);
3825 emu->x86.R_AX = (*emu->emu_inw) (emu, emu->x86.R_DX);
3831 * Handles opcode 0xee
3834 x86emuOp_out_byte_DX_AL(struct x86emu *emu)
3836 (*emu->emu_outb) (emu, emu->x86.R_DX, emu->x86.R_AL);
3841 * Handles opcode 0xef
3844 x86emuOp_out_word_DX_AX(struct x86emu *emu)
3846 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3847 (*emu->emu_outl) (emu, emu->x86.R_DX, emu->x86.R_EAX);
3849 (*emu->emu_outw) (emu, emu->x86.R_DX, emu->x86.R_AX);
3855 * Handles opcode 0xf0
3858 x86emuOp_lock(struct x86emu *emu)
3861 /*opcode 0xf1 ILLEGAL OPERATION */
3866 * Handles opcode 0xf5
3869 x86emuOp_cmc(struct x86emu *emu)
3871 if (ACCESS_FLAG(F_CF))
3879 * Handles opcode 0xf6
3882 x86emuOp_opcF6_byte_RM(struct x86emu *emu)
3884 uint8_t destval, srcval;
3886 /* long, drawn out code follows. Double switch for a total of 32
3888 fetch_decode_modrm(emu);
3889 if (emu->cur_rh == 1)
3890 x86emu_halt_sys(emu);
3892 if (emu->cur_rh == 0) {
3893 destval = decode_and_fetch_byte_imm8(emu, &srcval);
3894 test_byte(emu, destval, srcval);
3897 destval = decode_and_fetch_byte(emu);
3898 switch (emu->cur_rh) {
3901 write_back_byte(emu, destval);
3904 destval = neg_byte(emu, destval);
3905 write_back_byte(emu, destval);
3908 mul_byte(emu, destval);
3911 imul_byte(emu, destval);
3914 div_byte(emu, destval);
3917 idiv_byte(emu, destval);
3924 * Handles opcode 0xf7
3927 x86emuOp32_opcF7_word_RM(struct x86emu *emu)
3929 uint32_t destval, srcval;
3931 /* long, drawn out code follows. Double switch for a total of 32
3933 fetch_decode_modrm(emu);
3934 if (emu->cur_rh == 1)
3935 x86emu_halt_sys(emu);
3937 if (emu->cur_rh == 0) {
3938 if (emu->cur_mod != 3) {
3939 uint32_t destoffset;
3941 destoffset = decode_rl_address(emu);
3942 srcval = fetch_long_imm(emu);
3943 destval = fetch_data_long(emu, destoffset);
3945 srcval = fetch_long_imm(emu);
3946 destval = *decode_rl_long_register(emu);
3948 test_long(emu, destval, srcval);
3951 destval = decode_and_fetch_long(emu);
3952 switch (emu->cur_rh) {
3955 write_back_long(emu, destval);
3958 destval = neg_long(emu, destval);
3959 write_back_long(emu, destval);
3962 mul_long(emu, destval);
3965 imul_long(emu, destval);
3968 div_long(emu, destval);
3971 idiv_long(emu, destval);
3976 x86emuOp16_opcF7_word_RM(struct x86emu *emu)
3978 uint16_t destval, srcval;
3980 /* long, drawn out code follows. Double switch for a total of 32
3982 fetch_decode_modrm(emu);
3983 if (emu->cur_rh == 1)
3984 x86emu_halt_sys(emu);
3986 if (emu->cur_rh == 0) {
3987 if (emu->cur_mod != 3) {
3988 uint32_t destoffset;
3990 destoffset = decode_rl_address(emu);
3991 srcval = fetch_word_imm(emu);
3992 destval = fetch_data_word(emu, destoffset);
3994 srcval = fetch_word_imm(emu);
3995 destval = *decode_rl_word_register(emu);
3997 test_word(emu, destval, srcval);
4000 destval = decode_and_fetch_word(emu);
4001 switch (emu->cur_rh) {
4004 write_back_word(emu, destval);
4007 destval = neg_word(emu, destval);
4008 write_back_word(emu, destval);
4011 mul_word(emu, destval);
4014 imul_word(emu, destval);
4017 div_word(emu, destval);
4020 idiv_word(emu, destval);
4025 x86emuOp_opcF7_word_RM(struct x86emu *emu)
4027 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
4028 x86emuOp32_opcF7_word_RM(emu);
4030 x86emuOp16_opcF7_word_RM(emu);
4035 * Handles opcode 0xfe
4038 x86emuOp_opcFE_byte_RM(struct x86emu *emu)
4041 uint32_t destoffset;
4044 /* Yet another special case instruction. */
4045 fetch_decode_modrm(emu);
4046 if (emu->cur_mod != 3) {
4047 destoffset = decode_rl_address(emu);
4048 switch (emu->cur_rh) {
4049 case 0: /* inc word ptr ... */
4050 destval = fetch_data_byte(emu, destoffset);
4051 destval = inc_byte(emu, destval);
4052 store_data_byte(emu, destoffset, destval);
4054 case 1: /* dec word ptr ... */
4055 destval = fetch_data_byte(emu, destoffset);
4056 destval = dec_byte(emu, destval);
4057 store_data_byte(emu, destoffset, destval);
4061 destreg = decode_rl_byte_register(emu);
4062 switch (emu->cur_rh) {
4064 *destreg = inc_byte(emu, *destreg);
4067 *destreg = dec_byte(emu, *destreg);
4075 * Handles opcode 0xff
4078 x86emuOp32_opcFF_word_RM(struct x86emu *emu)
4080 uint32_t destoffset = 0;
4081 uint32_t destval, *destreg;
4083 if (emu->cur_mod != 3) {
4084 destoffset = decode_rl_address(emu);
4085 destval = fetch_data_long(emu, destoffset);
4086 switch (emu->cur_rh) {
4087 case 0: /* inc word ptr ... */
4088 destval = inc_long(emu, destval);
4089 store_data_long(emu, destoffset, destval);
4091 case 1: /* dec word ptr ... */
4092 destval = dec_long(emu, destval);
4093 store_data_long(emu, destoffset, destval);
4095 case 6: /* push word ptr ... */
4096 push_long(emu, destval);
4100 destreg = decode_rl_long_register(emu);
4101 switch (emu->cur_rh) {
4103 *destreg = inc_long(emu, *destreg);
4106 *destreg = dec_long(emu, *destreg);
4109 push_long(emu, *destreg);
4116 x86emuOp16_opcFF_word_RM(struct x86emu *emu)
4118 uint32_t destoffset = 0;
4122 if (emu->cur_mod != 3) {
4123 destoffset = decode_rl_address(emu);
4124 destval = fetch_data_word(emu, destoffset);
4125 switch (emu->cur_rh) {
4127 destval = inc_word(emu, destval);
4128 store_data_word(emu, destoffset, destval);
4130 case 1: /* dec word ptr ... */
4131 destval = dec_word(emu, destval);
4132 store_data_word(emu, destoffset, destval);
4134 case 6: /* push word ptr ... */
4135 push_word(emu, destval);
4139 destreg = decode_rl_word_register(emu);
4140 switch (emu->cur_rh) {
4142 *destreg = inc_word(emu, *destreg);
4145 *destreg = dec_word(emu, *destreg);
4148 push_word(emu, *destreg);
4155 x86emuOp_opcFF_word_RM(struct x86emu *emu)
4157 uint32_t destoffset = 0;
4158 uint16_t destval, destval2;
4160 /* Yet another special case instruction. */
4161 fetch_decode_modrm(emu);
4162 if ((emu->cur_mod == 3 && (emu->cur_rh == 3 || emu->cur_rh == 5)) ||
4164 x86emu_halt_sys(emu);
4165 if (emu->cur_rh == 0 || emu->cur_rh == 1 || emu->cur_rh == 6) {
4166 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
4167 x86emuOp32_opcFF_word_RM(emu);
4169 x86emuOp16_opcFF_word_RM(emu);
4173 if (emu->cur_mod != 3) {
4174 destoffset = decode_rl_address(emu);
4175 destval = fetch_data_word(emu, destoffset);
4176 switch (emu->cur_rh) {
4177 case 3: /* call far ptr ... */
4178 destval2 = fetch_data_word(emu, destoffset + 2);
4179 push_word(emu, emu->x86.R_CS);
4180 emu->x86.R_CS = destval2;
4181 push_word(emu, emu->x86.R_IP);
4182 emu->x86.R_IP = destval;
4184 case 5: /* jmp far ptr ... */
4185 destval2 = fetch_data_word(emu, destoffset + 2);
4186 emu->x86.R_IP = destval;
4187 emu->x86.R_CS = destval2;
4191 destval = *decode_rl_word_register(emu);
4194 switch (emu->cur_rh) {
4195 case 2: /* call word ptr */
4196 push_word(emu, emu->x86.R_IP);
4197 emu->x86.R_IP = destval;
4200 emu->x86.R_IP = destval;
4206 * * Single byte operation code table:
4209 x86emu_exec_one_byte(struct x86emu * emu)
4213 op1 = fetch_byte_imm(emu);
4217 common_binop_byte_rm_r(emu, add_byte);
4220 common_binop_word_long_rm_r(emu, add_word, add_long);
4223 common_binop_byte_r_rm(emu, add_byte);
4226 common_binop_word_long_r_rm(emu, add_word, add_long);
4229 common_binop_byte_imm(emu, add_byte);
4232 common_binop_word_long_imm(emu, add_word, add_long);
4235 push_word(emu, emu->x86.R_ES);
4238 emu->x86.R_ES = pop_word(emu);
4242 common_binop_byte_rm_r(emu, or_byte);
4245 common_binop_word_long_rm_r(emu, or_word, or_long);
4248 common_binop_byte_r_rm(emu, or_byte);
4251 common_binop_word_long_r_rm(emu, or_word, or_long);
4254 common_binop_byte_imm(emu, or_byte);
4257 common_binop_word_long_imm(emu, or_word, or_long);
4260 push_word(emu, emu->x86.R_CS);
4263 x86emu_exec_two_byte(emu);
4267 common_binop_byte_rm_r(emu, adc_byte);
4270 common_binop_word_long_rm_r(emu, adc_word, adc_long);
4273 common_binop_byte_r_rm(emu, adc_byte);
4276 common_binop_word_long_r_rm(emu, adc_word, adc_long);
4279 common_binop_byte_imm(emu, adc_byte);
4282 common_binop_word_long_imm(emu, adc_word, adc_long);
4285 push_word(emu, emu->x86.R_SS);
4288 emu->x86.R_SS = pop_word(emu);
4292 common_binop_byte_rm_r(emu, sbb_byte);
4295 common_binop_word_long_rm_r(emu, sbb_word, sbb_long);
4298 common_binop_byte_r_rm(emu, sbb_byte);
4301 common_binop_word_long_r_rm(emu, sbb_word, sbb_long);
4304 common_binop_byte_imm(emu, sbb_byte);
4307 common_binop_word_long_imm(emu, sbb_word, sbb_long);
4310 push_word(emu, emu->x86.R_DS);
4313 emu->x86.R_DS = pop_word(emu);
4317 common_binop_byte_rm_r(emu, and_byte);
4320 common_binop_word_long_rm_r(emu, and_word, and_long);
4323 common_binop_byte_r_rm(emu, and_byte);
4326 common_binop_word_long_r_rm(emu, and_word, and_long);
4329 common_binop_byte_imm(emu, and_byte);
4332 common_binop_word_long_imm(emu, and_word, and_long);
4335 emu->x86.mode |= SYSMODE_SEGOVR_ES;
4338 emu->x86.R_AL = daa_byte(emu, emu->x86.R_AL);
4342 common_binop_byte_rm_r(emu, sub_byte);
4345 common_binop_word_long_rm_r(emu, sub_word, sub_long);
4348 common_binop_byte_r_rm(emu, sub_byte);
4351 common_binop_word_long_r_rm(emu, sub_word, sub_long);
4354 common_binop_byte_imm(emu, sub_byte);
4357 common_binop_word_long_imm(emu, sub_word, sub_long);
4360 emu->x86.mode |= SYSMODE_SEGOVR_CS;
4363 emu->x86.R_AL = das_byte(emu, emu->x86.R_AL);
4367 common_binop_byte_rm_r(emu, xor_byte);
4370 common_binop_word_long_rm_r(emu, xor_word, xor_long);
4373 common_binop_byte_r_rm(emu, xor_byte);
4376 common_binop_word_long_r_rm(emu, xor_word, xor_long);
4379 common_binop_byte_imm(emu, xor_byte);
4382 common_binop_word_long_imm(emu, xor_word, xor_long);
4385 emu->x86.mode |= SYSMODE_SEGOVR_SS;
4388 emu->x86.R_AX = aaa_word(emu, emu->x86.R_AX);
4392 common_binop_ns_byte_rm_r(emu, cmp_byte_no_return);
4395 common_binop_ns_word_long_rm_r(emu, cmp_word_no_return,
4396 cmp_long_no_return);
4399 x86emuOp_cmp_byte_R_RM(emu);
4402 x86emuOp_cmp_word_R_RM(emu);
4405 x86emuOp_cmp_byte_AL_IMM(emu);
4408 x86emuOp_cmp_word_AX_IMM(emu);
4411 emu->x86.mode |= SYSMODE_SEGOVR_DS;
4414 emu->x86.R_AX = aas_word(emu, emu->x86.R_AX);
4418 common_inc_word_long(emu, &emu->x86.register_a);
4421 common_inc_word_long(emu, &emu->x86.register_c);
4424 common_inc_word_long(emu, &emu->x86.register_d);
4427 common_inc_word_long(emu, &emu->x86.register_b);
4430 common_inc_word_long(emu, &emu->x86.register_sp);
4433 common_inc_word_long(emu, &emu->x86.register_bp);
4436 common_inc_word_long(emu, &emu->x86.register_si);
4439 common_inc_word_long(emu, &emu->x86.register_di);
4443 common_dec_word_long(emu, &emu->x86.register_a);
4446 common_dec_word_long(emu, &emu->x86.register_c);
4449 common_dec_word_long(emu, &emu->x86.register_d);
4452 common_dec_word_long(emu, &emu->x86.register_b);
4455 common_dec_word_long(emu, &emu->x86.register_sp);
4458 common_dec_word_long(emu, &emu->x86.register_bp);
4461 common_dec_word_long(emu, &emu->x86.register_si);
4464 common_dec_word_long(emu, &emu->x86.register_di);
4468 common_push_word_long(emu, &emu->x86.register_a);
4471 common_push_word_long(emu, &emu->x86.register_c);
4474 common_push_word_long(emu, &emu->x86.register_d);
4477 common_push_word_long(emu, &emu->x86.register_b);
4480 common_push_word_long(emu, &emu->x86.register_sp);
4483 common_push_word_long(emu, &emu->x86.register_bp);
4486 common_push_word_long(emu, &emu->x86.register_si);
4489 common_push_word_long(emu, &emu->x86.register_di);
4493 common_pop_word_long(emu, &emu->x86.register_a);
4496 common_pop_word_long(emu, &emu->x86.register_c);
4499 common_pop_word_long(emu, &emu->x86.register_d);
4502 common_pop_word_long(emu, &emu->x86.register_b);
4505 common_pop_word_long(emu, &emu->x86.register_sp);
4508 common_pop_word_long(emu, &emu->x86.register_bp);
4511 common_pop_word_long(emu, &emu->x86.register_si);
4514 common_pop_word_long(emu, &emu->x86.register_di);
4518 x86emuOp_push_all(emu);
4521 x86emuOp_pop_all(emu);
4526 emu->x86.mode |= SYSMODE_SEGOVR_FS;
4529 emu->x86.mode |= SYSMODE_SEGOVR_GS;
4532 emu->x86.mode |= SYSMODE_PREFIX_DATA;
4535 emu->x86.mode |= SYSMODE_PREFIX_ADDR;
4539 x86emuOp_push_word_IMM(emu);
4542 common_imul_imm(emu, 0);
4545 x86emuOp_push_byte_IMM(emu);
4548 common_imul_imm(emu, 1);
4554 x86emuOp_ins_word(emu);
4560 x86emuOp_outs_word(emu);
4564 common_jmp_near(emu, ACCESS_FLAG(F_OF));
4567 common_jmp_near(emu, !ACCESS_FLAG(F_OF));
4570 common_jmp_near(emu, ACCESS_FLAG(F_CF));
4573 common_jmp_near(emu, !ACCESS_FLAG(F_CF));
4576 common_jmp_near(emu, ACCESS_FLAG(F_ZF));
4579 common_jmp_near(emu, !ACCESS_FLAG(F_ZF));
4582 common_jmp_near(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
4585 common_jmp_near(emu, !ACCESS_FLAG(F_CF) && !ACCESS_FLAG(F_ZF));
4589 common_jmp_near(emu, ACCESS_FLAG(F_SF));
4592 common_jmp_near(emu, !ACCESS_FLAG(F_SF));
4595 common_jmp_near(emu, ACCESS_FLAG(F_PF));
4598 common_jmp_near(emu, !ACCESS_FLAG(F_PF));
4601 x86emuOp_jump_near_L(emu);
4604 x86emuOp_jump_near_NL(emu);
4607 x86emuOp_jump_near_LE(emu);
4610 x86emuOp_jump_near_NLE(emu);
4614 x86emuOp_opc80_byte_RM_IMM(emu);
4617 x86emuOp_opc81_word_RM_IMM(emu);
4620 x86emuOp_opc82_byte_RM_IMM(emu);
4623 x86emuOp_opc83_word_RM_IMM(emu);
4626 common_binop_ns_byte_rm_r(emu, test_byte);
4629 common_binop_ns_word_long_rm_r(emu, test_word, test_long);
4632 x86emuOp_xchg_byte_RM_R(emu);
4635 x86emuOp_xchg_word_RM_R(emu);
4639 x86emuOp_mov_byte_RM_R(emu);
4642 x86emuOp_mov_word_RM_R(emu);
4645 x86emuOp_mov_byte_R_RM(emu);
4648 x86emuOp_mov_word_R_RM(emu);
4651 x86emuOp_mov_word_RM_SR(emu);
4654 x86emuOp_lea_word_R_M(emu);
4657 x86emuOp_mov_word_SR_RM(emu);
4660 x86emuOp_pop_RM(emu);
4667 x86emuOp_xchg_word_AX_CX(emu);
4670 x86emuOp_xchg_word_AX_DX(emu);
4673 x86emuOp_xchg_word_AX_BX(emu);
4676 x86emuOp_xchg_word_AX_SP(emu);
4679 x86emuOp_xchg_word_AX_BP(emu);
4682 x86emuOp_xchg_word_AX_SI(emu);
4685 x86emuOp_xchg_word_AX_DI(emu);
4695 x86emuOp_call_far_IMM(emu);
4701 x86emuOp_pushf_word(emu);
4704 x86emuOp_popf_word(emu);
4714 x86emuOp_mov_AL_M_IMM(emu);
4717 x86emuOp_mov_AX_M_IMM(emu);
4720 x86emuOp_mov_M_AL_IMM(emu);
4723 x86emuOp_mov_M_AX_IMM(emu);
4726 x86emuOp_movs_byte(emu);
4729 x86emuOp_movs_word(emu);
4732 x86emuOp_cmps_byte(emu);
4735 x86emuOp_cmps_word(emu);
4739 test_byte(emu, emu->x86.R_AL, fetch_byte_imm(emu));
4742 x86emuOp_test_AX_IMM(emu);
4745 x86emuOp_stos_byte(emu);
4748 x86emuOp_stos_word(emu);
4751 x86emuOp_lods_byte(emu);
4754 x86emuOp_lods_word(emu);
4757 x86emuOp_scas_byte(emu);
4760 x86emuOp_scas_word(emu);
4764 emu->x86.R_AL = fetch_byte_imm(emu);
4767 emu->x86.R_CL = fetch_byte_imm(emu);
4770 emu->x86.R_DL = fetch_byte_imm(emu);
4773 emu->x86.R_BL = fetch_byte_imm(emu);
4776 emu->x86.R_AH = fetch_byte_imm(emu);
4779 emu->x86.R_CH = fetch_byte_imm(emu);
4782 emu->x86.R_DH = fetch_byte_imm(emu);
4785 emu->x86.R_BH = fetch_byte_imm(emu);
4789 x86emuOp_mov_word_AX_IMM(emu);
4792 x86emuOp_mov_word_CX_IMM(emu);
4795 x86emuOp_mov_word_DX_IMM(emu);
4798 x86emuOp_mov_word_BX_IMM(emu);
4802 x86emuOp_mov_word_SP_IMM(emu);
4805 x86emuOp_mov_word_BP_IMM(emu);
4808 x86emuOp_mov_word_SI_IMM(emu);
4811 x86emuOp_mov_word_DI_IMM(emu);
4815 x86emuOp_opcC0_byte_RM_MEM(emu);
4818 x86emuOp_opcC1_word_RM_MEM(emu);
4821 x86emuOp_ret_near_IMM(emu);
4824 emu->x86.R_IP = pop_word(emu);
4827 common_load_far_pointer(emu, &emu->x86.R_ES);
4830 common_load_far_pointer(emu, &emu->x86.R_DS);
4833 x86emuOp_mov_byte_RM_IMM(emu);
4836 x86emuOp_mov_word_RM_IMM(emu);
4839 x86emuOp_enter(emu);
4842 x86emuOp_leave(emu);
4845 x86emuOp_ret_far_IMM(emu);
4848 x86emuOp_ret_far(emu);
4854 x86emuOp_int_IMM(emu);
4864 x86emuOp_opcD0_byte_RM_1(emu);
4867 x86emuOp_opcD1_word_RM_1(emu);
4870 x86emuOp_opcD2_byte_RM_CL(emu);
4873 x86emuOp_opcD3_word_RM_CL(emu);
4881 /* 0xd6 Undocumented SETALC instruction */
4886 x86emuOp_esc_coprocess_d8(emu);
4889 x86emuOp_esc_coprocess_d9(emu);
4892 x86emuOp_esc_coprocess_da(emu);
4895 x86emuOp_esc_coprocess_db(emu);
4898 x86emuOp_esc_coprocess_dc(emu);
4901 x86emuOp_esc_coprocess_dd(emu);
4904 x86emuOp_esc_coprocess_de(emu);
4907 x86emuOp_esc_coprocess_df(emu);
4911 x86emuOp_loopne(emu);
4914 x86emuOp_loope(emu);
4923 x86emuOp_in_byte_AL_IMM(emu);
4926 x86emuOp_in_word_AX_IMM(emu);
4929 x86emuOp_out_byte_IMM_AL(emu);
4932 x86emuOp_out_word_IMM_AX(emu);
4936 x86emuOp_call_near_IMM(emu);
4939 x86emuOp_jump_near_IMM(emu);
4942 x86emuOp_jump_far_IMM(emu);
4945 x86emuOp_jump_byte_IMM(emu);
4948 x86emuOp_in_byte_AL_DX(emu);
4951 x86emuOp_in_word_AX_DX(emu);
4954 x86emuOp_out_byte_DX_AL(emu);
4957 x86emuOp_out_word_DX_AX(emu);
4964 emu->x86.mode |= SYSMODE_PREFIX_REPNE;
4967 emu->x86.mode |= SYSMODE_PREFIX_REPE;
4970 x86emu_halt_sys(emu);
4976 x86emuOp_opcF6_byte_RM(emu);
4979 x86emuOp_opcF7_word_RM(emu);
5001 x86emuOp_opcFE_byte_RM(emu);
5004 x86emuOp_opcFF_word_RM(emu);
5007 x86emu_halt_sys(emu);
5010 if (op1 != 0x26 && op1 != 0x2e && op1 != 0x36 && op1 != 0x3e &&
5012 emu->x86.mode &= ~SYSMODE_CLRMASK;
5016 common_jmp_long(struct x86emu *emu, int cond)
5020 target = (int16_t) fetch_word_imm(emu);
5021 target += (int16_t) emu->x86.R_IP;
5023 emu->x86.R_IP = (uint16_t) target;
5027 common_set_byte(struct x86emu *emu, int cond)
5029 uint32_t destoffset;
5030 uint8_t *destreg, destval;
5032 fetch_decode_modrm(emu);
5033 destval = cond ? 0x01 : 0x00;
5034 if (emu->cur_mod != 3) {
5035 destoffset = decode_rl_address(emu);
5036 store_data_byte(emu, destoffset, destval);
5038 destreg = decode_rl_byte_register(emu);
5044 common_bitstring32(struct x86emu *emu, int op)
5047 uint32_t srcval, *shiftreg, mask;
5049 fetch_decode_modrm(emu);
5050 shiftreg = decode_rh_long_register(emu);
5051 srcval = decode_and_fetch_long_disp(emu, (int16_t) *shiftreg >> 5);
5052 bit = *shiftreg & 0x1F;
5054 CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5060 write_back_long(emu, srcval | mask);
5063 write_back_long(emu, srcval & ~mask);
5066 write_back_long(emu, srcval ^ mask);
5072 common_bitstring16(struct x86emu *emu, int op)
5075 uint16_t srcval, *shiftreg, mask;
5077 fetch_decode_modrm(emu);
5078 shiftreg = decode_rh_word_register(emu);
5079 srcval = decode_and_fetch_word_disp(emu, (int16_t) *shiftreg >> 4);
5080 bit = *shiftreg & 0xF;
5082 CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5088 write_back_word(emu, srcval | mask);
5091 write_back_word(emu, srcval & ~mask);
5094 write_back_word(emu, srcval ^ mask);
5100 common_bitstring(struct x86emu *emu, int op)
5102 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5103 common_bitstring32(emu, op);
5105 common_bitstring16(emu, op);
5109 common_bitsearch32(struct x86emu *emu, int diff)
5111 uint32_t srcval, *dstreg;
5113 fetch_decode_modrm(emu);
5114 dstreg = decode_rh_long_register(emu);
5115 srcval = decode_and_fetch_long(emu);
5116 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
5117 for (*dstreg = 0; *dstreg < 32; *dstreg += diff) {
5118 if ((srcval >> *dstreg) & 1)
5124 common_bitsearch16(struct x86emu *emu, int diff)
5126 uint16_t srcval, *dstreg;
5128 fetch_decode_modrm(emu);
5129 dstreg = decode_rh_word_register(emu);
5130 srcval = decode_and_fetch_word(emu);
5131 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
5132 for (*dstreg = 0; *dstreg < 16; *dstreg += diff) {
5133 if ((srcval >> *dstreg) & 1)
5139 common_bitsearch(struct x86emu *emu, int diff)
5141 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5142 common_bitsearch32(emu, diff);
5144 common_bitsearch16(emu, diff);
5148 common_shift32(struct x86emu *emu, int shift_left, int use_cl)
5151 uint32_t destval, *shiftreg;
5153 fetch_decode_modrm(emu);
5154 shiftreg = decode_rh_long_register(emu);
5156 destval = decode_and_fetch_long(emu);
5157 shift = emu->x86.R_CL;
5159 destval = decode_and_fetch_long_imm8(emu, &shift);
5162 destval = shld_long(emu, destval, *shiftreg, shift);
5164 destval = shrd_long(emu, destval, *shiftreg, shift);
5165 write_back_long(emu, destval);
5169 common_shift16(struct x86emu *emu, int shift_left, int use_cl)
5172 uint16_t destval, *shiftreg;
5174 fetch_decode_modrm(emu);
5175 shiftreg = decode_rh_word_register(emu);
5177 destval = decode_and_fetch_word(emu);
5178 shift = emu->x86.R_CL;
5180 destval = decode_and_fetch_word_imm8(emu, &shift);
5183 destval = shld_word(emu, destval, *shiftreg, shift);
5185 destval = shrd_word(emu, destval, *shiftreg, shift);
5186 write_back_word(emu, destval);
5190 common_shift(struct x86emu *emu, int shift_left, int use_cl)
5192 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5193 common_shift32(emu, shift_left, use_cl);
5195 common_shift16(emu, shift_left, use_cl);
5201 #define xorl(a,b) ((a) && !(b)) || (!(a) && (b))
5206 * Handles opcode 0x0f,0x31
5209 x86emuOp2_rdtsc(struct x86emu *emu)
5211 emu->x86.R_EAX = emu->cur_cycles & 0xffffffff;
5212 emu->x86.R_EDX = emu->cur_cycles >> 32;
5217 * Handles opcode 0x0f,0xa0
5220 x86emuOp2_push_FS(struct x86emu *emu)
5222 push_word(emu, emu->x86.R_FS);
5227 * Handles opcode 0x0f,0xa1
5230 x86emuOp2_pop_FS(struct x86emu *emu)
5232 emu->x86.R_FS = pop_word(emu);
5237 * Handles opcode 0x0f,0xa1
5239 #if defined(__i386__) || defined(__amd64__)
5241 hw_cpuid(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d)
5243 __asm__ __volatile__("cpuid"
5244 : "=a" (*a), "=b" (*b),
5245 "=c" (*c), "=d" (*d)
5246 : "a" (*a), "c" (*c)
5251 x86emuOp2_cpuid(struct x86emu *emu)
5253 #if defined(__i386__) || defined(__amd64__)
5254 hw_cpuid(&emu->x86.R_EAX, &emu->x86.R_EBX, &emu->x86.R_ECX,
5257 switch (emu->x86.R_EAX) {
5260 #if !defined(__i386__) && !defined(__amd64__)
5261 /* "GenuineIntel" */
5262 emu->x86.R_EBX = 0x756e6547;
5263 emu->x86.R_EDX = 0x49656e69;
5264 emu->x86.R_ECX = 0x6c65746e;
5268 #if !defined(__i386__) && !defined(__amd64__)
5269 emu->x86.R_EAX = 0x00000480;
5270 emu->x86.R_EBX = emu->x86.R_ECX = 0;
5271 emu->x86.R_EDX = 0x00000002;
5273 emu->x86.R_EDX &= 0x00000012;
5277 emu->x86.R_EAX = emu->x86.R_EBX = emu->x86.R_ECX =
5285 * Handles opcode 0x0f,0xa3
5288 x86emuOp2_bt_R(struct x86emu *emu)
5290 common_bitstring(emu, 0);
5295 * Handles opcode 0x0f,0xa4
5298 x86emuOp2_shld_IMM(struct x86emu *emu)
5300 common_shift(emu, 1, 0);
5305 * Handles opcode 0x0f,0xa5
5308 x86emuOp2_shld_CL(struct x86emu *emu)
5310 common_shift(emu, 1, 1);
5315 * Handles opcode 0x0f,0xa8
5318 x86emuOp2_push_GS(struct x86emu *emu)
5320 push_word(emu, emu->x86.R_GS);
5325 * Handles opcode 0x0f,0xa9
5328 x86emuOp2_pop_GS(struct x86emu *emu)
5330 emu->x86.R_GS = pop_word(emu);
5335 * Handles opcode 0x0f,0xab
5338 x86emuOp2_bts_R(struct x86emu *emu)
5340 common_bitstring(emu, 1);
5345 * Handles opcode 0x0f,0xac
5348 x86emuOp2_shrd_IMM(struct x86emu *emu)
5350 common_shift(emu, 0, 0);
5355 * Handles opcode 0x0f,0xad
5358 x86emuOp2_shrd_CL(struct x86emu *emu)
5360 common_shift(emu, 0, 1);
5365 * Handles opcode 0x0f,0xaf
5368 x86emuOp2_32_imul_R_RM(struct x86emu *emu)
5370 uint32_t *destreg, srcval;
5373 fetch_decode_modrm(emu);
5374 destreg = decode_rh_long_register(emu);
5375 srcval = decode_and_fetch_long(emu);
5376 res = (int32_t) *destreg * (int32_t)srcval;
5377 if (res > 0xffffffff) {
5384 *destreg = (uint32_t) res;
5388 x86emuOp2_16_imul_R_RM(struct x86emu *emu)
5390 uint16_t *destreg, srcval;
5393 fetch_decode_modrm(emu);
5394 destreg = decode_rh_word_register(emu);
5395 srcval = decode_and_fetch_word(emu);
5396 res = (int16_t) * destreg * (int16_t)srcval;
5404 *destreg = (uint16_t) res;
5408 x86emuOp2_imul_R_RM(struct x86emu *emu)
5410 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5411 x86emuOp2_32_imul_R_RM(emu);
5413 x86emuOp2_16_imul_R_RM(emu);
5418 * Handles opcode 0x0f,0xb2
5421 x86emuOp2_lss_R_IMM(struct x86emu *emu)
5423 common_load_far_pointer(emu, &emu->x86.R_SS);
5428 * Handles opcode 0x0f,0xb3
5431 x86emuOp2_btr_R(struct x86emu *emu)
5433 common_bitstring(emu, 2);
5438 * Handles opcode 0x0f,0xb4
5441 x86emuOp2_lfs_R_IMM(struct x86emu *emu)
5443 common_load_far_pointer(emu, &emu->x86.R_FS);
5448 * Handles opcode 0x0f,0xb5
5451 x86emuOp2_lgs_R_IMM(struct x86emu *emu)
5453 common_load_far_pointer(emu, &emu->x86.R_GS);
5458 * Handles opcode 0x0f,0xb6
5461 x86emuOp2_32_movzx_byte_R_RM(struct x86emu *emu)
5465 fetch_decode_modrm(emu);
5466 destreg = decode_rh_long_register(emu);
5467 *destreg = decode_and_fetch_byte(emu);
5471 x86emuOp2_16_movzx_byte_R_RM(struct x86emu *emu)
5475 fetch_decode_modrm(emu);
5476 destreg = decode_rh_word_register(emu);
5477 *destreg = decode_and_fetch_byte(emu);
5481 x86emuOp2_movzx_byte_R_RM(struct x86emu *emu)
5483 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5484 x86emuOp2_32_movzx_byte_R_RM(emu);
5486 x86emuOp2_16_movzx_byte_R_RM(emu);
5491 * Handles opcode 0x0f,0xb7
5494 x86emuOp2_movzx_word_R_RM(struct x86emu *emu)
5498 fetch_decode_modrm(emu);
5499 destreg = decode_rh_long_register(emu);
5500 *destreg = decode_and_fetch_word(emu);
5505 * Handles opcode 0x0f,0xba
5508 x86emuOp2_32_btX_I(struct x86emu *emu)
5511 uint32_t srcval, mask;
5514 fetch_decode_modrm(emu);
5515 if (emu->cur_rh < 4)
5516 x86emu_halt_sys(emu);
5518 srcval = decode_and_fetch_long_imm8(emu, &shift);
5520 mask = (0x1 << bit);
5522 switch (emu->cur_rh) {
5524 write_back_long(emu, srcval | mask);
5527 write_back_long(emu, srcval & ~mask);
5530 write_back_long(emu, srcval ^ mask);
5533 CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5537 x86emuOp2_16_btX_I(struct x86emu *emu)
5541 uint16_t srcval, mask;
5544 fetch_decode_modrm(emu);
5545 if (emu->cur_rh < 4)
5546 x86emu_halt_sys(emu);
5548 srcval = decode_and_fetch_word_imm8(emu, &shift);
5550 mask = (0x1 << bit);
5551 switch (emu->cur_rh) {
5553 write_back_word(emu, srcval | mask);
5556 write_back_word(emu, srcval & ~mask);
5559 write_back_word(emu, srcval ^ mask);
5562 CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5566 x86emuOp2_btX_I(struct x86emu *emu)
5568 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5569 x86emuOp2_32_btX_I(emu);
5571 x86emuOp2_16_btX_I(emu);
5576 * Handles opcode 0x0f,0xbb
5579 x86emuOp2_btc_R(struct x86emu *emu)
5581 common_bitstring(emu, 3);
5586 * Handles opcode 0x0f,0xbc
5589 x86emuOp2_bsf(struct x86emu *emu)
5591 common_bitsearch(emu, +1);
5596 * Handles opcode 0x0f,0xbd
5599 x86emuOp2_bsr(struct x86emu *emu)
5601 common_bitsearch(emu, -1);
5606 * Handles opcode 0x0f,0xbe
5609 x86emuOp2_32_movsx_byte_R_RM(struct x86emu *emu)
5613 destreg = decode_rh_long_register(emu);
5614 *destreg = (int32_t)(int8_t)decode_and_fetch_byte(emu);
5618 x86emuOp2_16_movsx_byte_R_RM(struct x86emu *emu)
5622 fetch_decode_modrm(emu);
5623 destreg = decode_rh_word_register(emu);
5624 *destreg = (int16_t)(int8_t)decode_and_fetch_byte(emu);
5628 x86emuOp2_movsx_byte_R_RM(struct x86emu *emu)
5630 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5631 x86emuOp2_32_movsx_byte_R_RM(emu);
5633 x86emuOp2_16_movsx_byte_R_RM(emu);
5638 * Handles opcode 0x0f,0xbf
5641 x86emuOp2_movsx_word_R_RM(struct x86emu *emu)
5645 fetch_decode_modrm(emu);
5646 destreg = decode_rh_long_register(emu);
5647 *destreg = (int32_t)(int16_t)decode_and_fetch_word(emu);
5651 x86emu_exec_two_byte(struct x86emu * emu)
5655 op2 = fetch_byte_imm(emu);
5658 /* 0x00 Group F (ring 0 PM) */
5659 /* 0x01 Group G (ring 0 PM) */
5660 /* 0x02 lar (ring 0 PM) */
5661 /* 0x03 lsl (ring 0 PM) */
5662 /* 0x05 loadall (undocumented) */
5663 /* 0x06 clts (ring 0 PM) */
5664 /* 0x07 loadall (undocumented) */
5665 /* 0x08 invd (ring 0 PM) */
5666 /* 0x09 wbinvd (ring 0 PM) */
5668 /* 0x20 mov reg32(op2); break;creg (ring 0 PM) */
5669 /* 0x21 mov reg32(op2); break;dreg (ring 0 PM) */
5670 /* 0x22 mov creg(op2); break;reg32 (ring 0 PM) */
5671 /* 0x23 mov dreg(op2); break;reg32 (ring 0 PM) */
5672 /* 0x24 mov reg32(op2); break;treg (ring 0 PM) */
5673 /* 0x26 mov treg(op2); break;reg32 (ring 0 PM) */
5676 x86emuOp2_rdtsc(emu);
5680 common_jmp_long(emu, ACCESS_FLAG(F_OF));
5683 common_jmp_long(emu, !ACCESS_FLAG(F_OF));
5686 common_jmp_long(emu, ACCESS_FLAG(F_CF));
5689 common_jmp_long(emu, !ACCESS_FLAG(F_CF));
5692 common_jmp_long(emu, ACCESS_FLAG(F_ZF));
5695 common_jmp_long(emu, !ACCESS_FLAG(F_ZF));
5698 common_jmp_long(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
5701 common_jmp_long(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)));
5704 common_jmp_long(emu, ACCESS_FLAG(F_SF));
5707 common_jmp_long(emu, !ACCESS_FLAG(F_SF));
5710 common_jmp_long(emu, ACCESS_FLAG(F_PF));
5713 common_jmp_long(emu, !ACCESS_FLAG(F_PF));
5716 common_jmp_long(emu, xorl(ACCESS_FLAG(F_SF),
5717 ACCESS_FLAG(F_OF)));
5720 common_jmp_long(emu, !(xorl(ACCESS_FLAG(F_SF),
5721 ACCESS_FLAG(F_OF))));
5724 common_jmp_long(emu, (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF))
5725 || ACCESS_FLAG(F_ZF)));
5728 common_jmp_long(emu,
5729 !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
5730 ACCESS_FLAG(F_ZF)));
5734 common_set_byte(emu, ACCESS_FLAG(F_OF));
5737 common_set_byte(emu, !ACCESS_FLAG(F_OF));
5740 common_set_byte(emu, ACCESS_FLAG(F_CF));
5743 common_set_byte(emu, !ACCESS_FLAG(F_CF));
5746 common_set_byte(emu, ACCESS_FLAG(F_ZF));
5749 common_set_byte(emu, !ACCESS_FLAG(F_ZF));
5752 common_set_byte(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
5755 common_set_byte(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)));
5758 common_set_byte(emu, ACCESS_FLAG(F_SF));
5761 common_set_byte(emu, !ACCESS_FLAG(F_SF));
5764 common_set_byte(emu, ACCESS_FLAG(F_PF));
5767 common_set_byte(emu, !ACCESS_FLAG(F_PF));
5770 common_set_byte(emu, xorl(ACCESS_FLAG(F_SF),
5771 ACCESS_FLAG(F_OF)));
5774 common_set_byte(emu, xorl(ACCESS_FLAG(F_SF),
5775 ACCESS_FLAG(F_OF)));
5778 common_set_byte(emu,
5779 (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
5780 ACCESS_FLAG(F_ZF)));
5783 common_set_byte(emu,
5784 !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
5785 ACCESS_FLAG(F_ZF)));
5789 x86emuOp2_push_FS(emu);
5792 x86emuOp2_pop_FS(emu);
5795 x86emuOp2_cpuid(emu);
5798 x86emuOp2_bt_R(emu);
5801 x86emuOp2_shld_IMM(emu);
5804 x86emuOp2_shld_CL(emu);
5807 x86emuOp2_push_GS(emu);
5810 x86emuOp2_pop_GS(emu);
5813 x86emuOp2_bts_R(emu);
5816 x86emuOp2_shrd_IMM(emu);
5819 x86emuOp2_shrd_CL(emu);
5822 x86emuOp2_imul_R_RM(emu);
5825 /* 0xb0 TODO: cmpxchg */
5826 /* 0xb1 TODO: cmpxchg */
5828 x86emuOp2_lss_R_IMM(emu);
5831 x86emuOp2_btr_R(emu);
5834 x86emuOp2_lfs_R_IMM(emu);
5837 x86emuOp2_lgs_R_IMM(emu);
5840 x86emuOp2_movzx_byte_R_RM(emu);
5843 x86emuOp2_movzx_word_R_RM(emu);
5846 x86emuOp2_btX_I(emu);
5849 x86emuOp2_btc_R(emu);
5858 x86emuOp2_movsx_byte_R_RM(emu);
5861 x86emuOp2_movsx_word_R_RM(emu);
5864 /* 0xc0 TODO: xadd */
5865 /* 0xc1 TODO: xadd */
5866 /* 0xc8 TODO: bswap */
5867 /* 0xc9 TODO: bswap */
5868 /* 0xca TODO: bswap */
5869 /* 0xcb TODO: bswap */
5870 /* 0xcc TODO: bswap */
5871 /* 0xcd TODO: bswap */
5872 /* 0xce TODO: bswap */
5873 /* 0xcf TODO: bswap */
5876 x86emu_halt_sys(emu);
5882 * Carry Chain Calculation
5884 * This represents a somewhat expensive calculation which is
5885 * apparently required to emulate the setting of the OF and AF flag.
5886 * The latter is not so important, but the former is. The overflow
5887 * flag is the XOR of the top two bits of the carry chain for an
5888 * addition (similar for subtraction). Since we do not want to
5889 * simulate the addition in a bitwise manner, we try to calculate the
5890 * carry chain given the two operands and the result.
5892 * So, given the following table, which represents the addition of two
5893 * bits, we can derive a formula for the carry chain.
5905 * Construction of table for cout:
5909 * |------------------
5913 * By inspection, one gets: cc = ab + r'(a + b)
5915 * That represents alot of operations, but NO CHOICE....
5917 * Borrow Chain Calculation.
5919 * The following table represents the subtraction of two bits, from
5920 * which we can derive a formula for the borrow chain.
5932 * Construction of table for cout:
5936 * |------------------
5940 * By inspection, one gets: bc = a'b + r(a' + b)
5948 static uint32_t x86emu_parity_tab[8] =
5959 #define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
5960 #define XOR2(x) (((x) ^ ((x)>>1)) & 0x1)
5965 * Implements the AAA instruction and side effects.
5968 aaa_word(struct x86emu *emu, uint16_t d)
5971 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
5980 res = (uint16_t) (d & 0xFF0F);
5982 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
5983 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
5989 * Implements the AAA instruction and side effects.
5992 aas_word(struct x86emu *emu, uint16_t d)
5995 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
6004 res = (uint16_t) (d & 0xFF0F);
6006 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6007 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6013 * Implements the AAD instruction and side effects.
6016 aad_word(struct x86emu *emu, uint16_t d)
6021 hb = (uint8_t) ((d >> 8) & 0xff);
6022 lb = (uint8_t) ((d & 0xff));
6023 l = (uint16_t) ((lb + 10 * hb) & 0xFF);
6028 CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
6029 CONDITIONAL_SET_FLAG(l == 0, F_ZF);
6030 CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
6036 * Implements the AAM instruction and side effects.
6039 aam_word(struct x86emu *emu, uint8_t d)
6043 h = (uint16_t) (d / 10);
6044 l = (uint16_t) (d % 10);
6045 l |= (uint16_t) (h << 8);
6050 CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
6051 CONDITIONAL_SET_FLAG(l == 0, F_ZF);
6052 CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
6058 * Implements the ADC instruction and side effects.
6061 adc_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6063 uint32_t res; /* all operands in native machine order */
6066 if (ACCESS_FLAG(F_CF))
6071 CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
6072 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6073 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6074 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6076 /* calculate the carry chain SEE NOTE AT TOP. */
6077 cc = (s & d) | ((~res) & (s | d));
6078 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
6079 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6080 return (uint8_t) res;
6085 * Implements the ADC instruction and side effects.
6088 adc_word(struct x86emu *emu, uint16_t d, uint16_t s)
6090 uint32_t res; /* all operands in native machine order */
6093 if (ACCESS_FLAG(F_CF))
6098 CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
6099 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6100 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6101 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6103 /* calculate the carry chain SEE NOTE AT TOP. */
6104 cc = (s & d) | ((~res) & (s | d));
6105 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
6106 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6107 return (uint16_t) res;
6112 * Implements the ADC instruction and side effects.
6115 adc_long(struct x86emu *emu, uint32_t d, uint32_t s)
6117 uint32_t lo; /* all operands in native machine order */
6122 if (ACCESS_FLAG(F_CF)) {
6123 lo = 1 + (d & 0xFFFF) + (s & 0xFFFF);
6126 lo = (d & 0xFFFF) + (s & 0xFFFF);
6129 hi = (lo >> 16) + (d >> 16) + (s >> 16);
6131 CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
6132 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6133 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6134 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6136 /* calculate the carry chain SEE NOTE AT TOP. */
6137 cc = (s & d) | ((~res) & (s | d));
6138 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
6139 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6145 * Implements the ADD instruction and side effects.
6148 add_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6150 uint32_t res; /* all operands in native machine order */
6154 CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
6155 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6156 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6157 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6159 /* calculate the carry chain SEE NOTE AT TOP. */
6160 cc = (s & d) | ((~res) & (s | d));
6161 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
6162 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6163 return (uint8_t) res;
6168 * Implements the ADD instruction and side effects.
6171 add_word(struct x86emu *emu, uint16_t d, uint16_t s)
6173 uint32_t res; /* all operands in native machine order */
6177 CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
6178 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6179 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6180 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6182 /* calculate the carry chain SEE NOTE AT TOP. */
6183 cc = (s & d) | ((~res) & (s | d));
6184 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
6185 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6186 return (uint16_t) res;
6191 * Implements the ADD instruction and side effects.
6194 add_long(struct x86emu *emu, uint32_t d, uint32_t s)
6196 uint32_t lo; /* all operands in native machine order */
6201 lo = (d & 0xFFFF) + (s & 0xFFFF);
6203 hi = (lo >> 16) + (d >> 16) + (s >> 16);
6205 CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
6206 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6207 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6208 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6210 /* calculate the carry chain SEE NOTE AT TOP. */
6211 cc = (s & d) | ((~res) & (s | d));
6212 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
6213 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6220 * Implements the AND instruction and side effects.
6223 and_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6225 uint8_t res; /* all operands in native machine order */
6233 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6234 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6235 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6241 * Implements the AND instruction and side effects.
6244 and_word(struct x86emu *emu, uint16_t d, uint16_t s)
6246 uint16_t res; /* all operands in native machine order */
6254 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6255 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6256 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6262 * Implements the AND instruction and side effects.
6265 and_long(struct x86emu *emu, uint32_t d, uint32_t s)
6267 uint32_t res; /* all operands in native machine order */
6275 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6276 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6277 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6283 * Implements the CMP instruction and side effects.
6286 cmp_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6288 uint32_t res; /* all operands in native machine order */
6293 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6294 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6295 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6297 /* calculate the borrow chain. See note at top */
6298 bc = (res & (~d | s)) | (~d & s);
6299 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
6300 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6301 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6306 cmp_byte_no_return(struct x86emu *emu, uint8_t d, uint8_t s)
6308 cmp_byte(emu, d, s);
6313 * Implements the CMP instruction and side effects.
6316 cmp_word(struct x86emu *emu, uint16_t d, uint16_t s)
6318 uint32_t res; /* all operands in native machine order */
6322 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6323 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6324 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6326 /* calculate the borrow chain. See note at top */
6327 bc = (res & (~d | s)) | (~d & s);
6328 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
6329 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6330 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6335 cmp_word_no_return(struct x86emu *emu, uint16_t d, uint16_t s)
6337 cmp_word(emu, d, s);
6342 * Implements the CMP instruction and side effects.
6345 cmp_long(struct x86emu *emu, uint32_t d, uint32_t s)
6347 uint32_t res; /* all operands in native machine order */
6351 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6352 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6353 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6355 /* calculate the borrow chain. See note at top */
6356 bc = (res & (~d | s)) | (~d & s);
6357 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
6358 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6359 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6364 cmp_long_no_return(struct x86emu *emu, uint32_t d, uint32_t s)
6366 cmp_long(emu, d, s);
6371 * Implements the DAA instruction and side effects.
6374 daa_byte(struct x86emu *emu, uint8_t d)
6377 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
6381 if (res > 0x9F || ACCESS_FLAG(F_CF)) {
6385 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6386 CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF);
6387 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6388 return (uint8_t) res;
6393 * Implements the DAS instruction and side effects.
6396 das_byte(struct x86emu *emu, uint8_t d)
6398 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
6402 if (d > 0x9F || ACCESS_FLAG(F_CF)) {
6406 CONDITIONAL_SET_FLAG(d & 0x80, F_SF);
6407 CONDITIONAL_SET_FLAG(d == 0, F_ZF);
6408 CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF);
6414 * Implements the DEC instruction and side effects.
6417 dec_byte(struct x86emu *emu, uint8_t d)
6419 uint32_t res; /* all operands in native machine order */
6423 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6424 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6425 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6427 /* calculate the borrow chain. See note at top */
6428 /* based on sub_byte, uses s==1. */
6429 bc = (res & (~d | 1)) | (~d & 1);
6430 /* carry flag unchanged */
6431 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6432 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6433 return (uint8_t) res;
6438 * Implements the DEC instruction and side effects.
6441 dec_word(struct x86emu *emu, uint16_t d)
6443 uint32_t res; /* all operands in native machine order */
6447 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6448 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6449 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6451 /* calculate the borrow chain. See note at top */
6452 /* based on the sub_byte routine, with s==1 */
6453 bc = (res & (~d | 1)) | (~d & 1);
6454 /* carry flag unchanged */
6455 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6456 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6457 return (uint16_t) res;
6462 * Implements the DEC instruction and side effects.
6465 dec_long(struct x86emu *emu, uint32_t d)
6467 uint32_t res; /* all operands in native machine order */
6472 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6473 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6474 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6476 /* calculate the borrow chain. See note at top */
6477 bc = (res & (~d | 1)) | (~d & 1);
6478 /* carry flag unchanged */
6479 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6480 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6486 * Implements the INC instruction and side effects.
6489 inc_byte(struct x86emu *emu, uint8_t d)
6491 uint32_t res; /* all operands in native machine order */
6495 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6496 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6497 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6499 /* calculate the carry chain SEE NOTE AT TOP. */
6500 cc = ((1 & d) | (~res)) & (1 | d);
6501 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
6502 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6503 return (uint8_t) res;
6508 * Implements the INC instruction and side effects.
6511 inc_word(struct x86emu *emu, uint16_t d)
6513 uint32_t res; /* all operands in native machine order */
6517 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6518 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6519 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6521 /* calculate the carry chain SEE NOTE AT TOP. */
6522 cc = (1 & d) | ((~res) & (1 | d));
6523 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
6524 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6525 return (uint16_t) res;
6530 * Implements the INC instruction and side effects.
6533 inc_long(struct x86emu *emu, uint32_t d)
6535 uint32_t res; /* all operands in native machine order */
6539 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6540 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6541 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6543 /* calculate the carry chain SEE NOTE AT TOP. */
6544 cc = (1 & d) | ((~res) & (1 | d));
6545 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
6546 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6552 * Implements the OR instruction and side effects.
6555 or_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6557 uint8_t res; /* all operands in native machine order */
6563 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6564 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6565 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6571 * Implements the OR instruction and side effects.
6574 or_word(struct x86emu *emu, uint16_t d, uint16_t s)
6576 uint16_t res; /* all operands in native machine order */
6579 /* set the carry flag to be bit 8 */
6583 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6584 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6585 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6591 * Implements the OR instruction and side effects.
6594 or_long(struct x86emu *emu, uint32_t d, uint32_t s)
6596 uint32_t res; /* all operands in native machine order */
6600 /* set the carry flag to be bit 8 */
6604 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6605 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6606 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6612 * Implements the OR instruction and side effects.
6615 neg_byte(struct x86emu *emu, uint8_t s)
6620 CONDITIONAL_SET_FLAG(s != 0, F_CF);
6621 res = (uint8_t) - s;
6622 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6623 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6624 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6625 /* calculate the borrow chain --- modified such that d=0.
6626 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for
6627 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6628 * res&0xfff... == res. Similarly ~d&s == s. So the simplified
6631 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6632 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6638 * Implements the OR instruction and side effects.
6641 neg_word(struct x86emu *emu, uint16_t s)
6646 CONDITIONAL_SET_FLAG(s != 0, F_CF);
6647 res = (uint16_t) - s;
6648 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6649 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6650 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6652 /* calculate the borrow chain --- modified such that d=0.
6653 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for
6654 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6655 * res&0xfff... == res. Similarly ~d&s == s. So the simplified
6658 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6659 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6665 * Implements the OR instruction and side effects.
6668 neg_long(struct x86emu *emu, uint32_t s)
6673 CONDITIONAL_SET_FLAG(s != 0, F_CF);
6674 res = (uint32_t) - s;
6675 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6676 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6677 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6679 /* calculate the borrow chain --- modified such that d=0.
6680 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for
6681 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6682 * res&0xfff... == res. Similarly ~d&s == s. So the simplified
6685 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6686 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6692 * Implements the RCL instruction and side effects.
6695 rcl_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6697 unsigned int res, cnt, mask, cf;
6699 /* s is the rotate distance. It varies from 0 - 8. */
6702 * CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
6704 * want to rotate through the carry by "s" bits. We could loop, but
6705 * that's inefficient. So the width is 9, and we split into three
6708 * The new carry flag (was B_n) the stuff in B_n-1 .. B_0 the stuff
6711 * The new rotate is done mod 9, and given this, for a rotation of n
6712 * bits (mod 9) the new carry flag is then located n bits from the MSB.
6713 * The low part is then shifted up cnt bits, and the high part is or'd
6714 * in. Using CAPS for new values, and lowercase for the original
6715 * values, this can be expressed as:
6717 * IF n > 0 1) CF <- b_(8-n) 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0
6718 * 3) B_(n-1) <- cf 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1))
6721 if ((cnt = s % 9) != 0) {
6722 /* extract the new CARRY FLAG. */
6724 cf = (d >> (8 - cnt)) & 0x1;
6727 * Get the low stuff which rotated into the range B_7 .. B_cnt
6728 * B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0
6729 * note that the right hand side done by the mask.
6731 res = (d << cnt) & 0xff;
6734 * now the high stuff which rotated around into the positions
6736 * B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1))
6737 * shift it downward, 7-(n-2) = 9-n positions. and mask off
6738 * the result before or'ing in.
6740 mask = (1 << (cnt - 1)) - 1;
6741 res |= (d >> (9 - cnt)) & mask;
6743 /* if the carry flag was set, or it in. */
6744 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
6746 res |= 1 << (cnt - 1);
6748 /* set the new carry flag, based on the variable "cf" */
6749 CONDITIONAL_SET_FLAG(cf, F_CF);
6750 /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and
6751 * the most significant bit. Blecck. */
6752 /* parenthesized this expression since it appears to be
6753 * causing OF to be misset */
6754 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
6758 return (uint8_t) res;
6763 * Implements the RCL instruction and side effects.
6766 rcl_word(struct x86emu *emu, uint16_t d, uint8_t s)
6768 unsigned int res, cnt, mask, cf;
6771 if ((cnt = s % 17) != 0) {
6772 cf = (d >> (16 - cnt)) & 0x1;
6773 res = (d << cnt) & 0xffff;
6774 mask = (1 << (cnt - 1)) - 1;
6775 res |= (d >> (17 - cnt)) & mask;
6776 if (ACCESS_FLAG(F_CF)) {
6777 res |= 1 << (cnt - 1);
6779 CONDITIONAL_SET_FLAG(cf, F_CF);
6780 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
6783 return (uint16_t) res;
6788 * Implements the RCL instruction and side effects.
6791 rcl_long(struct x86emu *emu, uint32_t d, uint8_t s)
6793 uint32_t res, cnt, mask, cf;
6796 if ((cnt = s % 33) != 0) {
6797 cf = (d >> (32 - cnt)) & 0x1;
6798 res = (d << cnt) & 0xffffffff;
6799 mask = (1 << (cnt - 1)) - 1;
6800 res |= (d >> (33 - cnt)) & mask;
6801 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
6802 res |= 1 << (cnt - 1);
6804 CONDITIONAL_SET_FLAG(cf, F_CF);
6805 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
6813 * Implements the RCR instruction and side effects.
6816 rcr_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6819 uint32_t mask, cf, ocf = 0;
6821 /* rotate right through carry */
6822 /* s is the rotate distance. It varies from 0 - 8. d is the byte
6827 * CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
6829 * The new rotate is done mod 9, and given this, for a rotation of n
6830 * bits (mod 9) the new carry flag is then located n bits from the LSB.
6831 * The low part is then shifted up cnt bits, and the high part is or'd
6832 * in. Using CAPS for new values, and lowercase for the original
6833 * values, this can be expressed as:
6837 * 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
6838 * 3) B_(8-n) <- cf 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0)
6841 if ((cnt = s % 9) != 0) {
6842 /* extract the new CARRY FLAG. */
6846 /* note hackery here. Access_flag(..) evaluates to
6847 * either 0 if flag not set non-zero if flag is set.
6848 * doing access_flag(..) != 0 casts that into either
6849 * 0..1 in any representation of the flags register
6850 * (i.e. packed bit array or unpacked.) */
6851 ocf = ACCESS_FLAG(F_CF) != 0;
6853 cf = (d >> (cnt - 1)) & 0x1;
6855 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */
6856 /* note that the right hand side done by the mask This is
6857 * effectively done by shifting the object to the right. The
6858 * result must be masked, in case the object came in and was
6859 * treated as a negative number. Needed??? */
6861 mask = (1 << (8 - cnt)) - 1;
6862 res = (d >> cnt) & mask;
6864 /* now the high stuff which rotated around into the positions
6866 /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */
6867 /* shift it downward, 7-(n-2) = 9-n positions. and mask off
6868 * the result before or'ing in. */
6869 res |= (d << (9 - cnt));
6871 /* if the carry flag was set, or it in. */
6872 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
6874 res |= 1 << (8 - cnt);
6876 /* set the new carry flag, based on the variable "cf" */
6877 CONDITIONAL_SET_FLAG(cf, F_CF);
6878 /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and
6879 * the most significant bit. Blecck. */
6880 /* parenthesized... */
6882 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
6886 return (uint8_t) res;
6891 * Implements the RCR instruction and side effects.
6894 rcr_word(struct x86emu *emu, uint16_t d, uint8_t s)
6897 uint32_t mask, cf, ocf = 0;
6899 /* rotate right through carry */
6901 if ((cnt = s % 17) != 0) {
6904 ocf = ACCESS_FLAG(F_CF) != 0;
6906 cf = (d >> (cnt - 1)) & 0x1;
6907 mask = (1 << (16 - cnt)) - 1;
6908 res = (d >> cnt) & mask;
6909 res |= (d << (17 - cnt));
6910 if (ACCESS_FLAG(F_CF)) {
6911 res |= 1 << (16 - cnt);
6913 CONDITIONAL_SET_FLAG(cf, F_CF);
6915 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
6919 return (uint16_t) res;
6924 * Implements the RCR instruction and side effects.
6927 rcr_long(struct x86emu *emu, uint32_t d, uint8_t s)
6930 uint32_t mask, cf, ocf = 0;
6932 /* rotate right through carry */
6934 if ((cnt = s % 33) != 0) {
6937 ocf = ACCESS_FLAG(F_CF) != 0;
6939 cf = (d >> (cnt - 1)) & 0x1;
6940 mask = (1 << (32 - cnt)) - 1;
6941 res = (d >> cnt) & mask;
6943 res |= (d << (33 - cnt));
6944 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
6945 res |= 1 << (32 - cnt);
6947 CONDITIONAL_SET_FLAG(cf, F_CF);
6949 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
6958 * Implements the ROL instruction and side effects.
6961 rol_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6963 unsigned int res, cnt, mask;
6966 /* s is the rotate distance. It varies from 0 - 8. d is the byte
6973 * The new rotate is done mod 8. Much simpler than the "rcl" or "rcr"
6976 * IF n > 0 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) 2) B_(n-1) ..
6977 * B_(0) <- b_(7) .. b_(8-n) */
6979 if ((cnt = s % 8) != 0) {
6980 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */
6983 /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */
6984 mask = (1 << cnt) - 1;
6985 res |= (d >> (8 - cnt)) & mask;
6987 /* set the new carry flag, Note that it is the low order bit
6988 * of the result!!! */
6989 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
6990 /* OVERFLOW is set *IFF* s==1, then it is the xor of CF and
6991 * the most significant bit. Blecck. */
6992 CONDITIONAL_SET_FLAG(s == 1 &&
6993 XOR2((res & 0x1) + ((res >> 6) & 0x2)),
6996 /* set the new carry flag, Note that it is the low order bit
6997 * of the result!!! */
6998 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
7000 return (uint8_t) res;
7005 * Implements the ROL instruction and side effects.
7008 rol_word(struct x86emu *emu, uint16_t d, uint8_t s)
7010 unsigned int res, cnt, mask;
7013 if ((cnt = s % 16) != 0) {
7015 mask = (1 << cnt) - 1;
7016 res |= (d >> (16 - cnt)) & mask;
7017 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
7018 CONDITIONAL_SET_FLAG(s == 1 &&
7019 XOR2((res & 0x1) + ((res >> 14) & 0x2)),
7022 /* set the new carry flag, Note that it is the low order bit
7023 * of the result!!! */
7024 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
7026 return (uint16_t) res;
7031 * Implements the ROL instruction and side effects.
7034 rol_long(struct x86emu *emu, uint32_t d, uint8_t s)
7036 uint32_t res, cnt, mask;
7039 if ((cnt = s % 32) != 0) {
7041 mask = (1 << cnt) - 1;
7042 res |= (d >> (32 - cnt)) & mask;
7043 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
7044 CONDITIONAL_SET_FLAG(s == 1 &&
7045 XOR2((res & 0x1) + ((res >> 30) & 0x2)),
7048 /* set the new carry flag, Note that it is the low order bit
7049 * of the result!!! */
7050 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
7057 * Implements the ROR instruction and side effects.
7060 ror_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7062 unsigned int res, cnt, mask;
7065 /* s is the rotate distance. It varies from 0 - 8. d is the byte
7072 * The rotate is done mod 8.
7074 * IF n > 0 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) 2) B_(7) ..
7075 * B_(8-n) <- b_(n-1) .. b_(0) */
7077 if ((cnt = s % 8) != 0) { /* not a typo, do nada if cnt==0 */
7078 /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */
7079 res = (d << (8 - cnt));
7081 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */
7082 mask = (1 << (8 - cnt)) - 1;
7083 res |= (d >> (cnt)) & mask;
7085 /* set the new carry flag, Note that it is the low order bit
7086 * of the result!!! */
7087 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
7088 /* OVERFLOW is set *IFF* s==1, then it is the xor of the two
7089 * most significant bits. Blecck. */
7090 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
7091 } else if (s != 0) {
7092 /* set the new carry flag, Note that it is the low order bit
7093 * of the result!!! */
7094 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
7096 return (uint8_t) res;
7101 * Implements the ROR instruction and side effects.
7104 ror_word(struct x86emu *emu, uint16_t d, uint8_t s)
7106 unsigned int res, cnt, mask;
7109 if ((cnt = s % 16) != 0) {
7110 res = (d << (16 - cnt));
7111 mask = (1 << (16 - cnt)) - 1;
7112 res |= (d >> (cnt)) & mask;
7113 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
7114 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
7115 } else if (s != 0) {
7116 /* set the new carry flag, Note that it is the low order bit
7117 * of the result!!! */
7118 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
7120 return (uint16_t) res;
7125 * Implements the ROR instruction and side effects.
7128 ror_long(struct x86emu *emu, uint32_t d, uint8_t s)
7130 uint32_t res, cnt, mask;
7133 if ((cnt = s % 32) != 0) {
7134 res = (d << (32 - cnt));
7135 mask = (1 << (32 - cnt)) - 1;
7136 res |= (d >> (cnt)) & mask;
7137 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
7138 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
7139 } else if (s != 0) {
7140 /* set the new carry flag, Note that it is the low order bit
7141 * of the result!!! */
7142 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
7149 * Implements the SHL instruction and side effects.
7152 shl_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7154 unsigned int cnt, res, cf;
7159 /* last bit shifted out goes into carry flag */
7162 cf = d & (1 << (8 - cnt));
7163 CONDITIONAL_SET_FLAG(cf, F_CF);
7164 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7165 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7166 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7172 /* Needs simplification. */
7173 CONDITIONAL_SET_FLAG(
7174 (((res & 0x80) == 0x80) ^
7175 (ACCESS_FLAG(F_CF) != 0)),
7176 /* was (emu->x86.R_FLG&F_CF)==F_CF)), */
7183 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80, F_CF);
7189 return (uint8_t) res;
7194 * Implements the SHL instruction and side effects.
7197 shl_word(struct x86emu *emu, uint16_t d, uint8_t s)
7199 unsigned int cnt, res, cf;
7205 cf = d & (1 << (16 - cnt));
7206 CONDITIONAL_SET_FLAG(cf, F_CF);
7207 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7208 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7209 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7215 CONDITIONAL_SET_FLAG(
7216 (((res & 0x8000) == 0x8000) ^
7217 (ACCESS_FLAG(F_CF) != 0)),
7224 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF);
7230 return (uint16_t) res;
7235 * Implements the SHL instruction and side effects.
7238 shl_long(struct x86emu *emu, uint32_t d, uint8_t s)
7240 unsigned int cnt, res, cf;
7246 cf = d & (1 << (32 - cnt));
7247 CONDITIONAL_SET_FLAG(cf, F_CF);
7248 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7249 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7250 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7255 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000)
7256 ^ (ACCESS_FLAG(F_CF) != 0)), F_OF);
7262 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF);
7273 * Implements the SHR instruction and side effects.
7276 shr_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7278 unsigned int cnt, res, cf;
7283 cf = d & (1 << (cnt - 1));
7285 CONDITIONAL_SET_FLAG(cf, F_CF);
7286 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7287 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7288 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7294 CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
7300 CONDITIONAL_SET_FLAG((d >> (s - 1)) & 0x1, F_CF);
7306 return (uint8_t) res;
7311 * Implements the SHR instruction and side effects.
7314 shr_word(struct x86emu *emu, uint16_t d, uint8_t s)
7316 unsigned int cnt, res, cf;
7321 cf = d & (1 << (cnt - 1));
7323 CONDITIONAL_SET_FLAG(cf, F_CF);
7324 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7325 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7326 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7332 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
7344 return (uint16_t) res;
7349 * Implements the SHR instruction and side effects.
7352 shr_long(struct x86emu *emu, uint32_t d, uint8_t s)
7354 unsigned int cnt, res, cf;
7359 cf = d & (1 << (cnt - 1));
7361 CONDITIONAL_SET_FLAG(cf, F_CF);
7362 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7363 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7364 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7369 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
7386 * Implements the SAR instruction and side effects.
7389 sar_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7391 unsigned int cnt, res, cf, mask, sf;
7396 if (cnt > 0 && cnt < 8) {
7397 mask = (1 << (8 - cnt)) - 1;
7398 cf = d & (1 << (cnt - 1));
7399 res = (d >> cnt) & mask;
7400 CONDITIONAL_SET_FLAG(cf, F_CF);
7404 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7405 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7406 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7407 } else if (cnt >= 8) {
7422 return (uint8_t) res;
7427 * Implements the SAR instruction and side effects.
7430 sar_word(struct x86emu *emu, uint16_t d, uint8_t s)
7432 unsigned int cnt, res, cf, mask, sf;
7437 if (cnt > 0 && cnt < 16) {
7438 mask = (1 << (16 - cnt)) - 1;
7439 cf = d & (1 << (cnt - 1));
7440 res = (d >> cnt) & mask;
7441 CONDITIONAL_SET_FLAG(cf, F_CF);
7445 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7446 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7447 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7448 } else if (cnt >= 16) {
7463 return (uint16_t) res;
7468 * Implements the SAR instruction and side effects.
7471 sar_long(struct x86emu *emu, uint32_t d, uint8_t s)
7473 uint32_t cnt, res, cf, mask, sf;
7475 sf = d & 0x80000000;
7478 if (cnt > 0 && cnt < 32) {
7479 mask = (1 << (32 - cnt)) - 1;
7480 cf = d & (1 << (cnt - 1));
7481 res = (d >> cnt) & mask;
7482 CONDITIONAL_SET_FLAG(cf, F_CF);
7486 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7487 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7488 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7489 } else if (cnt >= 32) {
7509 * Implements the SHLD instruction and side effects.
7512 shld_word(struct x86emu *emu, uint16_t d, uint16_t fill, uint8_t s)
7514 unsigned int cnt, res, cf;
7519 res = (d << cnt) | (fill >> (16 - cnt));
7520 cf = d & (1 << (16 - cnt));
7521 CONDITIONAL_SET_FLAG(cf, F_CF);
7522 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7523 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7524 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7529 CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
7530 (ACCESS_FLAG(F_CF) != 0)), F_OF);
7536 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF);
7542 return (uint16_t) res;
7547 * Implements the SHLD instruction and side effects.
7550 shld_long(struct x86emu *emu, uint32_t d, uint32_t fill, uint8_t s)
7552 unsigned int cnt, res, cf;
7557 res = (d << cnt) | (fill >> (32 - cnt));
7558 cf = d & (1 << (32 - cnt));
7559 CONDITIONAL_SET_FLAG(cf, F_CF);
7560 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7561 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7562 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7567 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000)
7568 ^ (ACCESS_FLAG(F_CF) != 0)), F_OF);
7574 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF);
7585 * Implements the SHRD instruction and side effects.
7588 shrd_word(struct x86emu *emu, uint16_t d, uint16_t fill, uint8_t s)
7590 unsigned int cnt, res, cf;
7595 cf = d & (1 << (cnt - 1));
7596 res = (d >> cnt) | (fill << (16 - cnt));
7597 CONDITIONAL_SET_FLAG(cf, F_CF);
7598 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7599 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7600 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7606 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
7618 return (uint16_t) res;
7623 * Implements the SHRD instruction and side effects.
7626 shrd_long(struct x86emu *emu, uint32_t d, uint32_t fill, uint8_t s)
7628 unsigned int cnt, res, cf;
7633 cf = d & (1 << (cnt - 1));
7634 res = (d >> cnt) | (fill << (32 - cnt));
7635 CONDITIONAL_SET_FLAG(cf, F_CF);
7636 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7637 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7638 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7643 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
7660 * Implements the SBB instruction and side effects.
7663 sbb_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7665 uint32_t res; /* all operands in native machine order */
7668 if (ACCESS_FLAG(F_CF))
7672 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7673 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7674 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7676 /* calculate the borrow chain. See note at top */
7677 bc = (res & (~d | s)) | (~d & s);
7678 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
7679 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
7680 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7681 return (uint8_t) res;
7686 * Implements the SBB instruction and side effects.
7689 sbb_word(struct x86emu *emu, uint16_t d, uint16_t s)
7691 uint32_t res; /* all operands in native machine order */
7694 if (ACCESS_FLAG(F_CF))
7698 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7699 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7700 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7702 /* calculate the borrow chain. See note at top */
7703 bc = (res & (~d | s)) | (~d & s);
7704 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
7705 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
7706 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7707 return (uint16_t) res;
7712 * Implements the SBB instruction and side effects.
7715 sbb_long(struct x86emu *emu, uint32_t d, uint32_t s)
7717 uint32_t res; /* all operands in native machine order */
7720 if (ACCESS_FLAG(F_CF))
7724 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7725 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7726 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7728 /* calculate the borrow chain. See note at top */
7729 bc = (res & (~d | s)) | (~d & s);
7730 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
7731 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
7732 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7738 * Implements the SUB instruction and side effects.
7741 sub_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7743 uint32_t res; /* all operands in native machine order */
7747 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7748 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7749 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7751 /* calculate the borrow chain. See note at top */
7752 bc = (res & (~d | s)) | (~d & s);
7753 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
7754 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
7755 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7756 return (uint8_t) res;
7761 * Implements the SUB instruction and side effects.
7764 sub_word(struct x86emu *emu, uint16_t d, uint16_t s)
7766 uint32_t res; /* all operands in native machine order */
7770 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7771 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7772 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7774 /* calculate the borrow chain. See note at top */
7775 bc = (res & (~d | s)) | (~d & s);
7776 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
7777 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
7778 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7779 return (uint16_t) res;
7784 * Implements the SUB instruction and side effects.
7787 sub_long(struct x86emu *emu, uint32_t d, uint32_t s)
7789 uint32_t res; /* all operands in native machine order */
7793 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7794 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7795 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7797 /* calculate the borrow chain. See note at top */
7798 bc = (res & (~d | s)) | (~d & s);
7799 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
7800 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
7801 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7807 * Implements the TEST instruction and side effects.
7810 test_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7812 uint32_t res; /* all operands in native machine order */
7817 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7818 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7819 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7820 /* AF == dont care */
7826 * Implements the TEST instruction and side effects.
7829 test_word(struct x86emu *emu, uint16_t d, uint16_t s)
7831 uint32_t res; /* all operands in native machine order */
7836 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7837 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7838 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7839 /* AF == dont care */
7845 * Implements the TEST instruction and side effects.
7848 test_long(struct x86emu *emu, uint32_t d, uint32_t s)
7850 uint32_t res; /* all operands in native machine order */
7855 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7856 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7857 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7858 /* AF == dont care */
7864 * Implements the XOR instruction and side effects.
7867 xor_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7869 uint8_t res; /* all operands in native machine order */
7873 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7874 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7875 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
7883 * Implements the XOR instruction and side effects.
7886 xor_word(struct x86emu *emu, uint16_t d, uint16_t s)
7888 uint16_t res; /* all operands in native machine order */
7892 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7893 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7894 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7902 * Implements the XOR instruction and side effects.
7905 xor_long(struct x86emu *emu, uint32_t d, uint32_t s)
7907 uint32_t res; /* all operands in native machine order */
7911 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7912 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7913 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7921 * Implements the IMUL instruction and side effects.
7924 imul_byte(struct x86emu *emu, uint8_t s)
7926 int16_t res = (int16_t) ((int8_t) emu->x86.R_AL * (int8_t) s);
7928 emu->x86.R_AX = res;
7929 if (((emu->x86.R_AL & 0x80) == 0 && emu->x86.R_AH == 0x00) ||
7930 ((emu->x86.R_AL & 0x80) != 0 && emu->x86.R_AH == 0xFF)) {
7941 * Implements the IMUL instruction and side effects.
7944 imul_word(struct x86emu *emu, uint16_t s)
7946 int32_t res = (int16_t) emu->x86.R_AX * (int16_t) s;
7948 emu->x86.R_AX = (uint16_t) res;
7949 emu->x86.R_DX = (uint16_t) (res >> 16);
7950 if (((emu->x86.R_AX & 0x8000) == 0 && emu->x86.R_DX == 0x00) ||
7951 ((emu->x86.R_AX & 0x8000) != 0 && emu->x86.R_DX == 0xFF)) {
7962 * Implements the IMUL instruction and side effects.
7965 imul_long(struct x86emu *emu, uint32_t s)
7969 res = (int64_t)(int32_t)emu->x86.R_EAX * (int32_t)s;
7970 emu->x86.R_EAX = (uint32_t)res;
7971 emu->x86.R_EDX = ((uint64_t)res) >> 32;
7972 if (((emu->x86.R_EAX & 0x80000000) == 0 && emu->x86.R_EDX == 0x00) ||
7973 ((emu->x86.R_EAX & 0x80000000) != 0 && emu->x86.R_EDX == 0xFF)) {
7984 * Implements the MUL instruction and side effects.
7987 mul_byte(struct x86emu *emu, uint8_t s)
7989 uint16_t res = (uint16_t) (emu->x86.R_AL * s);
7991 emu->x86.R_AX = res;
7992 if (emu->x86.R_AH == 0) {
8003 * Implements the MUL instruction and side effects.
8006 mul_word(struct x86emu *emu, uint16_t s)
8008 uint32_t res = emu->x86.R_AX * s;
8010 emu->x86.R_AX = (uint16_t) res;
8011 emu->x86.R_DX = (uint16_t) (res >> 16);
8012 if (emu->x86.R_DX == 0) {
8023 * Implements the MUL instruction and side effects.
8026 mul_long(struct x86emu *emu, uint32_t s)
8028 uint64_t res = (uint64_t) emu->x86.R_EAX * s;
8030 emu->x86.R_EAX = (uint32_t) res;
8031 emu->x86.R_EDX = (uint32_t) (res >> 32);
8033 if (emu->x86.R_EDX == 0) {
8044 * Implements the IDIV instruction and side effects.
8047 idiv_byte(struct x86emu *emu, uint8_t s)
8049 int32_t dvd, div, mod;
8051 dvd = (int16_t) emu->x86.R_AX;
8053 x86emu_intr_raise(emu, 8);
8056 div = dvd / (int8_t) s;
8057 mod = dvd % (int8_t) s;
8058 if (div > 0x7f || div < -0x7f) {
8059 x86emu_intr_raise(emu, 8);
8062 emu->x86.R_AL = (int8_t) div;
8063 emu->x86.R_AH = (int8_t) mod;
8068 * Implements the IDIV instruction and side effects.
8071 idiv_word(struct x86emu *emu, uint16_t s)
8073 int32_t dvd, div, mod;
8075 dvd = (((int32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX;
8077 x86emu_intr_raise(emu, 8);
8080 div = dvd / (int16_t) s;
8081 mod = dvd % (int16_t) s;
8082 if (div > 0x7fff || div < -0x7fff) {
8083 x86emu_intr_raise(emu, 8);
8088 CONDITIONAL_SET_FLAG(div == 0, F_ZF);
8089 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
8091 emu->x86.R_AX = (uint16_t) div;
8092 emu->x86.R_DX = (uint16_t) mod;
8097 * Implements the IDIV instruction and side effects.
8100 idiv_long(struct x86emu *emu, uint32_t s)
8102 int64_t dvd, div, mod;
8104 dvd = (((int64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX;
8106 x86emu_intr_raise(emu, 8);
8109 div = dvd / (int32_t) s;
8110 mod = dvd % (int32_t) s;
8111 if (div > 0x7fffffff || div < -0x7fffffff) {
8112 x86emu_intr_raise(emu, 8);
8119 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
8121 emu->x86.R_EAX = (uint32_t) div;
8122 emu->x86.R_EDX = (uint32_t) mod;
8127 * Implements the DIV instruction and side effects.
8130 div_byte(struct x86emu *emu, uint8_t s)
8132 uint32_t dvd, div, mod;
8134 dvd = emu->x86.R_AX;
8136 x86emu_intr_raise(emu, 8);
8139 div = dvd / (uint8_t) s;
8140 mod = dvd % (uint8_t) s;
8142 x86emu_intr_raise(emu, 8);
8145 emu->x86.R_AL = (uint8_t) div;
8146 emu->x86.R_AH = (uint8_t) mod;
8151 * Implements the DIV instruction and side effects.
8154 div_word(struct x86emu *emu, uint16_t s)
8156 uint32_t dvd, div, mod;
8158 dvd = (((uint32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX;
8160 x86emu_intr_raise(emu, 8);
8163 div = dvd / (uint16_t) s;
8164 mod = dvd % (uint16_t) s;
8166 x86emu_intr_raise(emu, 8);
8171 CONDITIONAL_SET_FLAG(div == 0, F_ZF);
8172 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
8174 emu->x86.R_AX = (uint16_t) div;
8175 emu->x86.R_DX = (uint16_t) mod;
8180 * Implements the DIV instruction and side effects.
8183 div_long(struct x86emu *emu, uint32_t s)
8185 uint64_t dvd, div, mod;
8187 dvd = (((uint64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX;
8189 x86emu_intr_raise(emu, 8);
8192 div = dvd / (uint32_t) s;
8193 mod = dvd % (uint32_t) s;
8194 if (div > 0xffffffff) {
8195 x86emu_intr_raise(emu, 8);
8202 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
8204 emu->x86.R_EAX = (uint32_t) div;
8205 emu->x86.R_EDX = (uint32_t) mod;
8210 * Implements the IN string instruction and side effects.
8213 ins(struct x86emu *emu, int size)
8217 if (ACCESS_FLAG(F_DF)) {
8220 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
8221 /* dont care whether REPE or REPNE */
8222 /* in until CX is ZERO. */
8223 uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ?
8224 emu->x86.R_ECX : emu->x86.R_CX);
8228 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
8229 (*emu->emu_inb) (emu, emu->x86.R_DX));
8230 emu->x86.R_DI += inc;
8236 store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
8237 (*emu->emu_inw) (emu, emu->x86.R_DX));
8238 emu->x86.R_DI += inc;
8243 store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
8244 (*emu->emu_inl) (emu, emu->x86.R_DX));
8245 emu->x86.R_DI += inc;
8250 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
8253 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
8257 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
8258 (*emu->emu_inb) (emu, emu->x86.R_DX));
8261 store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
8262 (*emu->emu_inw) (emu, emu->x86.R_DX));
8265 store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
8266 (*emu->emu_inl) (emu, emu->x86.R_DX));
8269 emu->x86.R_DI += inc;
8275 * Implements the OUT string instruction and side effects.
8278 outs(struct x86emu *emu, int size)
8282 if (ACCESS_FLAG(F_DF)) {
8285 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
8286 /* dont care whether REPE or REPNE */
8287 /* out until CX is ZERO. */
8288 uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ?
8289 emu->x86.R_ECX : emu->x86.R_CX);
8293 (*emu->emu_outb) (emu, emu->x86.R_DX,
8294 fetch_byte(emu, emu->x86.R_ES,
8296 emu->x86.R_SI += inc;
8302 (*emu->emu_outw) (emu, emu->x86.R_DX,
8303 fetch_word(emu, emu->x86.R_ES,
8305 emu->x86.R_SI += inc;
8310 (*emu->emu_outl) (emu, emu->x86.R_DX,
8311 fetch_long(emu, emu->x86.R_ES,
8313 emu->x86.R_SI += inc;
8318 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
8321 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
8325 (*emu->emu_outb) (emu, emu->x86.R_DX,
8326 fetch_byte(emu, emu->x86.R_ES, emu->x86.R_SI));
8329 (*emu->emu_outw) (emu, emu->x86.R_DX,
8330 fetch_word(emu, emu->x86.R_ES, emu->x86.R_SI));
8333 (*emu->emu_outl) (emu, emu->x86.R_DX,
8334 fetch_long(emu, emu->x86.R_ES, emu->x86.R_SI));
8337 emu->x86.R_SI += inc;
8343 * Pushes a word onto the stack.
8345 * NOTE: Do not inline this, as (*emu->emu_wrX) is already inline!
8348 push_word(struct x86emu *emu, uint16_t w)
8351 store_word(emu, emu->x86.R_SS, emu->x86.R_SP, w);
8356 * Pushes a long onto the stack.
8358 * NOTE: Do not inline this, as (*emu->emu_wrX) is already inline!
8361 push_long(struct x86emu *emu, uint32_t w)
8364 store_long(emu, emu->x86.R_SS, emu->x86.R_SP, w);
8369 * Pops a word from the stack.
8371 * NOTE: Do not inline this, as (*emu->emu_rdX) is already inline!
8374 pop_word(struct x86emu *emu)
8378 res = fetch_word(emu, emu->x86.R_SS, emu->x86.R_SP);
8385 * Pops a long from the stack.
8387 * NOTE: Do not inline this, as (*emu->emu_rdX) is already inline!
8390 pop_long(struct x86emu *emu)
8394 res = fetch_long(emu, emu->x86.R_SS, emu->x86.R_SP);