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)
2154 uint32_t destoffset;
2156 fetch_decode_modrm(emu);
2157 if (emu->cur_mod == 3)
2158 x86emu_halt_sys(emu);
2160 destoffset = decode_rl_address(emu);
2161 if (emu->x86.mode & SYSMODE_PREFIX_ADDR) {
2164 srcreg = decode_rh_long_register(emu);
2165 *srcreg = (uint32_t) destoffset;
2169 srcreg = decode_rh_word_register(emu);
2170 *srcreg = (uint16_t) destoffset;
2176 * Handles opcode 0x8e
2179 x86emuOp_mov_word_SR_RM(struct x86emu *emu)
2183 fetch_decode_modrm(emu);
2184 destreg = decode_rh_seg_register(emu);
2185 *destreg = decode_and_fetch_word(emu);
2187 * Clean up, and reset all the R_xSP pointers to the correct
2188 * locations. This is about 3x too much overhead (doing all the
2189 * segreg ptrs when only one is needed, but this instruction
2190 * *cannot* be that common, and this isn't too much work anyway.
2196 * Handles opcode 0x8f
2199 x86emuOp32_pop_RM(struct x86emu *emu)
2201 uint32_t destoffset;
2202 uint32_t destval, *destreg;
2204 fetch_decode_modrm(emu);
2205 if (emu->cur_mod != 3) {
2206 destoffset = decode_rl_address(emu);
2207 destval = pop_long(emu);
2208 store_data_long(emu, destoffset, destval);
2210 destreg = decode_rl_long_register(emu);
2211 *destreg = pop_long(emu);
2216 x86emuOp16_pop_RM(struct x86emu *emu)
2218 uint32_t destoffset;
2219 uint16_t destval, *destreg;
2221 fetch_decode_modrm(emu);
2222 if (emu->cur_mod != 3) {
2223 destoffset = decode_rl_address(emu);
2224 destval = pop_word(emu);
2225 store_data_word(emu, destoffset, destval);
2227 destreg = decode_rl_word_register(emu);
2228 *destreg = pop_word(emu);
2233 x86emuOp_pop_RM(struct x86emu *emu)
2235 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2236 x86emuOp32_pop_RM(emu);
2238 x86emuOp16_pop_RM(emu);
2243 * Handles opcode 0x91
2246 x86emuOp_xchg_word_AX_CX(struct x86emu *emu)
2250 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2251 tmp = emu->x86.R_EAX;
2252 emu->x86.R_EAX = emu->x86.R_ECX;
2253 emu->x86.R_ECX = tmp;
2255 tmp = emu->x86.R_AX;
2256 emu->x86.R_AX = emu->x86.R_CX;
2257 emu->x86.R_CX = (uint16_t) tmp;
2263 * Handles opcode 0x92
2266 x86emuOp_xchg_word_AX_DX(struct x86emu *emu)
2270 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2271 tmp = emu->x86.R_EAX;
2272 emu->x86.R_EAX = emu->x86.R_EDX;
2273 emu->x86.R_EDX = tmp;
2275 tmp = emu->x86.R_AX;
2276 emu->x86.R_AX = emu->x86.R_DX;
2277 emu->x86.R_DX = (uint16_t) tmp;
2283 * Handles opcode 0x93
2286 x86emuOp_xchg_word_AX_BX(struct x86emu *emu)
2290 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2291 tmp = emu->x86.R_EAX;
2292 emu->x86.R_EAX = emu->x86.R_EBX;
2293 emu->x86.R_EBX = tmp;
2295 tmp = emu->x86.R_AX;
2296 emu->x86.R_AX = emu->x86.R_BX;
2297 emu->x86.R_BX = (uint16_t) tmp;
2303 * Handles opcode 0x94
2306 x86emuOp_xchg_word_AX_SP(struct x86emu *emu)
2310 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2311 tmp = emu->x86.R_EAX;
2312 emu->x86.R_EAX = emu->x86.R_ESP;
2313 emu->x86.R_ESP = tmp;
2315 tmp = emu->x86.R_AX;
2316 emu->x86.R_AX = emu->x86.R_SP;
2317 emu->x86.R_SP = (uint16_t) tmp;
2323 * Handles opcode 0x95
2326 x86emuOp_xchg_word_AX_BP(struct x86emu *emu)
2330 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2331 tmp = emu->x86.R_EAX;
2332 emu->x86.R_EAX = emu->x86.R_EBP;
2333 emu->x86.R_EBP = tmp;
2335 tmp = emu->x86.R_AX;
2336 emu->x86.R_AX = emu->x86.R_BP;
2337 emu->x86.R_BP = (uint16_t) tmp;
2343 * Handles opcode 0x96
2346 x86emuOp_xchg_word_AX_SI(struct x86emu *emu)
2350 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2351 tmp = emu->x86.R_EAX;
2352 emu->x86.R_EAX = emu->x86.R_ESI;
2353 emu->x86.R_ESI = tmp;
2355 tmp = emu->x86.R_AX;
2356 emu->x86.R_AX = emu->x86.R_SI;
2357 emu->x86.R_SI = (uint16_t) tmp;
2363 * Handles opcode 0x97
2366 x86emuOp_xchg_word_AX_DI(struct x86emu *emu)
2370 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2371 tmp = emu->x86.R_EAX;
2372 emu->x86.R_EAX = emu->x86.R_EDI;
2373 emu->x86.R_EDI = tmp;
2375 tmp = emu->x86.R_AX;
2376 emu->x86.R_AX = emu->x86.R_DI;
2377 emu->x86.R_DI = (uint16_t) tmp;
2383 * Handles opcode 0x98
2386 x86emuOp_cbw(struct x86emu *emu)
2388 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2389 if (emu->x86.R_AX & 0x8000) {
2390 emu->x86.R_EAX |= 0xffff0000;
2392 emu->x86.R_EAX &= 0x0000ffff;
2395 if (emu->x86.R_AL & 0x80) {
2396 emu->x86.R_AH = 0xff;
2398 emu->x86.R_AH = 0x0;
2405 * Handles opcode 0x99
2408 x86emuOp_cwd(struct x86emu *emu)
2410 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2411 if (emu->x86.R_EAX & 0x80000000) {
2412 emu->x86.R_EDX = 0xffffffff;
2414 emu->x86.R_EDX = 0x0;
2417 if (emu->x86.R_AX & 0x8000) {
2418 emu->x86.R_DX = 0xffff;
2420 emu->x86.R_DX = 0x0;
2427 * Handles opcode 0x9a
2430 x86emuOp_call_far_IMM(struct x86emu *emu)
2432 uint16_t farseg, faroff;
2434 faroff = fetch_word_imm(emu);
2435 farseg = fetch_word_imm(emu);
2438 * Hooked interrupt vectors calling into our "BIOS" will cause problems
2439 * unless all intersegment stuff is checked for BIOS access. Check
2440 * needed here. For moment, let it alone. */
2441 push_word(emu, emu->x86.R_CS);
2442 emu->x86.R_CS = farseg;
2443 push_word(emu, emu->x86.R_IP);
2444 emu->x86.R_IP = faroff;
2449 * Handles opcode 0x9c
2452 x86emuOp_pushf_word(struct x86emu *emu)
2456 /* clear out *all* bits not representing flags, and turn on real bits */
2457 flags = (emu->x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
2458 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2459 push_long(emu, flags);
2461 push_word(emu, (uint16_t) flags);
2467 * Handles opcode 0x9d
2470 x86emuOp_popf_word(struct x86emu *emu)
2472 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2473 emu->x86.R_EFLG = pop_long(emu);
2475 emu->x86.R_FLG = pop_word(emu);
2481 * Handles opcode 0x9e
2484 x86emuOp_sahf(struct x86emu *emu)
2486 /* clear the lower bits of the flag register */
2487 emu->x86.R_FLG &= 0xffffff00;
2488 /* or in the AH register into the flags register */
2489 emu->x86.R_FLG |= emu->x86.R_AH;
2494 * Handles opcode 0x9f
2497 x86emuOp_lahf(struct x86emu *emu)
2499 emu->x86.R_AH = (uint8_t) (emu->x86.R_FLG & 0xff);
2500 /* undocumented TC++ behavior??? Nope. It's documented, but you have
2501 * too look real hard to notice it. */
2502 emu->x86.R_AH |= 0x2;
2507 * Handles opcode 0xa0
2510 x86emuOp_mov_AL_M_IMM(struct x86emu *emu)
2514 offset = fetch_word_imm(emu);
2515 emu->x86.R_AL = fetch_data_byte(emu, offset);
2520 * Handles opcode 0xa1
2523 x86emuOp_mov_AX_M_IMM(struct x86emu *emu)
2527 offset = fetch_word_imm(emu);
2528 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2529 emu->x86.R_EAX = fetch_data_long(emu, offset);
2531 emu->x86.R_AX = fetch_data_word(emu, offset);
2537 * Handles opcode 0xa2
2540 x86emuOp_mov_M_AL_IMM(struct x86emu *emu)
2544 offset = fetch_word_imm(emu);
2545 store_data_byte(emu, offset, emu->x86.R_AL);
2550 * Handles opcode 0xa3
2553 x86emuOp_mov_M_AX_IMM(struct x86emu *emu)
2557 offset = fetch_word_imm(emu);
2558 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2559 store_data_long(emu, offset, emu->x86.R_EAX);
2561 store_data_word(emu, offset, emu->x86.R_AX);
2567 * Handles opcode 0xa4
2570 x86emuOp_movs_byte(struct x86emu *emu)
2576 if (ACCESS_FLAG(F_DF)) /* down */
2581 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2582 /* dont care whether REPE or REPNE */
2583 /* move them until CX is ZERO. */
2584 count = emu->x86.R_CX;
2586 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2589 val = fetch_data_byte(emu, emu->x86.R_SI);
2590 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, val);
2591 emu->x86.R_SI += inc;
2592 emu->x86.R_DI += inc;
2598 * Handles opcode 0xa5
2601 x86emuOp_movs_word(struct x86emu *emu)
2607 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2612 if (ACCESS_FLAG(F_DF)) /* down */
2616 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2617 /* dont care whether REPE or REPNE */
2618 /* move them until CX is ZERO. */
2619 count = emu->x86.R_CX;
2621 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2624 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2625 val = fetch_data_long(emu, emu->x86.R_SI);
2626 store_long(emu, emu->x86.R_ES, emu->x86.R_DI, val);
2628 val = fetch_data_word(emu, emu->x86.R_SI);
2629 store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
2632 emu->x86.R_SI += inc;
2633 emu->x86.R_DI += inc;
2639 * Handles opcode 0xa6
2642 x86emuOp_cmps_byte(struct x86emu *emu)
2647 if (ACCESS_FLAG(F_DF)) /* down */
2652 if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2654 /* move them until CX is ZERO. */
2655 while (emu->x86.R_CX != 0) {
2656 val1 = fetch_data_byte(emu, emu->x86.R_SI);
2657 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2658 cmp_byte(emu, val1, val2);
2660 emu->x86.R_SI += inc;
2661 emu->x86.R_DI += inc;
2662 if (ACCESS_FLAG(F_ZF) == 0)
2665 emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2666 } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2668 /* move them until CX is ZERO. */
2669 while (emu->x86.R_CX != 0) {
2670 val1 = fetch_data_byte(emu, emu->x86.R_SI);
2671 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2672 cmp_byte(emu, val1, val2);
2674 emu->x86.R_SI += inc;
2675 emu->x86.R_DI += inc;
2676 if (ACCESS_FLAG(F_ZF))
2677 break; /* zero flag set means equal */
2679 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2681 val1 = fetch_data_byte(emu, emu->x86.R_SI);
2682 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2683 cmp_byte(emu, val1, val2);
2684 emu->x86.R_SI += inc;
2685 emu->x86.R_DI += inc;
2691 * Handles opcode 0xa7
2694 x86emuOp_cmps_word(struct x86emu *emu)
2696 uint32_t val1, val2;
2699 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2700 if (ACCESS_FLAG(F_DF)) /* down */
2705 if (ACCESS_FLAG(F_DF)) /* down */
2710 if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2712 /* move them until CX is ZERO. */
2713 while (emu->x86.R_CX != 0) {
2714 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2715 val1 = fetch_data_long(emu, emu->x86.R_SI);
2716 val2 = fetch_long(emu, emu->x86.R_ES,
2718 cmp_long(emu, val1, val2);
2720 val1 = fetch_data_word(emu, emu->x86.R_SI);
2721 val2 = fetch_word(emu, emu->x86.R_ES,
2723 cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
2726 emu->x86.R_SI += inc;
2727 emu->x86.R_DI += inc;
2728 if (ACCESS_FLAG(F_ZF) == 0)
2731 emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2732 } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2734 /* move them until CX is ZERO. */
2735 while (emu->x86.R_CX != 0) {
2736 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2737 val1 = fetch_data_long(emu, emu->x86.R_SI);
2738 val2 = fetch_long(emu, emu->x86.R_ES,
2740 cmp_long(emu, val1, val2);
2742 val1 = fetch_data_word(emu, emu->x86.R_SI);
2743 val2 = fetch_word(emu, emu->x86.R_ES,
2745 cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
2748 emu->x86.R_SI += inc;
2749 emu->x86.R_DI += inc;
2750 if (ACCESS_FLAG(F_ZF))
2751 break; /* zero flag set means equal */
2753 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2755 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2756 val1 = fetch_data_long(emu, emu->x86.R_SI);
2757 val2 = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
2758 cmp_long(emu, val1, val2);
2760 val1 = fetch_data_word(emu, emu->x86.R_SI);
2761 val2 = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
2762 cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
2764 emu->x86.R_SI += inc;
2765 emu->x86.R_DI += inc;
2771 * Handles opcode 0xa9
2774 x86emuOp_test_AX_IMM(struct x86emu *emu)
2776 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2777 test_long(emu, emu->x86.R_EAX, fetch_long_imm(emu));
2779 test_word(emu, emu->x86.R_AX, fetch_word_imm(emu));
2785 * Handles opcode 0xaa
2788 x86emuOp_stos_byte(struct x86emu *emu)
2792 if (ACCESS_FLAG(F_DF)) /* down */
2796 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2797 /* dont care whether REPE or REPNE */
2798 /* move them until CX is ZERO. */
2799 while (emu->x86.R_CX != 0) {
2800 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
2803 emu->x86.R_DI += inc;
2805 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2807 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_AL);
2808 emu->x86.R_DI += inc;
2814 * Handles opcode 0xab
2817 x86emuOp_stos_word(struct x86emu *emu)
2822 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2827 if (ACCESS_FLAG(F_DF)) /* down */
2831 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2832 /* dont care whether REPE or REPNE */
2833 /* move them until CX is ZERO. */
2834 count = emu->x86.R_CX;
2836 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2839 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2840 store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
2843 store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
2846 emu->x86.R_DI += inc;
2852 * Handles opcode 0xac
2855 x86emuOp_lods_byte(struct x86emu *emu)
2859 if (ACCESS_FLAG(F_DF)) /* down */
2863 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2864 /* dont care whether REPE or REPNE */
2865 /* move them until CX is ZERO. */
2866 while (emu->x86.R_CX != 0) {
2867 emu->x86.R_AL = fetch_data_byte(emu, emu->x86.R_SI);
2869 emu->x86.R_SI += inc;
2871 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2873 emu->x86.R_AL = fetch_data_byte(emu, emu->x86.R_SI);
2874 emu->x86.R_SI += inc;
2880 * Handles opcode 0xad
2883 x86emuOp_lods_word(struct x86emu *emu)
2888 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2893 if (ACCESS_FLAG(F_DF)) /* down */
2897 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2898 /* dont care whether REPE or REPNE */
2899 /* move them until CX is ZERO. */
2900 count = emu->x86.R_CX;
2902 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2905 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2906 emu->x86.R_EAX = fetch_data_long(emu, emu->x86.R_SI);
2908 emu->x86.R_AX = fetch_data_word(emu, emu->x86.R_SI);
2910 emu->x86.R_SI += inc;
2916 * Handles opcode 0xae
2919 x86emuOp_scas_byte(struct x86emu *emu)
2924 if (ACCESS_FLAG(F_DF)) /* down */
2928 if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2930 /* move them until CX is ZERO. */
2931 while (emu->x86.R_CX != 0) {
2932 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2933 cmp_byte(emu, emu->x86.R_AL, val2);
2935 emu->x86.R_DI += inc;
2936 if (ACCESS_FLAG(F_ZF) == 0)
2939 emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2940 } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2942 /* move them until CX is ZERO. */
2943 while (emu->x86.R_CX != 0) {
2944 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2945 cmp_byte(emu, emu->x86.R_AL, val2);
2947 emu->x86.R_DI += inc;
2948 if (ACCESS_FLAG(F_ZF))
2949 break; /* zero flag set means equal */
2951 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2953 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2954 cmp_byte(emu, emu->x86.R_AL, val2);
2955 emu->x86.R_DI += inc;
2961 * Handles opcode 0xaf
2964 x86emuOp_scas_word(struct x86emu *emu)
2969 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2974 if (ACCESS_FLAG(F_DF)) /* down */
2977 if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2979 /* move them until CX is ZERO. */
2980 while (emu->x86.R_CX != 0) {
2981 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2982 val = fetch_long(emu, emu->x86.R_ES,
2984 cmp_long(emu, emu->x86.R_EAX, val);
2986 val = fetch_word(emu, emu->x86.R_ES,
2988 cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
2991 emu->x86.R_DI += inc;
2992 if (ACCESS_FLAG(F_ZF) == 0)
2995 emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2996 } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2998 /* move them until CX is ZERO. */
2999 while (emu->x86.R_CX != 0) {
3000 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3001 val = fetch_long(emu, emu->x86.R_ES,
3003 cmp_long(emu, emu->x86.R_EAX, val);
3005 val = fetch_word(emu, emu->x86.R_ES,
3007 cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
3010 emu->x86.R_DI += inc;
3011 if (ACCESS_FLAG(F_ZF))
3012 break; /* zero flag set means equal */
3014 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
3016 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3017 val = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
3018 cmp_long(emu, emu->x86.R_EAX, val);
3020 val = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
3021 cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
3023 emu->x86.R_DI += inc;
3029 * Handles opcode 0xb8
3032 x86emuOp_mov_word_AX_IMM(struct x86emu *emu)
3034 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3035 emu->x86.R_EAX = fetch_long_imm(emu);
3037 emu->x86.R_AX = fetch_word_imm(emu);
3042 * Handles opcode 0xb9
3045 x86emuOp_mov_word_CX_IMM(struct x86emu *emu)
3047 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3048 emu->x86.R_ECX = fetch_long_imm(emu);
3050 emu->x86.R_CX = fetch_word_imm(emu);
3055 * Handles opcode 0xba
3058 x86emuOp_mov_word_DX_IMM(struct x86emu *emu)
3060 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3061 emu->x86.R_EDX = fetch_long_imm(emu);
3063 emu->x86.R_DX = fetch_word_imm(emu);
3068 * Handles opcode 0xbb
3071 x86emuOp_mov_word_BX_IMM(struct x86emu *emu)
3073 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3074 emu->x86.R_EBX = fetch_long_imm(emu);
3076 emu->x86.R_BX = fetch_word_imm(emu);
3081 * Handles opcode 0xbc
3084 x86emuOp_mov_word_SP_IMM(struct x86emu *emu)
3086 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3087 emu->x86.R_ESP = fetch_long_imm(emu);
3089 emu->x86.R_SP = fetch_word_imm(emu);
3094 * Handles opcode 0xbd
3097 x86emuOp_mov_word_BP_IMM(struct x86emu *emu)
3099 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3100 emu->x86.R_EBP = fetch_long_imm(emu);
3102 emu->x86.R_BP = fetch_word_imm(emu);
3107 * Handles opcode 0xbe
3110 x86emuOp_mov_word_SI_IMM(struct x86emu *emu)
3112 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3113 emu->x86.R_ESI = fetch_long_imm(emu);
3115 emu->x86.R_SI = fetch_word_imm(emu);
3120 * Handles opcode 0xbf
3123 x86emuOp_mov_word_DI_IMM(struct x86emu *emu)
3125 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3126 emu->x86.R_EDI = fetch_long_imm(emu);
3128 emu->x86.R_DI = fetch_word_imm(emu);
3130 /* used by opcodes c0, d0, and d2. */
3132 uint8_t(* const opcD0_byte_operation[])
3133 (struct x86emu *, uint8_t d, uint8_t s) =
3141 shl_byte, /* sal_byte === shl_byte by definition */
3147 * Handles opcode 0xc0
3150 x86emuOp_opcC0_byte_RM_MEM(struct x86emu *emu)
3152 uint8_t destval, amt;
3155 * Yet another weirdo special case instruction format. Part of
3156 * the opcode held below in "RH". Doubly nested case would
3157 * result, except that the decoded instruction
3159 fetch_decode_modrm(emu);
3160 /* know operation, decode the mod byte to find the addressing mode. */
3161 destval = decode_and_fetch_byte_imm8(emu, &amt);
3162 destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, amt);
3163 write_back_byte(emu, destval);
3165 /* used by opcodes c1, d1, and d3. */
3167 uint16_t(* const opcD1_word_operation[])
3168 (struct x86emu *, uint16_t s, uint8_t d) =
3176 shl_word, /* sal_byte === shl_byte by definition */
3179 /* used by opcodes c1, d1, and d3. */
3181 uint32_t(* const opcD1_long_operation[])
3182 (struct x86emu *, uint32_t s, uint8_t d) =
3190 shl_long, /* sal_byte === shl_byte by definition */
3196 * Handles opcode 0xc1
3199 x86emuOp_opcC1_word_RM_MEM(struct x86emu *emu)
3204 * Yet another weirdo special case instruction format. Part of
3205 * the opcode held below in "RH". Doubly nested case would
3206 * result, except that the decoded instruction
3208 fetch_decode_modrm(emu);
3209 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3212 destval = decode_and_fetch_long_imm8(emu, &amt);
3213 destval = (*opcD1_long_operation[emu->cur_rh])
3214 (emu, destval, amt);
3215 write_back_long(emu, destval);
3219 destval = decode_and_fetch_word_imm8(emu, &amt);
3220 destval = (*opcD1_word_operation[emu->cur_rh])
3221 (emu, destval, amt);
3222 write_back_word(emu, destval);
3228 * Handles opcode 0xc2
3231 x86emuOp_ret_near_IMM(struct x86emu *emu)
3235 imm = fetch_word_imm(emu);
3236 emu->x86.R_IP = pop_word(emu);
3237 emu->x86.R_SP += imm;
3242 * Handles opcode 0xc6
3245 x86emuOp_mov_byte_RM_IMM(struct x86emu *emu)
3248 uint32_t destoffset;
3251 fetch_decode_modrm(emu);
3252 if (emu->cur_rh != 0)
3253 x86emu_halt_sys(emu);
3254 if (emu->cur_mod != 3) {
3255 destoffset = decode_rl_address(emu);
3256 imm = fetch_byte_imm(emu);
3257 store_data_byte(emu, destoffset, imm);
3259 destreg = decode_rl_byte_register(emu);
3260 imm = fetch_byte_imm(emu);
3267 * Handles opcode 0xc7
3270 x86emuOp32_mov_word_RM_IMM(struct x86emu *emu)
3272 uint32_t destoffset;
3273 uint32_t imm, *destreg;
3275 fetch_decode_modrm(emu);
3276 if (emu->cur_rh != 0)
3277 x86emu_halt_sys(emu);
3279 if (emu->cur_mod != 3) {
3280 destoffset = decode_rl_address(emu);
3281 imm = fetch_long_imm(emu);
3282 store_data_long(emu, destoffset, imm);
3284 destreg = decode_rl_long_register(emu);
3285 imm = fetch_long_imm(emu);
3291 x86emuOp16_mov_word_RM_IMM(struct x86emu *emu)
3293 uint32_t destoffset;
3294 uint16_t imm, *destreg;
3296 fetch_decode_modrm(emu);
3297 if (emu->cur_rh != 0)
3298 x86emu_halt_sys(emu);
3300 if (emu->cur_mod != 3) {
3301 destoffset = decode_rl_address(emu);
3302 imm = fetch_word_imm(emu);
3303 store_data_word(emu, destoffset, imm);
3305 destreg = decode_rl_word_register(emu);
3306 imm = fetch_word_imm(emu);
3312 x86emuOp_mov_word_RM_IMM(struct x86emu *emu)
3314 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3315 x86emuOp32_mov_word_RM_IMM(emu);
3317 x86emuOp16_mov_word_RM_IMM(emu);
3322 * Handles opcode 0xc8
3325 x86emuOp_enter(struct x86emu *emu)
3327 uint16_t local, frame_pointer;
3331 local = fetch_word_imm(emu);
3332 nesting = fetch_byte_imm(emu);
3333 push_word(emu, emu->x86.R_BP);
3334 frame_pointer = emu->x86.R_SP;
3336 for (i = 1; i < nesting; i++) {
3338 push_word(emu, fetch_word(emu, emu->x86.R_SS,
3341 push_word(emu, frame_pointer);
3343 emu->x86.R_BP = frame_pointer;
3344 emu->x86.R_SP = (uint16_t) (emu->x86.R_SP - local);
3349 * Handles opcode 0xc9
3352 x86emuOp_leave(struct x86emu *emu)
3354 emu->x86.R_SP = emu->x86.R_BP;
3355 emu->x86.R_BP = pop_word(emu);
3360 * Handles opcode 0xca
3363 x86emuOp_ret_far_IMM(struct x86emu *emu)
3367 imm = fetch_word_imm(emu);
3368 emu->x86.R_IP = pop_word(emu);
3369 emu->x86.R_CS = pop_word(emu);
3370 emu->x86.R_SP += imm;
3375 * Handles opcode 0xcb
3378 x86emuOp_ret_far(struct x86emu *emu)
3380 emu->x86.R_IP = pop_word(emu);
3381 emu->x86.R_CS = pop_word(emu);
3386 * Handles opcode 0xcc
3389 x86emuOp_int3(struct x86emu *emu)
3391 x86emu_intr_dispatch(emu, 3);
3396 * Handles opcode 0xcd
3399 x86emuOp_int_IMM(struct x86emu *emu)
3403 intnum = fetch_byte_imm(emu);
3404 x86emu_intr_dispatch(emu, intnum);
3409 * Handles opcode 0xce
3412 x86emuOp_into(struct x86emu *emu)
3414 if (ACCESS_FLAG(F_OF))
3415 x86emu_intr_dispatch(emu, 4);
3420 * Handles opcode 0xcf
3423 x86emuOp_iret(struct x86emu *emu)
3425 emu->x86.R_IP = pop_word(emu);
3426 emu->x86.R_CS = pop_word(emu);
3427 emu->x86.R_FLG = pop_word(emu);
3432 * Handles opcode 0xd0
3435 x86emuOp_opcD0_byte_RM_1(struct x86emu *emu)
3439 fetch_decode_modrm(emu);
3440 destval = decode_and_fetch_byte(emu);
3441 destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, 1);
3442 write_back_byte(emu, destval);
3447 * Handles opcode 0xd1
3450 x86emuOp_opcD1_word_RM_1(struct x86emu *emu)
3452 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3455 fetch_decode_modrm(emu);
3456 destval = decode_and_fetch_long(emu);
3457 destval = (*opcD1_long_operation[emu->cur_rh])(emu, destval, 1);
3458 write_back_long(emu, destval);
3462 fetch_decode_modrm(emu);
3463 destval = decode_and_fetch_word(emu);
3464 destval = (*opcD1_word_operation[emu->cur_rh])(emu, destval, 1);
3465 write_back_word(emu, destval);
3471 * Handles opcode 0xd2
3474 x86emuOp_opcD2_byte_RM_CL(struct x86emu *emu)
3478 fetch_decode_modrm(emu);
3479 destval = decode_and_fetch_byte(emu);
3480 destval = (*opcD0_byte_operation[emu->cur_rh])
3481 (emu, destval, emu->x86.R_CL);
3482 write_back_byte(emu, destval);
3487 * Handles opcode 0xd3
3490 x86emuOp_opcD3_word_RM_CL(struct x86emu *emu)
3492 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3495 fetch_decode_modrm(emu);
3496 destval = decode_and_fetch_long(emu);
3497 destval = (*opcD1_long_operation[emu->cur_rh])
3498 (emu, destval, emu->x86.R_CL);
3499 write_back_long(emu, destval);
3503 fetch_decode_modrm(emu);
3504 destval = decode_and_fetch_word(emu);
3505 destval = (*opcD1_word_operation[emu->cur_rh])
3506 (emu, destval, emu->x86.R_CL);
3507 write_back_word(emu, destval);
3513 * Handles opcode 0xd4
3516 x86emuOp_aam(struct x86emu *emu)
3520 a = fetch_byte_imm(emu); /* this is a stupid encoding. */
3522 /* fix: add base decoding aam_word(uint8_t val, int base a) */
3523 x86emu_halt_sys(emu);
3525 /* note the type change here --- returning AL and AH in AX. */
3526 emu->x86.R_AX = aam_word(emu, emu->x86.R_AL);
3531 * Handles opcode 0xd5
3534 x86emuOp_aad(struct x86emu *emu)
3538 a = fetch_byte_imm(emu);
3540 /* fix: add base decoding aad_word(uint16_t val, int base a) */
3541 x86emu_halt_sys(emu);
3543 emu->x86.R_AX = aad_word(emu, emu->x86.R_AX);
3545 /* opcode 0xd6 ILLEGAL OPCODE */
3550 * Handles opcode 0xd7
3553 x86emuOp_xlat(struct x86emu *emu)
3557 addr = (uint16_t) (emu->x86.R_BX + (uint8_t) emu->x86.R_AL);
3558 emu->x86.R_AL = fetch_data_byte(emu, addr);
3563 x86emuOp_esc_coprocess_d8(struct x86emu *emu)
3568 x86emuOp_esc_coprocess_d9(struct x86emu *emu)
3570 fetch_decode_modrm(emu);
3571 if (emu->cur_mod != 3)
3572 decode_rl_address(emu);
3576 x86emuOp_esc_coprocess_da(struct x86emu *emu)
3578 fetch_decode_modrm(emu);
3579 if (emu->cur_mod != 3)
3580 decode_rl_address(emu);
3584 x86emuOp_esc_coprocess_db(struct x86emu *emu)
3586 fetch_decode_modrm(emu);
3587 if (emu->cur_mod != 3)
3588 decode_rl_address(emu);
3592 x86emuOp_esc_coprocess_dc(struct x86emu *emu)
3594 fetch_decode_modrm(emu);
3595 if (emu->cur_mod != 3)
3596 decode_rl_address(emu);
3600 x86emuOp_esc_coprocess_dd(struct x86emu *emu)
3602 fetch_decode_modrm(emu);
3603 if (emu->cur_mod != 3)
3604 decode_rl_address(emu);
3608 x86emuOp_esc_coprocess_de(struct x86emu *emu)
3610 fetch_decode_modrm(emu);
3611 if (emu->cur_mod != 3)
3612 decode_rl_address(emu);
3616 x86emuOp_esc_coprocess_df(struct x86emu *emu)
3618 fetch_decode_modrm(emu);
3619 if (emu->cur_mod != 3)
3620 decode_rl_address(emu);
3626 * Handles opcode 0xe0
3629 x86emuOp_loopne(struct x86emu *emu)
3633 ip = (int8_t) fetch_byte_imm(emu);
3634 ip += (int16_t) emu->x86.R_IP;
3636 if (emu->x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */
3642 * Handles opcode 0xe1
3645 x86emuOp_loope(struct x86emu *emu)
3649 ip = (int8_t) fetch_byte_imm(emu);
3650 ip += (int16_t) emu->x86.R_IP;
3652 if (emu->x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */
3658 * Handles opcode 0xe2
3661 x86emuOp_loop(struct x86emu *emu)
3665 ip = (int8_t) fetch_byte_imm(emu);
3666 ip += (int16_t) emu->x86.R_IP;
3668 if (emu->x86.R_CX != 0)
3674 * Handles opcode 0xe3
3677 x86emuOp_jcxz(struct x86emu *emu)
3682 /* jump to byte offset if overflow flag is set */
3683 offset = (int8_t) fetch_byte_imm(emu);
3684 target = (uint16_t) (emu->x86.R_IP + offset);
3685 if (emu->x86.R_CX == 0)
3686 emu->x86.R_IP = target;
3691 * Handles opcode 0xe4
3694 x86emuOp_in_byte_AL_IMM(struct x86emu *emu)
3698 port = (uint8_t) fetch_byte_imm(emu);
3699 emu->x86.R_AL = (*emu->emu_inb) (emu, port);
3704 * Handles opcode 0xe5
3707 x86emuOp_in_word_AX_IMM(struct x86emu *emu)
3711 port = (uint8_t) fetch_byte_imm(emu);
3712 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3713 emu->x86.R_EAX = (*emu->emu_inl) (emu, port);
3715 emu->x86.R_AX = (*emu->emu_inw) (emu, port);
3721 * Handles opcode 0xe6
3724 x86emuOp_out_byte_IMM_AL(struct x86emu *emu)
3728 port = (uint8_t) fetch_byte_imm(emu);
3729 (*emu->emu_outb) (emu, port, emu->x86.R_AL);
3734 * Handles opcode 0xe7
3737 x86emuOp_out_word_IMM_AX(struct x86emu *emu)
3741 port = (uint8_t) fetch_byte_imm(emu);
3742 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3743 (*emu->emu_outl) (emu, port, emu->x86.R_EAX);
3745 (*emu->emu_outw) (emu, port, emu->x86.R_AX);
3751 * Handles opcode 0xe8
3754 x86emuOp_call_near_IMM(struct x86emu *emu)
3756 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3758 ip = (int32_t) fetch_long_imm(emu);
3759 ip += (int32_t) emu->x86.R_EIP;
3760 push_long(emu, emu->x86.R_EIP);
3761 emu->x86.R_EIP = ip;
3764 ip = (int16_t) fetch_word_imm(emu);
3765 ip += (int16_t) emu->x86.R_IP; /* CHECK SIGN */
3766 push_word(emu, emu->x86.R_IP);
3773 * Handles opcode 0xe9
3776 x86emuOp_jump_near_IMM(struct x86emu *emu)
3780 ip = (int16_t) fetch_word_imm(emu);
3781 ip += (int16_t) emu->x86.R_IP;
3782 emu->x86.R_IP = (uint16_t) ip;
3787 * Handles opcode 0xea
3790 x86emuOp_jump_far_IMM(struct x86emu *emu)
3794 ip = fetch_word_imm(emu);
3795 cs = fetch_word_imm(emu);
3802 * Handles opcode 0xeb
3805 x86emuOp_jump_byte_IMM(struct x86emu *emu)
3810 offset = (int8_t) fetch_byte_imm(emu);
3811 target = (uint16_t) (emu->x86.R_IP + offset);
3812 emu->x86.R_IP = target;
3817 * Handles opcode 0xec
3820 x86emuOp_in_byte_AL_DX(struct x86emu *emu)
3822 emu->x86.R_AL = (*emu->emu_inb) (emu, emu->x86.R_DX);
3827 * Handles opcode 0xed
3830 x86emuOp_in_word_AX_DX(struct x86emu *emu)
3832 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3833 emu->x86.R_EAX = (*emu->emu_inl) (emu, emu->x86.R_DX);
3835 emu->x86.R_AX = (*emu->emu_inw) (emu, emu->x86.R_DX);
3841 * Handles opcode 0xee
3844 x86emuOp_out_byte_DX_AL(struct x86emu *emu)
3846 (*emu->emu_outb) (emu, emu->x86.R_DX, emu->x86.R_AL);
3851 * Handles opcode 0xef
3854 x86emuOp_out_word_DX_AX(struct x86emu *emu)
3856 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3857 (*emu->emu_outl) (emu, emu->x86.R_DX, emu->x86.R_EAX);
3859 (*emu->emu_outw) (emu, emu->x86.R_DX, emu->x86.R_AX);
3865 * Handles opcode 0xf0
3868 x86emuOp_lock(struct x86emu *emu)
3871 /*opcode 0xf1 ILLEGAL OPERATION */
3876 * Handles opcode 0xf5
3879 x86emuOp_cmc(struct x86emu *emu)
3881 if (ACCESS_FLAG(F_CF))
3889 * Handles opcode 0xf6
3892 x86emuOp_opcF6_byte_RM(struct x86emu *emu)
3894 uint8_t destval, srcval;
3896 /* long, drawn out code follows. Double switch for a total of 32
3898 fetch_decode_modrm(emu);
3899 if (emu->cur_rh == 1)
3900 x86emu_halt_sys(emu);
3902 if (emu->cur_rh == 0) {
3903 destval = decode_and_fetch_byte_imm8(emu, &srcval);
3904 test_byte(emu, destval, srcval);
3907 destval = decode_and_fetch_byte(emu);
3908 switch (emu->cur_rh) {
3911 write_back_byte(emu, destval);
3914 destval = neg_byte(emu, destval);
3915 write_back_byte(emu, destval);
3918 mul_byte(emu, destval);
3921 imul_byte(emu, destval);
3924 div_byte(emu, destval);
3927 idiv_byte(emu, destval);
3934 * Handles opcode 0xf7
3937 x86emuOp32_opcF7_word_RM(struct x86emu *emu)
3939 uint32_t destval, srcval;
3941 /* long, drawn out code follows. Double switch for a total of 32
3943 fetch_decode_modrm(emu);
3944 if (emu->cur_rh == 1)
3945 x86emu_halt_sys(emu);
3947 if (emu->cur_rh == 0) {
3948 if (emu->cur_mod != 3) {
3949 uint32_t destoffset;
3951 destoffset = decode_rl_address(emu);
3952 srcval = fetch_long_imm(emu);
3953 destval = fetch_data_long(emu, destoffset);
3955 srcval = fetch_long_imm(emu);
3956 destval = *decode_rl_long_register(emu);
3958 test_long(emu, destval, srcval);
3961 destval = decode_and_fetch_long(emu);
3962 switch (emu->cur_rh) {
3965 write_back_long(emu, destval);
3968 destval = neg_long(emu, destval);
3969 write_back_long(emu, destval);
3972 mul_long(emu, destval);
3975 imul_long(emu, destval);
3978 div_long(emu, destval);
3981 idiv_long(emu, destval);
3986 x86emuOp16_opcF7_word_RM(struct x86emu *emu)
3988 uint16_t destval, srcval;
3990 /* long, drawn out code follows. Double switch for a total of 32
3992 fetch_decode_modrm(emu);
3993 if (emu->cur_rh == 1)
3994 x86emu_halt_sys(emu);
3996 if (emu->cur_rh == 0) {
3997 if (emu->cur_mod != 3) {
3998 uint32_t destoffset;
4000 destoffset = decode_rl_address(emu);
4001 srcval = fetch_word_imm(emu);
4002 destval = fetch_data_word(emu, destoffset);
4004 srcval = fetch_word_imm(emu);
4005 destval = *decode_rl_word_register(emu);
4007 test_word(emu, destval, srcval);
4010 destval = decode_and_fetch_word(emu);
4011 switch (emu->cur_rh) {
4014 write_back_word(emu, destval);
4017 destval = neg_word(emu, destval);
4018 write_back_word(emu, destval);
4021 mul_word(emu, destval);
4024 imul_word(emu, destval);
4027 div_word(emu, destval);
4030 idiv_word(emu, destval);
4035 x86emuOp_opcF7_word_RM(struct x86emu *emu)
4037 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
4038 x86emuOp32_opcF7_word_RM(emu);
4040 x86emuOp16_opcF7_word_RM(emu);
4045 * Handles opcode 0xfe
4048 x86emuOp_opcFE_byte_RM(struct x86emu *emu)
4051 uint32_t destoffset;
4054 /* Yet another special case instruction. */
4055 fetch_decode_modrm(emu);
4056 if (emu->cur_mod != 3) {
4057 destoffset = decode_rl_address(emu);
4058 switch (emu->cur_rh) {
4059 case 0: /* inc word ptr ... */
4060 destval = fetch_data_byte(emu, destoffset);
4061 destval = inc_byte(emu, destval);
4062 store_data_byte(emu, destoffset, destval);
4064 case 1: /* dec word ptr ... */
4065 destval = fetch_data_byte(emu, destoffset);
4066 destval = dec_byte(emu, destval);
4067 store_data_byte(emu, destoffset, destval);
4071 destreg = decode_rl_byte_register(emu);
4072 switch (emu->cur_rh) {
4074 *destreg = inc_byte(emu, *destreg);
4077 *destreg = dec_byte(emu, *destreg);
4085 * Handles opcode 0xff
4088 x86emuOp32_opcFF_word_RM(struct x86emu *emu)
4090 uint32_t destoffset = 0;
4091 uint32_t destval, *destreg;
4093 if (emu->cur_mod != 3) {
4094 destoffset = decode_rl_address(emu);
4095 destval = fetch_data_long(emu, destoffset);
4096 switch (emu->cur_rh) {
4097 case 0: /* inc word ptr ... */
4098 destval = inc_long(emu, destval);
4099 store_data_long(emu, destoffset, destval);
4101 case 1: /* dec word ptr ... */
4102 destval = dec_long(emu, destval);
4103 store_data_long(emu, destoffset, destval);
4105 case 6: /* push word ptr ... */
4106 push_long(emu, destval);
4110 destreg = decode_rl_long_register(emu);
4111 switch (emu->cur_rh) {
4113 *destreg = inc_long(emu, *destreg);
4116 *destreg = dec_long(emu, *destreg);
4119 push_long(emu, *destreg);
4126 x86emuOp16_opcFF_word_RM(struct x86emu *emu)
4128 uint32_t destoffset = 0;
4132 if (emu->cur_mod != 3) {
4133 destoffset = decode_rl_address(emu);
4134 destval = fetch_data_word(emu, destoffset);
4135 switch (emu->cur_rh) {
4137 destval = inc_word(emu, destval);
4138 store_data_word(emu, destoffset, destval);
4140 case 1: /* dec word ptr ... */
4141 destval = dec_word(emu, destval);
4142 store_data_word(emu, destoffset, destval);
4144 case 6: /* push word ptr ... */
4145 push_word(emu, destval);
4149 destreg = decode_rl_word_register(emu);
4150 switch (emu->cur_rh) {
4152 *destreg = inc_word(emu, *destreg);
4155 *destreg = dec_word(emu, *destreg);
4158 push_word(emu, *destreg);
4165 x86emuOp_opcFF_word_RM(struct x86emu *emu)
4167 uint32_t destoffset = 0;
4168 uint16_t destval, destval2;
4170 /* Yet another special case instruction. */
4171 fetch_decode_modrm(emu);
4172 if ((emu->cur_mod == 3 && (emu->cur_rh == 3 || emu->cur_rh == 5)) ||
4174 x86emu_halt_sys(emu);
4175 if (emu->cur_rh == 0 || emu->cur_rh == 1 || emu->cur_rh == 6) {
4176 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
4177 x86emuOp32_opcFF_word_RM(emu);
4179 x86emuOp16_opcFF_word_RM(emu);
4183 if (emu->cur_mod != 3) {
4184 destoffset = decode_rl_address(emu);
4185 destval = fetch_data_word(emu, destoffset);
4186 switch (emu->cur_rh) {
4187 case 3: /* call far ptr ... */
4188 destval2 = fetch_data_word(emu, destoffset + 2);
4189 push_word(emu, emu->x86.R_CS);
4190 emu->x86.R_CS = destval2;
4191 push_word(emu, emu->x86.R_IP);
4192 emu->x86.R_IP = destval;
4194 case 5: /* jmp far ptr ... */
4195 destval2 = fetch_data_word(emu, destoffset + 2);
4196 emu->x86.R_IP = destval;
4197 emu->x86.R_CS = destval2;
4201 destval = *decode_rl_word_register(emu);
4204 switch (emu->cur_rh) {
4205 case 2: /* call word ptr */
4206 push_word(emu, emu->x86.R_IP);
4207 emu->x86.R_IP = destval;
4210 emu->x86.R_IP = destval;
4216 * * Single byte operation code table:
4219 x86emu_exec_one_byte(struct x86emu * emu)
4223 op1 = fetch_byte_imm(emu);
4227 common_binop_byte_rm_r(emu, add_byte);
4230 common_binop_word_long_rm_r(emu, add_word, add_long);
4233 common_binop_byte_r_rm(emu, add_byte);
4236 common_binop_word_long_r_rm(emu, add_word, add_long);
4239 common_binop_byte_imm(emu, add_byte);
4242 common_binop_word_long_imm(emu, add_word, add_long);
4245 push_word(emu, emu->x86.R_ES);
4248 emu->x86.R_ES = pop_word(emu);
4252 common_binop_byte_rm_r(emu, or_byte);
4255 common_binop_word_long_rm_r(emu, or_word, or_long);
4258 common_binop_byte_r_rm(emu, or_byte);
4261 common_binop_word_long_r_rm(emu, or_word, or_long);
4264 common_binop_byte_imm(emu, or_byte);
4267 common_binop_word_long_imm(emu, or_word, or_long);
4270 push_word(emu, emu->x86.R_CS);
4273 x86emu_exec_two_byte(emu);
4277 common_binop_byte_rm_r(emu, adc_byte);
4280 common_binop_word_long_rm_r(emu, adc_word, adc_long);
4283 common_binop_byte_r_rm(emu, adc_byte);
4286 common_binop_word_long_r_rm(emu, adc_word, adc_long);
4289 common_binop_byte_imm(emu, adc_byte);
4292 common_binop_word_long_imm(emu, adc_word, adc_long);
4295 push_word(emu, emu->x86.R_SS);
4298 emu->x86.R_SS = pop_word(emu);
4302 common_binop_byte_rm_r(emu, sbb_byte);
4305 common_binop_word_long_rm_r(emu, sbb_word, sbb_long);
4308 common_binop_byte_r_rm(emu, sbb_byte);
4311 common_binop_word_long_r_rm(emu, sbb_word, sbb_long);
4314 common_binop_byte_imm(emu, sbb_byte);
4317 common_binop_word_long_imm(emu, sbb_word, sbb_long);
4320 push_word(emu, emu->x86.R_DS);
4323 emu->x86.R_DS = pop_word(emu);
4327 common_binop_byte_rm_r(emu, and_byte);
4330 common_binop_word_long_rm_r(emu, and_word, and_long);
4333 common_binop_byte_r_rm(emu, and_byte);
4336 common_binop_word_long_r_rm(emu, and_word, and_long);
4339 common_binop_byte_imm(emu, and_byte);
4342 common_binop_word_long_imm(emu, and_word, and_long);
4345 emu->x86.mode |= SYSMODE_SEGOVR_ES;
4348 emu->x86.R_AL = daa_byte(emu, emu->x86.R_AL);
4352 common_binop_byte_rm_r(emu, sub_byte);
4355 common_binop_word_long_rm_r(emu, sub_word, sub_long);
4358 common_binop_byte_r_rm(emu, sub_byte);
4361 common_binop_word_long_r_rm(emu, sub_word, sub_long);
4364 common_binop_byte_imm(emu, sub_byte);
4367 common_binop_word_long_imm(emu, sub_word, sub_long);
4370 emu->x86.mode |= SYSMODE_SEGOVR_CS;
4373 emu->x86.R_AL = das_byte(emu, emu->x86.R_AL);
4377 common_binop_byte_rm_r(emu, xor_byte);
4380 common_binop_word_long_rm_r(emu, xor_word, xor_long);
4383 common_binop_byte_r_rm(emu, xor_byte);
4386 common_binop_word_long_r_rm(emu, xor_word, xor_long);
4389 common_binop_byte_imm(emu, xor_byte);
4392 common_binop_word_long_imm(emu, xor_word, xor_long);
4395 emu->x86.mode |= SYSMODE_SEGOVR_SS;
4398 emu->x86.R_AX = aaa_word(emu, emu->x86.R_AX);
4402 common_binop_ns_byte_rm_r(emu, cmp_byte_no_return);
4405 common_binop_ns_word_long_rm_r(emu, cmp_word_no_return,
4406 cmp_long_no_return);
4409 x86emuOp_cmp_byte_R_RM(emu);
4412 x86emuOp_cmp_word_R_RM(emu);
4415 x86emuOp_cmp_byte_AL_IMM(emu);
4418 x86emuOp_cmp_word_AX_IMM(emu);
4421 emu->x86.mode |= SYSMODE_SEGOVR_DS;
4424 emu->x86.R_AX = aas_word(emu, emu->x86.R_AX);
4428 common_inc_word_long(emu, &emu->x86.register_a);
4431 common_inc_word_long(emu, &emu->x86.register_c);
4434 common_inc_word_long(emu, &emu->x86.register_d);
4437 common_inc_word_long(emu, &emu->x86.register_b);
4440 common_inc_word_long(emu, &emu->x86.register_sp);
4443 common_inc_word_long(emu, &emu->x86.register_bp);
4446 common_inc_word_long(emu, &emu->x86.register_si);
4449 common_inc_word_long(emu, &emu->x86.register_di);
4453 common_dec_word_long(emu, &emu->x86.register_a);
4456 common_dec_word_long(emu, &emu->x86.register_c);
4459 common_dec_word_long(emu, &emu->x86.register_d);
4462 common_dec_word_long(emu, &emu->x86.register_b);
4465 common_dec_word_long(emu, &emu->x86.register_sp);
4468 common_dec_word_long(emu, &emu->x86.register_bp);
4471 common_dec_word_long(emu, &emu->x86.register_si);
4474 common_dec_word_long(emu, &emu->x86.register_di);
4478 common_push_word_long(emu, &emu->x86.register_a);
4481 common_push_word_long(emu, &emu->x86.register_c);
4484 common_push_word_long(emu, &emu->x86.register_d);
4487 common_push_word_long(emu, &emu->x86.register_b);
4490 common_push_word_long(emu, &emu->x86.register_sp);
4493 common_push_word_long(emu, &emu->x86.register_bp);
4496 common_push_word_long(emu, &emu->x86.register_si);
4499 common_push_word_long(emu, &emu->x86.register_di);
4503 common_pop_word_long(emu, &emu->x86.register_a);
4506 common_pop_word_long(emu, &emu->x86.register_c);
4509 common_pop_word_long(emu, &emu->x86.register_d);
4512 common_pop_word_long(emu, &emu->x86.register_b);
4515 common_pop_word_long(emu, &emu->x86.register_sp);
4518 common_pop_word_long(emu, &emu->x86.register_bp);
4521 common_pop_word_long(emu, &emu->x86.register_si);
4524 common_pop_word_long(emu, &emu->x86.register_di);
4528 x86emuOp_push_all(emu);
4531 x86emuOp_pop_all(emu);
4536 emu->x86.mode |= SYSMODE_SEGOVR_FS;
4539 emu->x86.mode |= SYSMODE_SEGOVR_GS;
4542 emu->x86.mode |= SYSMODE_PREFIX_DATA;
4545 emu->x86.mode |= SYSMODE_PREFIX_ADDR;
4549 x86emuOp_push_word_IMM(emu);
4552 common_imul_imm(emu, 0);
4555 x86emuOp_push_byte_IMM(emu);
4558 common_imul_imm(emu, 1);
4564 x86emuOp_ins_word(emu);
4570 x86emuOp_outs_word(emu);
4574 common_jmp_near(emu, ACCESS_FLAG(F_OF));
4577 common_jmp_near(emu, !ACCESS_FLAG(F_OF));
4580 common_jmp_near(emu, ACCESS_FLAG(F_CF));
4583 common_jmp_near(emu, !ACCESS_FLAG(F_CF));
4586 common_jmp_near(emu, ACCESS_FLAG(F_ZF));
4589 common_jmp_near(emu, !ACCESS_FLAG(F_ZF));
4592 common_jmp_near(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
4595 common_jmp_near(emu, !ACCESS_FLAG(F_CF) && !ACCESS_FLAG(F_ZF));
4599 common_jmp_near(emu, ACCESS_FLAG(F_SF));
4602 common_jmp_near(emu, !ACCESS_FLAG(F_SF));
4605 common_jmp_near(emu, ACCESS_FLAG(F_PF));
4608 common_jmp_near(emu, !ACCESS_FLAG(F_PF));
4611 x86emuOp_jump_near_L(emu);
4614 x86emuOp_jump_near_NL(emu);
4617 x86emuOp_jump_near_LE(emu);
4620 x86emuOp_jump_near_NLE(emu);
4624 x86emuOp_opc80_byte_RM_IMM(emu);
4627 x86emuOp_opc81_word_RM_IMM(emu);
4630 x86emuOp_opc82_byte_RM_IMM(emu);
4633 x86emuOp_opc83_word_RM_IMM(emu);
4636 common_binop_ns_byte_rm_r(emu, test_byte);
4639 common_binop_ns_word_long_rm_r(emu, test_word, test_long);
4642 x86emuOp_xchg_byte_RM_R(emu);
4645 x86emuOp_xchg_word_RM_R(emu);
4649 x86emuOp_mov_byte_RM_R(emu);
4652 x86emuOp_mov_word_RM_R(emu);
4655 x86emuOp_mov_byte_R_RM(emu);
4658 x86emuOp_mov_word_R_RM(emu);
4661 x86emuOp_mov_word_RM_SR(emu);
4664 x86emuOp_lea_word_R_M(emu);
4667 x86emuOp_mov_word_SR_RM(emu);
4670 x86emuOp_pop_RM(emu);
4677 x86emuOp_xchg_word_AX_CX(emu);
4680 x86emuOp_xchg_word_AX_DX(emu);
4683 x86emuOp_xchg_word_AX_BX(emu);
4686 x86emuOp_xchg_word_AX_SP(emu);
4689 x86emuOp_xchg_word_AX_BP(emu);
4692 x86emuOp_xchg_word_AX_SI(emu);
4695 x86emuOp_xchg_word_AX_DI(emu);
4705 x86emuOp_call_far_IMM(emu);
4711 x86emuOp_pushf_word(emu);
4714 x86emuOp_popf_word(emu);
4724 x86emuOp_mov_AL_M_IMM(emu);
4727 x86emuOp_mov_AX_M_IMM(emu);
4730 x86emuOp_mov_M_AL_IMM(emu);
4733 x86emuOp_mov_M_AX_IMM(emu);
4736 x86emuOp_movs_byte(emu);
4739 x86emuOp_movs_word(emu);
4742 x86emuOp_cmps_byte(emu);
4745 x86emuOp_cmps_word(emu);
4749 test_byte(emu, emu->x86.R_AL, fetch_byte_imm(emu));
4752 x86emuOp_test_AX_IMM(emu);
4755 x86emuOp_stos_byte(emu);
4758 x86emuOp_stos_word(emu);
4761 x86emuOp_lods_byte(emu);
4764 x86emuOp_lods_word(emu);
4767 x86emuOp_scas_byte(emu);
4770 x86emuOp_scas_word(emu);
4774 emu->x86.R_AL = fetch_byte_imm(emu);
4777 emu->x86.R_CL = fetch_byte_imm(emu);
4780 emu->x86.R_DL = fetch_byte_imm(emu);
4783 emu->x86.R_BL = fetch_byte_imm(emu);
4786 emu->x86.R_AH = fetch_byte_imm(emu);
4789 emu->x86.R_CH = fetch_byte_imm(emu);
4792 emu->x86.R_DH = fetch_byte_imm(emu);
4795 emu->x86.R_BH = fetch_byte_imm(emu);
4799 x86emuOp_mov_word_AX_IMM(emu);
4802 x86emuOp_mov_word_CX_IMM(emu);
4805 x86emuOp_mov_word_DX_IMM(emu);
4808 x86emuOp_mov_word_BX_IMM(emu);
4812 x86emuOp_mov_word_SP_IMM(emu);
4815 x86emuOp_mov_word_BP_IMM(emu);
4818 x86emuOp_mov_word_SI_IMM(emu);
4821 x86emuOp_mov_word_DI_IMM(emu);
4825 x86emuOp_opcC0_byte_RM_MEM(emu);
4828 x86emuOp_opcC1_word_RM_MEM(emu);
4831 x86emuOp_ret_near_IMM(emu);
4834 emu->x86.R_IP = pop_word(emu);
4837 common_load_far_pointer(emu, &emu->x86.R_ES);
4840 common_load_far_pointer(emu, &emu->x86.R_DS);
4843 x86emuOp_mov_byte_RM_IMM(emu);
4846 x86emuOp_mov_word_RM_IMM(emu);
4849 x86emuOp_enter(emu);
4852 x86emuOp_leave(emu);
4855 x86emuOp_ret_far_IMM(emu);
4858 x86emuOp_ret_far(emu);
4864 x86emuOp_int_IMM(emu);
4874 x86emuOp_opcD0_byte_RM_1(emu);
4877 x86emuOp_opcD1_word_RM_1(emu);
4880 x86emuOp_opcD2_byte_RM_CL(emu);
4883 x86emuOp_opcD3_word_RM_CL(emu);
4891 /* 0xd6 Undocumented SETALC instruction */
4896 x86emuOp_esc_coprocess_d8(emu);
4899 x86emuOp_esc_coprocess_d9(emu);
4902 x86emuOp_esc_coprocess_da(emu);
4905 x86emuOp_esc_coprocess_db(emu);
4908 x86emuOp_esc_coprocess_dc(emu);
4911 x86emuOp_esc_coprocess_dd(emu);
4914 x86emuOp_esc_coprocess_de(emu);
4917 x86emuOp_esc_coprocess_df(emu);
4921 x86emuOp_loopne(emu);
4924 x86emuOp_loope(emu);
4933 x86emuOp_in_byte_AL_IMM(emu);
4936 x86emuOp_in_word_AX_IMM(emu);
4939 x86emuOp_out_byte_IMM_AL(emu);
4942 x86emuOp_out_word_IMM_AX(emu);
4946 x86emuOp_call_near_IMM(emu);
4949 x86emuOp_jump_near_IMM(emu);
4952 x86emuOp_jump_far_IMM(emu);
4955 x86emuOp_jump_byte_IMM(emu);
4958 x86emuOp_in_byte_AL_DX(emu);
4961 x86emuOp_in_word_AX_DX(emu);
4964 x86emuOp_out_byte_DX_AL(emu);
4967 x86emuOp_out_word_DX_AX(emu);
4974 emu->x86.mode |= SYSMODE_PREFIX_REPNE;
4977 emu->x86.mode |= SYSMODE_PREFIX_REPE;
4980 x86emu_halt_sys(emu);
4986 x86emuOp_opcF6_byte_RM(emu);
4989 x86emuOp_opcF7_word_RM(emu);
5011 x86emuOp_opcFE_byte_RM(emu);
5014 x86emuOp_opcFF_word_RM(emu);
5017 x86emu_halt_sys(emu);
5020 if (op1 != 0x26 && op1 != 0x2e && op1 != 0x36 && op1 != 0x3e &&
5022 emu->x86.mode &= ~SYSMODE_CLRMASK;
5026 common_jmp_long(struct x86emu *emu, int cond)
5030 target = (int16_t) fetch_word_imm(emu);
5031 target += (int16_t) emu->x86.R_IP;
5033 emu->x86.R_IP = (uint16_t) target;
5037 common_set_byte(struct x86emu *emu, int cond)
5039 uint32_t destoffset;
5040 uint8_t *destreg, destval;
5042 fetch_decode_modrm(emu);
5043 destval = cond ? 0x01 : 0x00;
5044 if (emu->cur_mod != 3) {
5045 destoffset = decode_rl_address(emu);
5046 store_data_byte(emu, destoffset, destval);
5048 destreg = decode_rl_byte_register(emu);
5054 common_bitstring32(struct x86emu *emu, int op)
5057 uint32_t srcval, *shiftreg, mask;
5059 fetch_decode_modrm(emu);
5060 shiftreg = decode_rh_long_register(emu);
5061 srcval = decode_and_fetch_long_disp(emu, (int16_t) *shiftreg >> 5);
5062 bit = *shiftreg & 0x1F;
5064 CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5070 write_back_long(emu, srcval | mask);
5073 write_back_long(emu, srcval & ~mask);
5076 write_back_long(emu, srcval ^ mask);
5082 common_bitstring16(struct x86emu *emu, int op)
5085 uint16_t srcval, *shiftreg, mask;
5087 fetch_decode_modrm(emu);
5088 shiftreg = decode_rh_word_register(emu);
5089 srcval = decode_and_fetch_word_disp(emu, (int16_t) *shiftreg >> 4);
5090 bit = *shiftreg & 0xF;
5092 CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5098 write_back_word(emu, srcval | mask);
5101 write_back_word(emu, srcval & ~mask);
5104 write_back_word(emu, srcval ^ mask);
5110 common_bitstring(struct x86emu *emu, int op)
5112 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5113 common_bitstring32(emu, op);
5115 common_bitstring16(emu, op);
5119 common_bitsearch32(struct x86emu *emu, int diff)
5121 uint32_t srcval, *dstreg;
5123 fetch_decode_modrm(emu);
5124 dstreg = decode_rh_long_register(emu);
5125 srcval = decode_and_fetch_long(emu);
5126 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
5127 for (*dstreg = 0; *dstreg < 32; *dstreg += diff) {
5128 if ((srcval >> *dstreg) & 1)
5134 common_bitsearch16(struct x86emu *emu, int diff)
5136 uint16_t srcval, *dstreg;
5138 fetch_decode_modrm(emu);
5139 dstreg = decode_rh_word_register(emu);
5140 srcval = decode_and_fetch_word(emu);
5141 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
5142 for (*dstreg = 0; *dstreg < 16; *dstreg += diff) {
5143 if ((srcval >> *dstreg) & 1)
5149 common_bitsearch(struct x86emu *emu, int diff)
5151 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5152 common_bitsearch32(emu, diff);
5154 common_bitsearch16(emu, diff);
5158 common_shift32(struct x86emu *emu, int shift_left, int use_cl)
5161 uint32_t destval, *shiftreg;
5163 fetch_decode_modrm(emu);
5164 shiftreg = decode_rh_long_register(emu);
5166 destval = decode_and_fetch_long(emu);
5167 shift = emu->x86.R_CL;
5169 destval = decode_and_fetch_long_imm8(emu, &shift);
5172 destval = shld_long(emu, destval, *shiftreg, shift);
5174 destval = shrd_long(emu, destval, *shiftreg, shift);
5175 write_back_long(emu, destval);
5179 common_shift16(struct x86emu *emu, int shift_left, int use_cl)
5182 uint16_t destval, *shiftreg;
5184 fetch_decode_modrm(emu);
5185 shiftreg = decode_rh_word_register(emu);
5187 destval = decode_and_fetch_word(emu);
5188 shift = emu->x86.R_CL;
5190 destval = decode_and_fetch_word_imm8(emu, &shift);
5193 destval = shld_word(emu, destval, *shiftreg, shift);
5195 destval = shrd_word(emu, destval, *shiftreg, shift);
5196 write_back_word(emu, destval);
5200 common_shift(struct x86emu *emu, int shift_left, int use_cl)
5202 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5203 common_shift32(emu, shift_left, use_cl);
5205 common_shift16(emu, shift_left, use_cl);
5211 #define xorl(a,b) ((a) && !(b)) || (!(a) && (b))
5216 * Handles opcode 0x0f,0x31
5219 x86emuOp2_rdtsc(struct x86emu *emu)
5221 emu->x86.R_EAX = emu->cur_cycles & 0xffffffff;
5222 emu->x86.R_EDX = emu->cur_cycles >> 32;
5227 * Handles opcode 0x0f,0xa0
5230 x86emuOp2_push_FS(struct x86emu *emu)
5232 push_word(emu, emu->x86.R_FS);
5237 * Handles opcode 0x0f,0xa1
5240 x86emuOp2_pop_FS(struct x86emu *emu)
5242 emu->x86.R_FS = pop_word(emu);
5247 * Handles opcode 0x0f,0xa1
5249 #if defined(__i386__) || defined(__amd64__)
5251 hw_cpuid(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d)
5253 __asm__ __volatile__("cpuid"
5254 : "=a" (*a), "=b" (*b),
5255 "=c" (*c), "=d" (*d)
5256 : "a" (*a), "c" (*c)
5261 x86emuOp2_cpuid(struct x86emu *emu)
5263 #if defined(__i386__) || defined(__amd64__)
5264 hw_cpuid(&emu->x86.R_EAX, &emu->x86.R_EBX, &emu->x86.R_ECX,
5267 switch (emu->x86.R_EAX) {
5270 #if !defined(__i386__) && !defined(__amd64__)
5271 /* "GenuineIntel" */
5272 emu->x86.R_EBX = 0x756e6547;
5273 emu->x86.R_EDX = 0x49656e69;
5274 emu->x86.R_ECX = 0x6c65746e;
5278 #if !defined(__i386__) && !defined(__amd64__)
5279 emu->x86.R_EAX = 0x00000480;
5280 emu->x86.R_EBX = emu->x86.R_ECX = 0;
5281 emu->x86.R_EDX = 0x00000002;
5283 emu->x86.R_EDX &= 0x00000012;
5287 emu->x86.R_EAX = emu->x86.R_EBX = emu->x86.R_ECX =
5295 * Handles opcode 0x0f,0xa3
5298 x86emuOp2_bt_R(struct x86emu *emu)
5300 common_bitstring(emu, 0);
5305 * Handles opcode 0x0f,0xa4
5308 x86emuOp2_shld_IMM(struct x86emu *emu)
5310 common_shift(emu, 1, 0);
5315 * Handles opcode 0x0f,0xa5
5318 x86emuOp2_shld_CL(struct x86emu *emu)
5320 common_shift(emu, 1, 1);
5325 * Handles opcode 0x0f,0xa8
5328 x86emuOp2_push_GS(struct x86emu *emu)
5330 push_word(emu, emu->x86.R_GS);
5335 * Handles opcode 0x0f,0xa9
5338 x86emuOp2_pop_GS(struct x86emu *emu)
5340 emu->x86.R_GS = pop_word(emu);
5345 * Handles opcode 0x0f,0xab
5348 x86emuOp2_bts_R(struct x86emu *emu)
5350 common_bitstring(emu, 1);
5355 * Handles opcode 0x0f,0xac
5358 x86emuOp2_shrd_IMM(struct x86emu *emu)
5360 common_shift(emu, 0, 0);
5365 * Handles opcode 0x0f,0xad
5368 x86emuOp2_shrd_CL(struct x86emu *emu)
5370 common_shift(emu, 0, 1);
5375 * Handles opcode 0x0f,0xaf
5378 x86emuOp2_32_imul_R_RM(struct x86emu *emu)
5380 uint32_t *destreg, srcval;
5383 fetch_decode_modrm(emu);
5384 destreg = decode_rh_long_register(emu);
5385 srcval = decode_and_fetch_long(emu);
5386 res = (int32_t) *destreg * (int32_t)srcval;
5387 if (res > 0xffffffff) {
5394 *destreg = (uint32_t) res;
5398 x86emuOp2_16_imul_R_RM(struct x86emu *emu)
5400 uint16_t *destreg, srcval;
5403 fetch_decode_modrm(emu);
5404 destreg = decode_rh_word_register(emu);
5405 srcval = decode_and_fetch_word(emu);
5406 res = (int16_t) * destreg * (int16_t)srcval;
5414 *destreg = (uint16_t) res;
5418 x86emuOp2_imul_R_RM(struct x86emu *emu)
5420 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5421 x86emuOp2_32_imul_R_RM(emu);
5423 x86emuOp2_16_imul_R_RM(emu);
5428 * Handles opcode 0x0f,0xb2
5431 x86emuOp2_lss_R_IMM(struct x86emu *emu)
5433 common_load_far_pointer(emu, &emu->x86.R_SS);
5438 * Handles opcode 0x0f,0xb3
5441 x86emuOp2_btr_R(struct x86emu *emu)
5443 common_bitstring(emu, 2);
5448 * Handles opcode 0x0f,0xb4
5451 x86emuOp2_lfs_R_IMM(struct x86emu *emu)
5453 common_load_far_pointer(emu, &emu->x86.R_FS);
5458 * Handles opcode 0x0f,0xb5
5461 x86emuOp2_lgs_R_IMM(struct x86emu *emu)
5463 common_load_far_pointer(emu, &emu->x86.R_GS);
5468 * Handles opcode 0x0f,0xb6
5471 x86emuOp2_32_movzx_byte_R_RM(struct x86emu *emu)
5475 fetch_decode_modrm(emu);
5476 destreg = decode_rh_long_register(emu);
5477 *destreg = decode_and_fetch_byte(emu);
5481 x86emuOp2_16_movzx_byte_R_RM(struct x86emu *emu)
5485 fetch_decode_modrm(emu);
5486 destreg = decode_rh_word_register(emu);
5487 *destreg = decode_and_fetch_byte(emu);
5491 x86emuOp2_movzx_byte_R_RM(struct x86emu *emu)
5493 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5494 x86emuOp2_32_movzx_byte_R_RM(emu);
5496 x86emuOp2_16_movzx_byte_R_RM(emu);
5501 * Handles opcode 0x0f,0xb7
5504 x86emuOp2_movzx_word_R_RM(struct x86emu *emu)
5508 fetch_decode_modrm(emu);
5509 destreg = decode_rh_long_register(emu);
5510 *destreg = decode_and_fetch_word(emu);
5515 * Handles opcode 0x0f,0xba
5518 x86emuOp2_32_btX_I(struct x86emu *emu)
5521 uint32_t srcval, mask;
5524 fetch_decode_modrm(emu);
5525 if (emu->cur_rh < 4)
5526 x86emu_halt_sys(emu);
5528 srcval = decode_and_fetch_long_imm8(emu, &shift);
5530 mask = (0x1 << bit);
5532 switch (emu->cur_rh) {
5534 write_back_long(emu, srcval | mask);
5537 write_back_long(emu, srcval & ~mask);
5540 write_back_long(emu, srcval ^ mask);
5543 CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5547 x86emuOp2_16_btX_I(struct x86emu *emu)
5551 uint16_t srcval, mask;
5554 fetch_decode_modrm(emu);
5555 if (emu->cur_rh < 4)
5556 x86emu_halt_sys(emu);
5558 srcval = decode_and_fetch_word_imm8(emu, &shift);
5560 mask = (0x1 << bit);
5561 switch (emu->cur_rh) {
5563 write_back_word(emu, srcval | mask);
5566 write_back_word(emu, srcval & ~mask);
5569 write_back_word(emu, srcval ^ mask);
5572 CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5576 x86emuOp2_btX_I(struct x86emu *emu)
5578 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5579 x86emuOp2_32_btX_I(emu);
5581 x86emuOp2_16_btX_I(emu);
5586 * Handles opcode 0x0f,0xbb
5589 x86emuOp2_btc_R(struct x86emu *emu)
5591 common_bitstring(emu, 3);
5596 * Handles opcode 0x0f,0xbc
5599 x86emuOp2_bsf(struct x86emu *emu)
5601 common_bitsearch(emu, +1);
5606 * Handles opcode 0x0f,0xbd
5609 x86emuOp2_bsr(struct x86emu *emu)
5611 common_bitsearch(emu, -1);
5616 * Handles opcode 0x0f,0xbe
5619 x86emuOp2_32_movsx_byte_R_RM(struct x86emu *emu)
5623 fetch_decode_modrm(emu);
5624 destreg = decode_rh_long_register(emu);
5625 *destreg = (int32_t)(int8_t)decode_and_fetch_byte(emu);
5629 x86emuOp2_16_movsx_byte_R_RM(struct x86emu *emu)
5633 fetch_decode_modrm(emu);
5634 destreg = decode_rh_word_register(emu);
5635 *destreg = (int16_t)(int8_t)decode_and_fetch_byte(emu);
5639 x86emuOp2_movsx_byte_R_RM(struct x86emu *emu)
5641 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5642 x86emuOp2_32_movsx_byte_R_RM(emu);
5644 x86emuOp2_16_movsx_byte_R_RM(emu);
5649 * Handles opcode 0x0f,0xbf
5652 x86emuOp2_movsx_word_R_RM(struct x86emu *emu)
5656 fetch_decode_modrm(emu);
5657 destreg = decode_rh_long_register(emu);
5658 *destreg = (int32_t)(int16_t)decode_and_fetch_word(emu);
5662 x86emu_exec_two_byte(struct x86emu * emu)
5666 op2 = fetch_byte_imm(emu);
5669 /* 0x00 Group F (ring 0 PM) */
5670 /* 0x01 Group G (ring 0 PM) */
5671 /* 0x02 lar (ring 0 PM) */
5672 /* 0x03 lsl (ring 0 PM) */
5673 /* 0x05 loadall (undocumented) */
5674 /* 0x06 clts (ring 0 PM) */
5675 /* 0x07 loadall (undocumented) */
5676 /* 0x08 invd (ring 0 PM) */
5677 /* 0x09 wbinvd (ring 0 PM) */
5679 /* 0x20 mov reg32(op2); break;creg (ring 0 PM) */
5680 /* 0x21 mov reg32(op2); break;dreg (ring 0 PM) */
5681 /* 0x22 mov creg(op2); break;reg32 (ring 0 PM) */
5682 /* 0x23 mov dreg(op2); break;reg32 (ring 0 PM) */
5683 /* 0x24 mov reg32(op2); break;treg (ring 0 PM) */
5684 /* 0x26 mov treg(op2); break;reg32 (ring 0 PM) */
5687 x86emuOp2_rdtsc(emu);
5691 common_jmp_long(emu, ACCESS_FLAG(F_OF));
5694 common_jmp_long(emu, !ACCESS_FLAG(F_OF));
5697 common_jmp_long(emu, ACCESS_FLAG(F_CF));
5700 common_jmp_long(emu, !ACCESS_FLAG(F_CF));
5703 common_jmp_long(emu, ACCESS_FLAG(F_ZF));
5706 common_jmp_long(emu, !ACCESS_FLAG(F_ZF));
5709 common_jmp_long(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
5712 common_jmp_long(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)));
5715 common_jmp_long(emu, ACCESS_FLAG(F_SF));
5718 common_jmp_long(emu, !ACCESS_FLAG(F_SF));
5721 common_jmp_long(emu, ACCESS_FLAG(F_PF));
5724 common_jmp_long(emu, !ACCESS_FLAG(F_PF));
5727 common_jmp_long(emu, xorl(ACCESS_FLAG(F_SF),
5728 ACCESS_FLAG(F_OF)));
5731 common_jmp_long(emu, !(xorl(ACCESS_FLAG(F_SF),
5732 ACCESS_FLAG(F_OF))));
5735 common_jmp_long(emu, (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF))
5736 || ACCESS_FLAG(F_ZF)));
5739 common_jmp_long(emu,
5740 !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
5741 ACCESS_FLAG(F_ZF)));
5745 common_set_byte(emu, ACCESS_FLAG(F_OF));
5748 common_set_byte(emu, !ACCESS_FLAG(F_OF));
5751 common_set_byte(emu, ACCESS_FLAG(F_CF));
5754 common_set_byte(emu, !ACCESS_FLAG(F_CF));
5757 common_set_byte(emu, ACCESS_FLAG(F_ZF));
5760 common_set_byte(emu, !ACCESS_FLAG(F_ZF));
5763 common_set_byte(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
5766 common_set_byte(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)));
5769 common_set_byte(emu, ACCESS_FLAG(F_SF));
5772 common_set_byte(emu, !ACCESS_FLAG(F_SF));
5775 common_set_byte(emu, ACCESS_FLAG(F_PF));
5778 common_set_byte(emu, !ACCESS_FLAG(F_PF));
5781 common_set_byte(emu, xorl(ACCESS_FLAG(F_SF),
5782 ACCESS_FLAG(F_OF)));
5785 common_set_byte(emu, xorl(ACCESS_FLAG(F_SF),
5786 ACCESS_FLAG(F_OF)));
5789 common_set_byte(emu,
5790 (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
5791 ACCESS_FLAG(F_ZF)));
5794 common_set_byte(emu,
5795 !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
5796 ACCESS_FLAG(F_ZF)));
5800 x86emuOp2_push_FS(emu);
5803 x86emuOp2_pop_FS(emu);
5806 x86emuOp2_cpuid(emu);
5809 x86emuOp2_bt_R(emu);
5812 x86emuOp2_shld_IMM(emu);
5815 x86emuOp2_shld_CL(emu);
5818 x86emuOp2_push_GS(emu);
5821 x86emuOp2_pop_GS(emu);
5824 x86emuOp2_bts_R(emu);
5827 x86emuOp2_shrd_IMM(emu);
5830 x86emuOp2_shrd_CL(emu);
5833 x86emuOp2_imul_R_RM(emu);
5836 /* 0xb0 TODO: cmpxchg */
5837 /* 0xb1 TODO: cmpxchg */
5839 x86emuOp2_lss_R_IMM(emu);
5842 x86emuOp2_btr_R(emu);
5845 x86emuOp2_lfs_R_IMM(emu);
5848 x86emuOp2_lgs_R_IMM(emu);
5851 x86emuOp2_movzx_byte_R_RM(emu);
5854 x86emuOp2_movzx_word_R_RM(emu);
5857 x86emuOp2_btX_I(emu);
5860 x86emuOp2_btc_R(emu);
5869 x86emuOp2_movsx_byte_R_RM(emu);
5872 x86emuOp2_movsx_word_R_RM(emu);
5875 /* 0xc0 TODO: xadd */
5876 /* 0xc1 TODO: xadd */
5877 /* 0xc8 TODO: bswap */
5878 /* 0xc9 TODO: bswap */
5879 /* 0xca TODO: bswap */
5880 /* 0xcb TODO: bswap */
5881 /* 0xcc TODO: bswap */
5882 /* 0xcd TODO: bswap */
5883 /* 0xce TODO: bswap */
5884 /* 0xcf TODO: bswap */
5887 x86emu_halt_sys(emu);
5893 * Carry Chain Calculation
5895 * This represents a somewhat expensive calculation which is
5896 * apparently required to emulate the setting of the OF and AF flag.
5897 * The latter is not so important, but the former is. The overflow
5898 * flag is the XOR of the top two bits of the carry chain for an
5899 * addition (similar for subtraction). Since we do not want to
5900 * simulate the addition in a bitwise manner, we try to calculate the
5901 * carry chain given the two operands and the result.
5903 * So, given the following table, which represents the addition of two
5904 * bits, we can derive a formula for the carry chain.
5916 * Construction of table for cout:
5920 * |------------------
5924 * By inspection, one gets: cc = ab + r'(a + b)
5926 * That represents alot of operations, but NO CHOICE....
5928 * Borrow Chain Calculation.
5930 * The following table represents the subtraction of two bits, from
5931 * which we can derive a formula for the borrow chain.
5943 * Construction of table for cout:
5947 * |------------------
5951 * By inspection, one gets: bc = a'b + r(a' + b)
5959 static uint32_t x86emu_parity_tab[8] =
5970 #define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
5971 #define XOR2(x) (((x) ^ ((x)>>1)) & 0x1)
5976 * Implements the AAA instruction and side effects.
5979 aaa_word(struct x86emu *emu, uint16_t d)
5982 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
5991 res = (uint16_t) (d & 0xFF0F);
5993 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
5994 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6000 * Implements the AAA instruction and side effects.
6003 aas_word(struct x86emu *emu, uint16_t d)
6006 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
6015 res = (uint16_t) (d & 0xFF0F);
6017 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6018 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6024 * Implements the AAD instruction and side effects.
6027 aad_word(struct x86emu *emu, uint16_t d)
6032 hb = (uint8_t) ((d >> 8) & 0xff);
6033 lb = (uint8_t) ((d & 0xff));
6034 l = (uint16_t) ((lb + 10 * hb) & 0xFF);
6039 CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
6040 CONDITIONAL_SET_FLAG(l == 0, F_ZF);
6041 CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
6047 * Implements the AAM instruction and side effects.
6050 aam_word(struct x86emu *emu, uint8_t d)
6054 h = (uint16_t) (d / 10);
6055 l = (uint16_t) (d % 10);
6056 l |= (uint16_t) (h << 8);
6061 CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
6062 CONDITIONAL_SET_FLAG(l == 0, F_ZF);
6063 CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
6069 * Implements the ADC instruction and side effects.
6072 adc_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6074 uint32_t res; /* all operands in native machine order */
6077 if (ACCESS_FLAG(F_CF))
6082 CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
6083 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6084 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6085 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6087 /* calculate the carry chain SEE NOTE AT TOP. */
6088 cc = (s & d) | ((~res) & (s | d));
6089 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
6090 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6091 return (uint8_t) res;
6096 * Implements the ADC instruction and side effects.
6099 adc_word(struct x86emu *emu, uint16_t d, uint16_t s)
6101 uint32_t res; /* all operands in native machine order */
6104 if (ACCESS_FLAG(F_CF))
6109 CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
6110 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6111 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6112 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6114 /* calculate the carry chain SEE NOTE AT TOP. */
6115 cc = (s & d) | ((~res) & (s | d));
6116 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
6117 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6118 return (uint16_t) res;
6123 * Implements the ADC instruction and side effects.
6126 adc_long(struct x86emu *emu, uint32_t d, uint32_t s)
6128 uint32_t lo; /* all operands in native machine order */
6133 if (ACCESS_FLAG(F_CF)) {
6134 lo = 1 + (d & 0xFFFF) + (s & 0xFFFF);
6137 lo = (d & 0xFFFF) + (s & 0xFFFF);
6140 hi = (lo >> 16) + (d >> 16) + (s >> 16);
6142 CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
6143 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6144 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6145 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6147 /* calculate the carry chain SEE NOTE AT TOP. */
6148 cc = (s & d) | ((~res) & (s | d));
6149 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
6150 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6156 * Implements the ADD instruction and side effects.
6159 add_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6161 uint32_t res; /* all operands in native machine order */
6165 CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
6166 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6167 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6168 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6170 /* calculate the carry chain SEE NOTE AT TOP. */
6171 cc = (s & d) | ((~res) & (s | d));
6172 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
6173 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6174 return (uint8_t) res;
6179 * Implements the ADD instruction and side effects.
6182 add_word(struct x86emu *emu, uint16_t d, uint16_t s)
6184 uint32_t res; /* all operands in native machine order */
6188 CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
6189 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6190 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6191 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6193 /* calculate the carry chain SEE NOTE AT TOP. */
6194 cc = (s & d) | ((~res) & (s | d));
6195 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
6196 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6197 return (uint16_t) res;
6202 * Implements the ADD instruction and side effects.
6205 add_long(struct x86emu *emu, uint32_t d, uint32_t s)
6207 uint32_t lo; /* all operands in native machine order */
6212 lo = (d & 0xFFFF) + (s & 0xFFFF);
6214 hi = (lo >> 16) + (d >> 16) + (s >> 16);
6216 CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
6217 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6218 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6219 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6221 /* calculate the carry chain SEE NOTE AT TOP. */
6222 cc = (s & d) | ((~res) & (s | d));
6223 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
6224 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6231 * Implements the AND instruction and side effects.
6234 and_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6236 uint8_t res; /* all operands in native machine order */
6244 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6245 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6246 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6252 * Implements the AND instruction and side effects.
6255 and_word(struct x86emu *emu, uint16_t d, uint16_t s)
6257 uint16_t res; /* all operands in native machine order */
6265 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6266 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6267 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6273 * Implements the AND instruction and side effects.
6276 and_long(struct x86emu *emu, uint32_t d, uint32_t s)
6278 uint32_t res; /* all operands in native machine order */
6286 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6287 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6288 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6294 * Implements the CMP instruction and side effects.
6297 cmp_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6299 uint32_t res; /* all operands in native machine order */
6304 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6305 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6306 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6308 /* calculate the borrow chain. See note at top */
6309 bc = (res & (~d | s)) | (~d & s);
6310 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
6311 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6312 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6317 cmp_byte_no_return(struct x86emu *emu, uint8_t d, uint8_t s)
6319 cmp_byte(emu, d, s);
6324 * Implements the CMP instruction and side effects.
6327 cmp_word(struct x86emu *emu, uint16_t d, uint16_t s)
6329 uint32_t res; /* all operands in native machine order */
6333 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6334 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6335 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6337 /* calculate the borrow chain. See note at top */
6338 bc = (res & (~d | s)) | (~d & s);
6339 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
6340 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6341 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6346 cmp_word_no_return(struct x86emu *emu, uint16_t d, uint16_t s)
6348 cmp_word(emu, d, s);
6353 * Implements the CMP instruction and side effects.
6356 cmp_long(struct x86emu *emu, uint32_t d, uint32_t s)
6358 uint32_t res; /* all operands in native machine order */
6362 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6363 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6364 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6366 /* calculate the borrow chain. See note at top */
6367 bc = (res & (~d | s)) | (~d & s);
6368 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
6369 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6370 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6375 cmp_long_no_return(struct x86emu *emu, uint32_t d, uint32_t s)
6377 cmp_long(emu, d, s);
6382 * Implements the DAA instruction and side effects.
6385 daa_byte(struct x86emu *emu, uint8_t d)
6388 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
6392 if (res > 0x9F || ACCESS_FLAG(F_CF)) {
6396 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6397 CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF);
6398 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6399 return (uint8_t) res;
6404 * Implements the DAS instruction and side effects.
6407 das_byte(struct x86emu *emu, uint8_t d)
6409 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
6413 if (d > 0x9F || ACCESS_FLAG(F_CF)) {
6417 CONDITIONAL_SET_FLAG(d & 0x80, F_SF);
6418 CONDITIONAL_SET_FLAG(d == 0, F_ZF);
6419 CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF);
6425 * Implements the DEC instruction and side effects.
6428 dec_byte(struct x86emu *emu, uint8_t d)
6430 uint32_t res; /* all operands in native machine order */
6434 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6435 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6436 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6438 /* calculate the borrow chain. See note at top */
6439 /* based on sub_byte, uses s==1. */
6440 bc = (res & (~d | 1)) | (~d & 1);
6441 /* carry flag unchanged */
6442 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6443 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6444 return (uint8_t) res;
6449 * Implements the DEC instruction and side effects.
6452 dec_word(struct x86emu *emu, uint16_t d)
6454 uint32_t res; /* all operands in native machine order */
6458 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6459 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6460 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6462 /* calculate the borrow chain. See note at top */
6463 /* based on the sub_byte routine, with s==1 */
6464 bc = (res & (~d | 1)) | (~d & 1);
6465 /* carry flag unchanged */
6466 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6467 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6468 return (uint16_t) res;
6473 * Implements the DEC instruction and side effects.
6476 dec_long(struct x86emu *emu, uint32_t d)
6478 uint32_t res; /* all operands in native machine order */
6483 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6484 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6485 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6487 /* calculate the borrow chain. See note at top */
6488 bc = (res & (~d | 1)) | (~d & 1);
6489 /* carry flag unchanged */
6490 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6491 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6497 * Implements the INC instruction and side effects.
6500 inc_byte(struct x86emu *emu, uint8_t d)
6502 uint32_t res; /* all operands in native machine order */
6506 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6507 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6508 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6510 /* calculate the carry chain SEE NOTE AT TOP. */
6511 cc = ((1 & d) | (~res)) & (1 | d);
6512 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
6513 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6514 return (uint8_t) res;
6519 * Implements the INC instruction and side effects.
6522 inc_word(struct x86emu *emu, uint16_t d)
6524 uint32_t res; /* all operands in native machine order */
6528 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6529 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6530 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6532 /* calculate the carry chain SEE NOTE AT TOP. */
6533 cc = (1 & d) | ((~res) & (1 | d));
6534 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
6535 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6536 return (uint16_t) res;
6541 * Implements the INC instruction and side effects.
6544 inc_long(struct x86emu *emu, uint32_t d)
6546 uint32_t res; /* all operands in native machine order */
6550 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6551 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6552 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6554 /* calculate the carry chain SEE NOTE AT TOP. */
6555 cc = (1 & d) | ((~res) & (1 | d));
6556 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
6557 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6563 * Implements the OR instruction and side effects.
6566 or_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6568 uint8_t res; /* all operands in native machine order */
6574 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6575 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6576 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6582 * Implements the OR instruction and side effects.
6585 or_word(struct x86emu *emu, uint16_t d, uint16_t s)
6587 uint16_t res; /* all operands in native machine order */
6590 /* set the carry flag to be bit 8 */
6594 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6595 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6596 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6602 * Implements the OR instruction and side effects.
6605 or_long(struct x86emu *emu, uint32_t d, uint32_t s)
6607 uint32_t res; /* all operands in native machine order */
6611 /* set the carry flag to be bit 8 */
6615 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6616 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6617 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6623 * Implements the OR instruction and side effects.
6626 neg_byte(struct x86emu *emu, uint8_t s)
6631 CONDITIONAL_SET_FLAG(s != 0, F_CF);
6632 res = (uint8_t) - s;
6633 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6634 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6635 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6636 /* calculate the borrow chain --- modified such that d=0.
6637 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for
6638 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6639 * res&0xfff... == res. Similarly ~d&s == s. So the simplified
6642 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6643 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6649 * Implements the OR instruction and side effects.
6652 neg_word(struct x86emu *emu, uint16_t s)
6657 CONDITIONAL_SET_FLAG(s != 0, F_CF);
6658 res = (uint16_t) - s;
6659 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6660 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6661 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6663 /* calculate the borrow chain --- modified such that d=0.
6664 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for
6665 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6666 * res&0xfff... == res. Similarly ~d&s == s. So the simplified
6669 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6670 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6676 * Implements the OR instruction and side effects.
6679 neg_long(struct x86emu *emu, uint32_t s)
6684 CONDITIONAL_SET_FLAG(s != 0, F_CF);
6685 res = (uint32_t) - s;
6686 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6687 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6688 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6690 /* calculate the borrow chain --- modified such that d=0.
6691 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for
6692 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6693 * res&0xfff... == res. Similarly ~d&s == s. So the simplified
6696 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6697 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6703 * Implements the RCL instruction and side effects.
6706 rcl_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6708 unsigned int res, cnt, mask, cf;
6710 /* s is the rotate distance. It varies from 0 - 8. */
6713 * CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
6715 * want to rotate through the carry by "s" bits. We could loop, but
6716 * that's inefficient. So the width is 9, and we split into three
6719 * The new carry flag (was B_n) the stuff in B_n-1 .. B_0 the stuff
6722 * The new rotate is done mod 9, and given this, for a rotation of n
6723 * bits (mod 9) the new carry flag is then located n bits from the MSB.
6724 * The low part is then shifted up cnt bits, and the high part is or'd
6725 * in. Using CAPS for new values, and lowercase for the original
6726 * values, this can be expressed as:
6728 * IF n > 0 1) CF <- b_(8-n) 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0
6729 * 3) B_(n-1) <- cf 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1))
6732 if ((cnt = s % 9) != 0) {
6733 /* extract the new CARRY FLAG. */
6735 cf = (d >> (8 - cnt)) & 0x1;
6738 * Get the low stuff which rotated into the range B_7 .. B_cnt
6739 * B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0
6740 * note that the right hand side done by the mask.
6742 res = (d << cnt) & 0xff;
6745 * now the high stuff which rotated around into the positions
6747 * B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1))
6748 * shift it downward, 7-(n-2) = 9-n positions. and mask off
6749 * the result before or'ing in.
6751 mask = (1 << (cnt - 1)) - 1;
6752 res |= (d >> (9 - cnt)) & mask;
6754 /* if the carry flag was set, or it in. */
6755 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
6757 res |= 1 << (cnt - 1);
6759 /* set the new carry flag, based on the variable "cf" */
6760 CONDITIONAL_SET_FLAG(cf, F_CF);
6761 /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and
6762 * the most significant bit. Blecck. */
6763 /* parenthesized this expression since it appears to be
6764 * causing OF to be misset */
6765 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
6769 return (uint8_t) res;
6774 * Implements the RCL instruction and side effects.
6777 rcl_word(struct x86emu *emu, uint16_t d, uint8_t s)
6779 unsigned int res, cnt, mask, cf;
6782 if ((cnt = s % 17) != 0) {
6783 cf = (d >> (16 - cnt)) & 0x1;
6784 res = (d << cnt) & 0xffff;
6785 mask = (1 << (cnt - 1)) - 1;
6786 res |= (d >> (17 - cnt)) & mask;
6787 if (ACCESS_FLAG(F_CF)) {
6788 res |= 1 << (cnt - 1);
6790 CONDITIONAL_SET_FLAG(cf, F_CF);
6791 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
6794 return (uint16_t) res;
6799 * Implements the RCL instruction and side effects.
6802 rcl_long(struct x86emu *emu, uint32_t d, uint8_t s)
6804 uint32_t res, cnt, mask, cf;
6807 if ((cnt = s % 33) != 0) {
6808 cf = (d >> (32 - cnt)) & 0x1;
6809 res = (d << cnt) & 0xffffffff;
6810 mask = (1 << (cnt - 1)) - 1;
6811 res |= (d >> (33 - cnt)) & mask;
6812 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
6813 res |= 1 << (cnt - 1);
6815 CONDITIONAL_SET_FLAG(cf, F_CF);
6816 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
6824 * Implements the RCR instruction and side effects.
6827 rcr_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6830 uint32_t mask, cf, ocf = 0;
6832 /* rotate right through carry */
6833 /* s is the rotate distance. It varies from 0 - 8. d is the byte
6838 * CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
6840 * The new rotate is done mod 9, and given this, for a rotation of n
6841 * bits (mod 9) the new carry flag is then located n bits from the LSB.
6842 * The low part is then shifted up cnt bits, and the high part is or'd
6843 * in. Using CAPS for new values, and lowercase for the original
6844 * values, this can be expressed as:
6848 * 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
6849 * 3) B_(8-n) <- cf 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0)
6852 if ((cnt = s % 9) != 0) {
6853 /* extract the new CARRY FLAG. */
6857 /* note hackery here. Access_flag(..) evaluates to
6858 * either 0 if flag not set non-zero if flag is set.
6859 * doing access_flag(..) != 0 casts that into either
6860 * 0..1 in any representation of the flags register
6861 * (i.e. packed bit array or unpacked.) */
6862 ocf = ACCESS_FLAG(F_CF) != 0;
6864 cf = (d >> (cnt - 1)) & 0x1;
6866 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */
6867 /* note that the right hand side done by the mask This is
6868 * effectively done by shifting the object to the right. The
6869 * result must be masked, in case the object came in and was
6870 * treated as a negative number. Needed??? */
6872 mask = (1 << (8 - cnt)) - 1;
6873 res = (d >> cnt) & mask;
6875 /* now the high stuff which rotated around into the positions
6877 /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */
6878 /* shift it downward, 7-(n-2) = 9-n positions. and mask off
6879 * the result before or'ing in. */
6880 res |= (d << (9 - cnt));
6882 /* if the carry flag was set, or it in. */
6883 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
6885 res |= 1 << (8 - cnt);
6887 /* set the new carry flag, based on the variable "cf" */
6888 CONDITIONAL_SET_FLAG(cf, F_CF);
6889 /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and
6890 * the most significant bit. Blecck. */
6891 /* parenthesized... */
6893 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
6897 return (uint8_t) res;
6902 * Implements the RCR instruction and side effects.
6905 rcr_word(struct x86emu *emu, uint16_t d, uint8_t s)
6908 uint32_t mask, cf, ocf = 0;
6910 /* rotate right through carry */
6912 if ((cnt = s % 17) != 0) {
6915 ocf = ACCESS_FLAG(F_CF) != 0;
6917 cf = (d >> (cnt - 1)) & 0x1;
6918 mask = (1 << (16 - cnt)) - 1;
6919 res = (d >> cnt) & mask;
6920 res |= (d << (17 - cnt));
6921 if (ACCESS_FLAG(F_CF)) {
6922 res |= 1 << (16 - cnt);
6924 CONDITIONAL_SET_FLAG(cf, F_CF);
6926 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
6930 return (uint16_t) res;
6935 * Implements the RCR instruction and side effects.
6938 rcr_long(struct x86emu *emu, uint32_t d, uint8_t s)
6941 uint32_t mask, cf, ocf = 0;
6943 /* rotate right through carry */
6945 if ((cnt = s % 33) != 0) {
6948 ocf = ACCESS_FLAG(F_CF) != 0;
6950 cf = (d >> (cnt - 1)) & 0x1;
6951 mask = (1 << (32 - cnt)) - 1;
6952 res = (d >> cnt) & mask;
6954 res |= (d << (33 - cnt));
6955 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
6956 res |= 1 << (32 - cnt);
6958 CONDITIONAL_SET_FLAG(cf, F_CF);
6960 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
6969 * Implements the ROL instruction and side effects.
6972 rol_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6974 unsigned int res, cnt, mask;
6977 /* s is the rotate distance. It varies from 0 - 8. d is the byte
6984 * The new rotate is done mod 8. Much simpler than the "rcl" or "rcr"
6987 * IF n > 0 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) 2) B_(n-1) ..
6988 * B_(0) <- b_(7) .. b_(8-n) */
6990 if ((cnt = s % 8) != 0) {
6991 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */
6994 /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */
6995 mask = (1 << cnt) - 1;
6996 res |= (d >> (8 - cnt)) & mask;
6998 /* set the new carry flag, Note that it is the low order bit
6999 * of the result!!! */
7000 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
7001 /* OVERFLOW is set *IFF* s==1, then it is the xor of CF and
7002 * the most significant bit. Blecck. */
7003 CONDITIONAL_SET_FLAG(s == 1 &&
7004 XOR2((res & 0x1) + ((res >> 6) & 0x2)),
7007 /* set the new carry flag, Note that it is the low order bit
7008 * of the result!!! */
7009 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
7011 return (uint8_t) res;
7016 * Implements the ROL instruction and side effects.
7019 rol_word(struct x86emu *emu, uint16_t d, uint8_t s)
7021 unsigned int res, cnt, mask;
7024 if ((cnt = s % 16) != 0) {
7026 mask = (1 << cnt) - 1;
7027 res |= (d >> (16 - cnt)) & mask;
7028 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
7029 CONDITIONAL_SET_FLAG(s == 1 &&
7030 XOR2((res & 0x1) + ((res >> 14) & 0x2)),
7033 /* set the new carry flag, Note that it is the low order bit
7034 * of the result!!! */
7035 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
7037 return (uint16_t) res;
7042 * Implements the ROL instruction and side effects.
7045 rol_long(struct x86emu *emu, uint32_t d, uint8_t s)
7047 uint32_t res, cnt, mask;
7050 if ((cnt = s % 32) != 0) {
7052 mask = (1 << cnt) - 1;
7053 res |= (d >> (32 - cnt)) & mask;
7054 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
7055 CONDITIONAL_SET_FLAG(s == 1 &&
7056 XOR2((res & 0x1) + ((res >> 30) & 0x2)),
7059 /* set the new carry flag, Note that it is the low order bit
7060 * of the result!!! */
7061 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
7068 * Implements the ROR instruction and side effects.
7071 ror_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7073 unsigned int res, cnt, mask;
7076 /* s is the rotate distance. It varies from 0 - 8. d is the byte
7083 * The rotate is done mod 8.
7085 * IF n > 0 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) 2) B_(7) ..
7086 * B_(8-n) <- b_(n-1) .. b_(0) */
7088 if ((cnt = s % 8) != 0) { /* not a typo, do nada if cnt==0 */
7089 /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */
7090 res = (d << (8 - cnt));
7092 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */
7093 mask = (1 << (8 - cnt)) - 1;
7094 res |= (d >> (cnt)) & mask;
7096 /* set the new carry flag, Note that it is the low order bit
7097 * of the result!!! */
7098 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
7099 /* OVERFLOW is set *IFF* s==1, then it is the xor of the two
7100 * most significant bits. Blecck. */
7101 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
7102 } else if (s != 0) {
7103 /* set the new carry flag, Note that it is the low order bit
7104 * of the result!!! */
7105 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
7107 return (uint8_t) res;
7112 * Implements the ROR instruction and side effects.
7115 ror_word(struct x86emu *emu, uint16_t d, uint8_t s)
7117 unsigned int res, cnt, mask;
7120 if ((cnt = s % 16) != 0) {
7121 res = (d << (16 - cnt));
7122 mask = (1 << (16 - cnt)) - 1;
7123 res |= (d >> (cnt)) & mask;
7124 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
7125 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
7126 } else if (s != 0) {
7127 /* set the new carry flag, Note that it is the low order bit
7128 * of the result!!! */
7129 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
7131 return (uint16_t) res;
7136 * Implements the ROR instruction and side effects.
7139 ror_long(struct x86emu *emu, uint32_t d, uint8_t s)
7141 uint32_t res, cnt, mask;
7144 if ((cnt = s % 32) != 0) {
7145 res = (d << (32 - cnt));
7146 mask = (1 << (32 - cnt)) - 1;
7147 res |= (d >> (cnt)) & mask;
7148 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
7149 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
7150 } else if (s != 0) {
7151 /* set the new carry flag, Note that it is the low order bit
7152 * of the result!!! */
7153 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
7160 * Implements the SHL instruction and side effects.
7163 shl_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7165 unsigned int cnt, res, cf;
7170 /* last bit shifted out goes into carry flag */
7173 cf = d & (1 << (8 - cnt));
7174 CONDITIONAL_SET_FLAG(cf, F_CF);
7175 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7176 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7177 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7183 /* Needs simplification. */
7184 CONDITIONAL_SET_FLAG(
7185 (((res & 0x80) == 0x80) ^
7186 (ACCESS_FLAG(F_CF) != 0)),
7187 /* was (emu->x86.R_FLG&F_CF)==F_CF)), */
7194 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80, F_CF);
7200 return (uint8_t) res;
7205 * Implements the SHL instruction and side effects.
7208 shl_word(struct x86emu *emu, uint16_t d, uint8_t s)
7210 unsigned int cnt, res, cf;
7216 cf = d & (1 << (16 - cnt));
7217 CONDITIONAL_SET_FLAG(cf, F_CF);
7218 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7219 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7220 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7226 CONDITIONAL_SET_FLAG(
7227 (((res & 0x8000) == 0x8000) ^
7228 (ACCESS_FLAG(F_CF) != 0)),
7235 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF);
7241 return (uint16_t) res;
7246 * Implements the SHL instruction and side effects.
7249 shl_long(struct x86emu *emu, uint32_t d, uint8_t s)
7251 unsigned int cnt, res, cf;
7257 cf = d & (1 << (32 - cnt));
7258 CONDITIONAL_SET_FLAG(cf, F_CF);
7259 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7260 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7261 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7266 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000)
7267 ^ (ACCESS_FLAG(F_CF) != 0)), F_OF);
7273 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF);
7284 * Implements the SHR instruction and side effects.
7287 shr_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7289 unsigned int cnt, res, cf;
7294 cf = d & (1 << (cnt - 1));
7296 CONDITIONAL_SET_FLAG(cf, F_CF);
7297 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7298 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7299 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7305 CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
7311 CONDITIONAL_SET_FLAG((d >> (s - 1)) & 0x1, F_CF);
7317 return (uint8_t) res;
7322 * Implements the SHR instruction and side effects.
7325 shr_word(struct x86emu *emu, uint16_t d, uint8_t s)
7327 unsigned int cnt, res, cf;
7332 cf = d & (1 << (cnt - 1));
7334 CONDITIONAL_SET_FLAG(cf, F_CF);
7335 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7336 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7337 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7343 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
7355 return (uint16_t) res;
7360 * Implements the SHR instruction and side effects.
7363 shr_long(struct x86emu *emu, uint32_t d, uint8_t s)
7365 unsigned int cnt, res, cf;
7370 cf = d & (1 << (cnt - 1));
7372 CONDITIONAL_SET_FLAG(cf, F_CF);
7373 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7374 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7375 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7380 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
7397 * Implements the SAR instruction and side effects.
7400 sar_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7402 unsigned int cnt, res, cf, mask, sf;
7407 if (cnt > 0 && cnt < 8) {
7408 mask = (1 << (8 - cnt)) - 1;
7409 cf = d & (1 << (cnt - 1));
7410 res = (d >> cnt) & mask;
7411 CONDITIONAL_SET_FLAG(cf, F_CF);
7415 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7416 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7417 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7418 } else if (cnt >= 8) {
7433 return (uint8_t) res;
7438 * Implements the SAR instruction and side effects.
7441 sar_word(struct x86emu *emu, uint16_t d, uint8_t s)
7443 unsigned int cnt, res, cf, mask, sf;
7448 if (cnt > 0 && cnt < 16) {
7449 mask = (1 << (16 - cnt)) - 1;
7450 cf = d & (1 << (cnt - 1));
7451 res = (d >> cnt) & mask;
7452 CONDITIONAL_SET_FLAG(cf, F_CF);
7456 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7457 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7458 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7459 } else if (cnt >= 16) {
7474 return (uint16_t) res;
7479 * Implements the SAR instruction and side effects.
7482 sar_long(struct x86emu *emu, uint32_t d, uint8_t s)
7484 uint32_t cnt, res, cf, mask, sf;
7486 sf = d & 0x80000000;
7489 if (cnt > 0 && cnt < 32) {
7490 mask = (1 << (32 - cnt)) - 1;
7491 cf = d & (1 << (cnt - 1));
7492 res = (d >> cnt) & mask;
7493 CONDITIONAL_SET_FLAG(cf, F_CF);
7497 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7498 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7499 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7500 } else if (cnt >= 32) {
7520 * Implements the SHLD instruction and side effects.
7523 shld_word(struct x86emu *emu, uint16_t d, uint16_t fill, uint8_t s)
7525 unsigned int cnt, res, cf;
7530 res = (d << cnt) | (fill >> (16 - cnt));
7531 cf = d & (1 << (16 - cnt));
7532 CONDITIONAL_SET_FLAG(cf, F_CF);
7533 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7534 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7535 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7540 CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
7541 (ACCESS_FLAG(F_CF) != 0)), F_OF);
7547 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF);
7553 return (uint16_t) res;
7558 * Implements the SHLD instruction and side effects.
7561 shld_long(struct x86emu *emu, uint32_t d, uint32_t fill, uint8_t s)
7563 unsigned int cnt, res, cf;
7568 res = (d << cnt) | (fill >> (32 - cnt));
7569 cf = d & (1 << (32 - cnt));
7570 CONDITIONAL_SET_FLAG(cf, F_CF);
7571 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7572 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7573 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7578 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000)
7579 ^ (ACCESS_FLAG(F_CF) != 0)), F_OF);
7585 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF);
7596 * Implements the SHRD instruction and side effects.
7599 shrd_word(struct x86emu *emu, uint16_t d, uint16_t fill, uint8_t s)
7601 unsigned int cnt, res, cf;
7606 cf = d & (1 << (cnt - 1));
7607 res = (d >> cnt) | (fill << (16 - cnt));
7608 CONDITIONAL_SET_FLAG(cf, F_CF);
7609 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7610 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7611 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7617 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
7629 return (uint16_t) res;
7634 * Implements the SHRD instruction and side effects.
7637 shrd_long(struct x86emu *emu, uint32_t d, uint32_t fill, uint8_t s)
7639 unsigned int cnt, res, cf;
7644 cf = d & (1 << (cnt - 1));
7645 res = (d >> cnt) | (fill << (32 - cnt));
7646 CONDITIONAL_SET_FLAG(cf, F_CF);
7647 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7648 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7649 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7654 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
7671 * Implements the SBB instruction and side effects.
7674 sbb_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7676 uint32_t res; /* all operands in native machine order */
7679 if (ACCESS_FLAG(F_CF))
7683 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7684 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7685 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7687 /* calculate the borrow chain. See note at top */
7688 bc = (res & (~d | s)) | (~d & s);
7689 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
7690 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
7691 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7692 return (uint8_t) res;
7697 * Implements the SBB instruction and side effects.
7700 sbb_word(struct x86emu *emu, uint16_t d, uint16_t s)
7702 uint32_t res; /* all operands in native machine order */
7705 if (ACCESS_FLAG(F_CF))
7709 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7710 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7711 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7713 /* calculate the borrow chain. See note at top */
7714 bc = (res & (~d | s)) | (~d & s);
7715 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
7716 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
7717 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7718 return (uint16_t) res;
7723 * Implements the SBB instruction and side effects.
7726 sbb_long(struct x86emu *emu, uint32_t d, uint32_t s)
7728 uint32_t res; /* all operands in native machine order */
7731 if (ACCESS_FLAG(F_CF))
7735 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7736 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7737 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7739 /* calculate the borrow chain. See note at top */
7740 bc = (res & (~d | s)) | (~d & s);
7741 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
7742 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
7743 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7749 * Implements the SUB instruction and side effects.
7752 sub_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7754 uint32_t res; /* all operands in native machine order */
7758 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7759 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7760 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7762 /* calculate the borrow chain. See note at top */
7763 bc = (res & (~d | s)) | (~d & s);
7764 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
7765 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
7766 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7767 return (uint8_t) res;
7772 * Implements the SUB instruction and side effects.
7775 sub_word(struct x86emu *emu, uint16_t d, uint16_t s)
7777 uint32_t res; /* all operands in native machine order */
7781 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7782 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7783 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7785 /* calculate the borrow chain. See note at top */
7786 bc = (res & (~d | s)) | (~d & s);
7787 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
7788 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
7789 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7790 return (uint16_t) res;
7795 * Implements the SUB instruction and side effects.
7798 sub_long(struct x86emu *emu, uint32_t d, uint32_t s)
7800 uint32_t res; /* all operands in native machine order */
7804 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7805 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7806 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7808 /* calculate the borrow chain. See note at top */
7809 bc = (res & (~d | s)) | (~d & s);
7810 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
7811 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
7812 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7818 * Implements the TEST instruction and side effects.
7821 test_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7823 uint32_t res; /* all operands in native machine order */
7828 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7829 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7830 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7831 /* AF == dont care */
7837 * Implements the TEST instruction and side effects.
7840 test_word(struct x86emu *emu, uint16_t d, uint16_t s)
7842 uint32_t res; /* all operands in native machine order */
7847 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7848 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7849 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7850 /* AF == dont care */
7856 * Implements the TEST instruction and side effects.
7859 test_long(struct x86emu *emu, uint32_t d, uint32_t s)
7861 uint32_t res; /* all operands in native machine order */
7866 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7867 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7868 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7869 /* AF == dont care */
7875 * Implements the XOR instruction and side effects.
7878 xor_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7880 uint8_t res; /* all operands in native machine order */
7884 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7885 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7886 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
7894 * Implements the XOR instruction and side effects.
7897 xor_word(struct x86emu *emu, uint16_t d, uint16_t s)
7899 uint16_t res; /* all operands in native machine order */
7903 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7904 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7905 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7913 * Implements the XOR instruction and side effects.
7916 xor_long(struct x86emu *emu, uint32_t d, uint32_t s)
7918 uint32_t res; /* all operands in native machine order */
7922 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7923 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7924 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7932 * Implements the IMUL instruction and side effects.
7935 imul_byte(struct x86emu *emu, uint8_t s)
7937 int16_t res = (int16_t) ((int8_t) emu->x86.R_AL * (int8_t) s);
7939 emu->x86.R_AX = res;
7940 if (((emu->x86.R_AL & 0x80) == 0 && emu->x86.R_AH == 0x00) ||
7941 ((emu->x86.R_AL & 0x80) != 0 && emu->x86.R_AH == 0xFF)) {
7952 * Implements the IMUL instruction and side effects.
7955 imul_word(struct x86emu *emu, uint16_t s)
7957 int32_t res = (int16_t) emu->x86.R_AX * (int16_t) s;
7959 emu->x86.R_AX = (uint16_t) res;
7960 emu->x86.R_DX = (uint16_t) (res >> 16);
7961 if (((emu->x86.R_AX & 0x8000) == 0 && emu->x86.R_DX == 0x00) ||
7962 ((emu->x86.R_AX & 0x8000) != 0 && emu->x86.R_DX == 0xFF)) {
7973 * Implements the IMUL instruction and side effects.
7976 imul_long(struct x86emu *emu, uint32_t s)
7980 res = (int64_t)(int32_t)emu->x86.R_EAX * (int32_t)s;
7981 emu->x86.R_EAX = (uint32_t)res;
7982 emu->x86.R_EDX = ((uint64_t)res) >> 32;
7983 if (((emu->x86.R_EAX & 0x80000000) == 0 && emu->x86.R_EDX == 0x00) ||
7984 ((emu->x86.R_EAX & 0x80000000) != 0 && emu->x86.R_EDX == 0xFF)) {
7995 * Implements the MUL instruction and side effects.
7998 mul_byte(struct x86emu *emu, uint8_t s)
8000 uint16_t res = (uint16_t) (emu->x86.R_AL * s);
8002 emu->x86.R_AX = res;
8003 if (emu->x86.R_AH == 0) {
8014 * Implements the MUL instruction and side effects.
8017 mul_word(struct x86emu *emu, uint16_t s)
8019 uint32_t res = emu->x86.R_AX * s;
8021 emu->x86.R_AX = (uint16_t) res;
8022 emu->x86.R_DX = (uint16_t) (res >> 16);
8023 if (emu->x86.R_DX == 0) {
8034 * Implements the MUL instruction and side effects.
8037 mul_long(struct x86emu *emu, uint32_t s)
8039 uint64_t res = (uint64_t) emu->x86.R_EAX * s;
8041 emu->x86.R_EAX = (uint32_t) res;
8042 emu->x86.R_EDX = (uint32_t) (res >> 32);
8044 if (emu->x86.R_EDX == 0) {
8055 * Implements the IDIV instruction and side effects.
8058 idiv_byte(struct x86emu *emu, uint8_t s)
8060 int32_t dvd, div, mod;
8062 dvd = (int16_t) emu->x86.R_AX;
8064 x86emu_intr_raise(emu, 8);
8067 div = dvd / (int8_t) s;
8068 mod = dvd % (int8_t) s;
8069 if (div > 0x7f || div < -0x7f) {
8070 x86emu_intr_raise(emu, 8);
8073 emu->x86.R_AL = (int8_t) div;
8074 emu->x86.R_AH = (int8_t) mod;
8079 * Implements the IDIV instruction and side effects.
8082 idiv_word(struct x86emu *emu, uint16_t s)
8084 int32_t dvd, div, mod;
8086 dvd = (((int32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX;
8088 x86emu_intr_raise(emu, 8);
8091 div = dvd / (int16_t) s;
8092 mod = dvd % (int16_t) s;
8093 if (div > 0x7fff || div < -0x7fff) {
8094 x86emu_intr_raise(emu, 8);
8099 CONDITIONAL_SET_FLAG(div == 0, F_ZF);
8100 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
8102 emu->x86.R_AX = (uint16_t) div;
8103 emu->x86.R_DX = (uint16_t) mod;
8108 * Implements the IDIV instruction and side effects.
8111 idiv_long(struct x86emu *emu, uint32_t s)
8113 int64_t dvd, div, mod;
8115 dvd = (((int64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX;
8117 x86emu_intr_raise(emu, 8);
8120 div = dvd / (int32_t) s;
8121 mod = dvd % (int32_t) s;
8122 if (div > 0x7fffffff || div < -0x7fffffff) {
8123 x86emu_intr_raise(emu, 8);
8130 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
8132 emu->x86.R_EAX = (uint32_t) div;
8133 emu->x86.R_EDX = (uint32_t) mod;
8138 * Implements the DIV instruction and side effects.
8141 div_byte(struct x86emu *emu, uint8_t s)
8143 uint32_t dvd, div, mod;
8145 dvd = emu->x86.R_AX;
8147 x86emu_intr_raise(emu, 8);
8150 div = dvd / (uint8_t) s;
8151 mod = dvd % (uint8_t) s;
8153 x86emu_intr_raise(emu, 8);
8156 emu->x86.R_AL = (uint8_t) div;
8157 emu->x86.R_AH = (uint8_t) mod;
8162 * Implements the DIV instruction and side effects.
8165 div_word(struct x86emu *emu, uint16_t s)
8167 uint32_t dvd, div, mod;
8169 dvd = (((uint32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX;
8171 x86emu_intr_raise(emu, 8);
8174 div = dvd / (uint16_t) s;
8175 mod = dvd % (uint16_t) s;
8177 x86emu_intr_raise(emu, 8);
8182 CONDITIONAL_SET_FLAG(div == 0, F_ZF);
8183 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
8185 emu->x86.R_AX = (uint16_t) div;
8186 emu->x86.R_DX = (uint16_t) mod;
8191 * Implements the DIV instruction and side effects.
8194 div_long(struct x86emu *emu, uint32_t s)
8196 uint64_t dvd, div, mod;
8198 dvd = (((uint64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX;
8200 x86emu_intr_raise(emu, 8);
8203 div = dvd / (uint32_t) s;
8204 mod = dvd % (uint32_t) s;
8205 if (div > 0xffffffff) {
8206 x86emu_intr_raise(emu, 8);
8213 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
8215 emu->x86.R_EAX = (uint32_t) div;
8216 emu->x86.R_EDX = (uint32_t) mod;
8221 * Implements the IN string instruction and side effects.
8224 ins(struct x86emu *emu, int size)
8228 if (ACCESS_FLAG(F_DF)) {
8231 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
8232 /* dont care whether REPE or REPNE */
8233 /* in until CX is ZERO. */
8234 uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ?
8235 emu->x86.R_ECX : emu->x86.R_CX);
8239 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
8240 (*emu->emu_inb) (emu, emu->x86.R_DX));
8241 emu->x86.R_DI += inc;
8247 store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
8248 (*emu->emu_inw) (emu, emu->x86.R_DX));
8249 emu->x86.R_DI += inc;
8254 store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
8255 (*emu->emu_inl) (emu, emu->x86.R_DX));
8256 emu->x86.R_DI += inc;
8261 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
8264 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
8268 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
8269 (*emu->emu_inb) (emu, emu->x86.R_DX));
8272 store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
8273 (*emu->emu_inw) (emu, emu->x86.R_DX));
8276 store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
8277 (*emu->emu_inl) (emu, emu->x86.R_DX));
8280 emu->x86.R_DI += inc;
8286 * Implements the OUT string instruction and side effects.
8289 outs(struct x86emu *emu, int size)
8293 if (ACCESS_FLAG(F_DF)) {
8296 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
8297 /* dont care whether REPE or REPNE */
8298 /* out until CX is ZERO. */
8299 uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ?
8300 emu->x86.R_ECX : emu->x86.R_CX);
8304 (*emu->emu_outb) (emu, emu->x86.R_DX,
8305 fetch_byte(emu, emu->x86.R_ES,
8307 emu->x86.R_SI += inc;
8313 (*emu->emu_outw) (emu, emu->x86.R_DX,
8314 fetch_word(emu, emu->x86.R_ES,
8316 emu->x86.R_SI += inc;
8321 (*emu->emu_outl) (emu, emu->x86.R_DX,
8322 fetch_long(emu, emu->x86.R_ES,
8324 emu->x86.R_SI += inc;
8329 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
8332 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
8336 (*emu->emu_outb) (emu, emu->x86.R_DX,
8337 fetch_byte(emu, emu->x86.R_ES, emu->x86.R_SI));
8340 (*emu->emu_outw) (emu, emu->x86.R_DX,
8341 fetch_word(emu, emu->x86.R_ES, emu->x86.R_SI));
8344 (*emu->emu_outl) (emu, emu->x86.R_DX,
8345 fetch_long(emu, emu->x86.R_ES, emu->x86.R_SI));
8348 emu->x86.R_SI += inc;
8354 * Pushes a word onto the stack.
8356 * NOTE: Do not inline this, as (*emu->emu_wrX) is already inline!
8359 push_word(struct x86emu *emu, uint16_t w)
8362 store_word(emu, emu->x86.R_SS, emu->x86.R_SP, w);
8367 * Pushes a long onto the stack.
8369 * NOTE: Do not inline this, as (*emu->emu_wrX) is already inline!
8372 push_long(struct x86emu *emu, uint32_t w)
8375 store_long(emu, emu->x86.R_SS, emu->x86.R_SP, w);
8380 * Pops a word from the stack.
8382 * NOTE: Do not inline this, as (*emu->emu_rdX) is already inline!
8385 pop_word(struct x86emu *emu)
8389 res = fetch_word(emu, emu->x86.R_SS, emu->x86.R_SP);
8396 * Pops a long from the stack.
8398 * NOTE: Do not inline this, as (*emu->emu_rdX) is already inline!
8401 pop_long(struct x86emu *emu)
8405 res = fetch_long(emu, emu->x86.R_SS, emu->x86.R_SP);