1 /* $OpenBSD: x86emu.c,v 1.4 2009/06/18 14:19:21 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) && (emu->x86.intno == 0 || emu->x86.intno == 2)) ||
239 !ACCESS_FLAG(F_IF)) {
240 x86emu_intr_handle(emu);
243 if (emu->x86.R_CS == 0 && emu->x86.R_IP == 0)
245 x86emu_exec_one_byte(emu);
251 x86emu_exec_call(struct x86emu *emu, uint16_t seg, uint16_t off)
262 x86emu_exec_intr(struct x86emu *emu, uint8_t intr)
264 push_word(emu, emu->x86.R_FLG);
269 emu->x86.R_CS = (*emu->emu_rdw)(emu, intr * 4 + 2);
270 emu->x86.R_IP = (*emu->emu_rdw)(emu, intr * 4);
278 * Halts the system by setting the halted system flag.
281 x86emu_halt_sys(struct x86emu *emu)
283 longjmp(emu->exec_state, 1);
288 * mod - Mod value from decoded byte
289 * regh - Reg h value from decoded byte
290 * regl - Reg l value from decoded byte
293 * Raise the specified interrupt to be handled before the execution of the
296 * NOTE: Do not inline this function, as (*emu->emu_rdb) is already inline!
299 fetch_decode_modrm(struct x86emu *emu)
303 fetched = fetch_byte_imm(emu);
304 emu->cur_mod = (fetched >> 6) & 0x03;
305 emu->cur_rh = (fetched >> 3) & 0x07;
306 emu->cur_rl = (fetched >> 0) & 0x07;
311 * Immediate byte value read from instruction queue
314 * This function returns the immediate byte from the instruction queue, and
315 * moves the instruction pointer to the next value.
317 * NOTE: Do not inline this function, as (*emu->emu_rdb) is already inline!
320 fetch_byte_imm(struct x86emu *emu)
324 fetched = fetch_byte(emu, emu->x86.R_CS, emu->x86.R_IP);
331 * Immediate word value read from instruction queue
334 * This function returns the immediate byte from the instruction queue, and
335 * moves the instruction pointer to the next value.
337 * NOTE: Do not inline this function, as (*emu->emu_rdw) is already inline!
340 fetch_word_imm(struct x86emu *emu)
344 fetched = fetch_word(emu, emu->x86.R_CS, emu->x86.R_IP);
351 * Immediate lone value read from instruction queue
354 * This function returns the immediate byte from the instruction queue, and
355 * moves the instruction pointer to the next value.
357 * NOTE: Do not inline this function, as (*emu->emu_rdw) is already inline!
360 fetch_long_imm(struct x86emu *emu)
364 fetched = fetch_long(emu, emu->x86.R_CS, emu->x86.R_IP);
371 * Value of the default data segment
374 * Inline function that returns the default data segment for the current
377 * On the x86 processor, the default segment is not always DS if there is
378 * no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to
379 * addresses relative to SS (ie: on the stack). So, at the minimum, all
380 * decodings of addressing modes would have to set/clear a bit describing
381 * whether the access is relative to DS or SS. That is the function of the
382 * cpu-state-varible emu->x86.mode. There are several potential states:
384 * repe prefix seen (handled elsewhere)
385 * repne prefix seen (ditto)
387 * cs segment override
388 * ds segment override
389 * es segment override
390 * fs segment override
391 * gs segment override
392 * ss segment override
394 * ds/ss select (in absense of override)
396 * Each of the above 7 items are handled with a bit in the mode field.
399 get_data_segment(struct x86emu *emu)
401 switch (emu->x86.mode & SYSMODE_SEGMASK) {
402 case 0: /* default case: use ds register */
403 case SYSMODE_SEGOVR_DS:
404 case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS:
405 return emu->x86.R_DS;
406 case SYSMODE_SEG_DS_SS:/* non-overridden, use ss register */
407 return emu->x86.R_SS;
408 case SYSMODE_SEGOVR_CS:
409 case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS:
410 return emu->x86.R_CS;
411 case SYSMODE_SEGOVR_ES:
412 case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS:
413 return emu->x86.R_ES;
414 case SYSMODE_SEGOVR_FS:
415 case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS:
416 return emu->x86.R_FS;
417 case SYSMODE_SEGOVR_GS:
418 case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS:
419 return emu->x86.R_GS;
420 case SYSMODE_SEGOVR_SS:
421 case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS:
422 return emu->x86.R_SS;
424 x86emu_halt_sys(emu);
429 * offset - Offset to load data from
432 * Byte value read from the absolute memory location.
434 * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
437 fetch_data_byte(struct x86emu *emu, uint32_t offset)
439 return fetch_byte(emu, get_data_segment(emu), offset);
444 * offset - Offset to load data from
447 * Word value read from the absolute memory location.
449 * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
452 fetch_data_word(struct x86emu *emu, uint32_t offset)
454 return fetch_word(emu, get_data_segment(emu), offset);
459 * offset - Offset to load data from
462 * Long value read from the absolute memory location.
464 * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
467 fetch_data_long(struct x86emu *emu, uint32_t offset)
469 return fetch_long(emu, get_data_segment(emu), offset);
474 * segment - Segment to load data from
475 * offset - Offset to load data from
478 * Byte value read from the absolute memory location.
480 * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
483 fetch_byte(struct x86emu *emu, uint32_t segment, uint32_t offset)
485 return (*emu->emu_rdb) (emu, ((uint32_t) segment << 4) + offset);
490 * segment - Segment to load data from
491 * offset - Offset to load data from
494 * Word value read from the absolute memory location.
496 * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
499 fetch_word(struct x86emu *emu, uint32_t segment, uint32_t offset)
501 return (*emu->emu_rdw) (emu, ((uint32_t) segment << 4) + offset);
506 * segment - Segment to load data from
507 * offset - Offset to load data from
510 * Long value read from the absolute memory location.
512 * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
515 fetch_long(struct x86emu *emu, uint32_t segment, uint32_t offset)
517 return (*emu->emu_rdl) (emu, ((uint32_t) segment << 4) + offset);
522 * offset - Offset to store data at
523 * val - Value to store
526 * Writes a word value to an segmented memory location. The segment used is
527 * the current 'default' segment, which may have been overridden.
529 * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
532 store_data_byte(struct x86emu *emu, uint32_t offset, uint8_t val)
534 store_byte(emu, get_data_segment(emu), offset, val);
539 * offset - Offset to store data at
540 * val - Value to store
543 * Writes a word value to an segmented memory location. The segment used is
544 * the current 'default' segment, which may have been overridden.
546 * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
549 store_data_word(struct x86emu *emu, uint32_t offset, uint16_t val)
551 store_word(emu, get_data_segment(emu), offset, val);
556 * offset - Offset to store data at
557 * val - Value to store
560 * Writes a long value to an segmented memory location. The segment used is
561 * the current 'default' segment, which may have been overridden.
563 * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
566 store_data_long(struct x86emu *emu, uint32_t offset, uint32_t val)
568 store_long(emu, get_data_segment(emu), offset, val);
573 * segment - Segment to store data at
574 * offset - Offset to store data at
575 * val - Value to store
578 * Writes a byte value to an absolute memory location.
580 * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
583 store_byte(struct x86emu *emu, uint32_t segment, uint32_t offset, uint8_t val)
585 (*emu->emu_wrb) (emu, ((uint32_t) segment << 4) + offset, val);
590 * segment - Segment to store data at
591 * offset - Offset to store data at
592 * val - Value to store
595 * Writes a word value to an absolute memory location.
597 * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
600 store_word(struct x86emu *emu, uint32_t segment, uint32_t offset, uint16_t val)
602 (*emu->emu_wrw) (emu, ((uint32_t) segment << 4) + offset, val);
607 * segment - Segment to store data at
608 * offset - Offset to store data at
609 * val - Value to store
612 * Writes a long value to an absolute memory location.
614 * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
617 store_long(struct x86emu *emu, uint32_t segment, uint32_t offset, uint32_t val)
619 (*emu->emu_wrl) (emu, ((uint32_t) segment << 4) + offset, val);
624 * reg - Register to decode
627 * Pointer to the appropriate register
630 * Return a pointer to the register given by the R/RM field of the
631 * modrm byte, for byte operands. Also enables the decoding of instructions.
634 decode_rm_byte_register(struct x86emu *emu, int reg)
638 return &emu->x86.R_AL;
640 return &emu->x86.R_CL;
642 return &emu->x86.R_DL;
644 return &emu->x86.R_BL;
646 return &emu->x86.R_AH;
648 return &emu->x86.R_CH;
650 return &emu->x86.R_DH;
652 return &emu->x86.R_BH;
654 x86emu_halt_sys(emu);
659 decode_rl_byte_register(struct x86emu *emu)
661 return decode_rm_byte_register(emu, emu->cur_rl);
665 decode_rh_byte_register(struct x86emu *emu)
667 return decode_rm_byte_register(emu, emu->cur_rh);
672 * reg - Register to decode
675 * Pointer to the appropriate register
678 * Return a pointer to the register given by the R/RM field of the
679 * modrm byte, for word operands. Also enables the decoding of instructions.
682 decode_rm_word_register(struct x86emu *emu, int reg)
686 return &emu->x86.R_AX;
688 return &emu->x86.R_CX;
690 return &emu->x86.R_DX;
692 return &emu->x86.R_BX;
694 return &emu->x86.R_SP;
696 return &emu->x86.R_BP;
698 return &emu->x86.R_SI;
700 return &emu->x86.R_DI;
702 x86emu_halt_sys(emu);
707 decode_rl_word_register(struct x86emu *emu)
709 return decode_rm_word_register(emu, emu->cur_rl);
713 decode_rh_word_register(struct x86emu *emu)
715 return decode_rm_word_register(emu, emu->cur_rh);
720 * reg - Register to decode
723 * Pointer to the appropriate register
726 * Return a pointer to the register given by the R/RM field of the
727 * modrm byte, for dword operands. Also enables the decoding of instructions.
730 decode_rm_long_register(struct x86emu *emu, int reg)
734 return &emu->x86.R_EAX;
736 return &emu->x86.R_ECX;
738 return &emu->x86.R_EDX;
740 return &emu->x86.R_EBX;
742 return &emu->x86.R_ESP;
744 return &emu->x86.R_EBP;
746 return &emu->x86.R_ESI;
748 return &emu->x86.R_EDI;
750 x86emu_halt_sys(emu);
755 decode_rl_long_register(struct x86emu *emu)
757 return decode_rm_long_register(emu, emu->cur_rl);
761 decode_rh_long_register(struct x86emu *emu)
763 return decode_rm_long_register(emu, emu->cur_rh);
769 * reg - Register to decode
772 * Pointer to the appropriate register
775 * Return a pointer to the register given by the R/RM field of the
776 * modrm byte, for word operands, modified from above for the weirdo
777 * special case of segreg operands. Also enables the decoding of instructions.
780 decode_rh_seg_register(struct x86emu *emu)
782 switch (emu->cur_rh) {
784 return &emu->x86.R_ES;
786 return &emu->x86.R_CS;
788 return &emu->x86.R_SS;
790 return &emu->x86.R_DS;
792 return &emu->x86.R_FS;
794 return &emu->x86.R_GS;
796 x86emu_halt_sys(emu);
801 * return offset from the SIB Byte
804 decode_sib_address(struct x86emu *emu, int sib, int mod)
806 uint32_t base = 0, i = 0, scale = 1;
808 switch (sib & 0x07) {
810 base = emu->x86.R_EAX;
813 base = emu->x86.R_ECX;
817 base = emu->x86.R_EDX;
820 base = emu->x86.R_EBX;
823 base = emu->x86.R_ESP;
824 emu->x86.mode |= SYSMODE_SEG_DS_SS;
828 base = fetch_long_imm(emu);
830 base = emu->x86.R_EBP;
831 emu->x86.mode |= SYSMODE_SEG_DS_SS;
835 base = emu->x86.R_ESI;
838 base = emu->x86.R_EDI;
841 switch ((sib >> 3) & 0x07) {
867 scale = 1 << ((sib >> 6) & 0x03);
868 return base + (i * scale);
873 * rm - RM value to decode
876 * Offset in memory for the address decoding
879 * Return the offset given by mod=00, mod=01 or mod=10 addressing.
880 * Also enables the decoding of instructions.
883 decode_rl_address(struct x86emu *emu)
885 if (emu->x86.mode & SYSMODE_PREFIX_ADDR) {
886 uint32_t offset, sib;
887 /* 32-bit addressing */
888 switch (emu->cur_rl) {
890 offset = emu->x86.R_EAX;
893 offset = emu->x86.R_ECX;
896 offset = emu->x86.R_EDX;
899 offset = emu->x86.R_EBX;
902 sib = fetch_byte_imm(emu);
903 offset = decode_sib_address(emu, sib, 0);
906 if (emu->cur_mod == 0) {
907 offset = fetch_long_imm(emu);
909 emu->x86.mode |= SYSMODE_SEG_DS_SS;
910 offset = emu->x86.R_EBP;
914 offset = emu->x86.R_ESI;
917 offset = emu->x86.R_EDI;
920 x86emu_halt_sys(emu);
922 if (emu->cur_mod == 1)
923 offset += (int8_t)fetch_byte_imm(emu);
924 else if (emu->cur_mod == 2)
925 offset += fetch_long_imm(emu);
930 /* 16-bit addressing */
931 switch (emu->cur_rl) {
933 offset = emu->x86.R_BX + emu->x86.R_SI;
936 offset = emu->x86.R_BX + emu->x86.R_DI;
939 emu->x86.mode |= SYSMODE_SEG_DS_SS;
940 offset = emu->x86.R_BP + emu->x86.R_SI;
943 emu->x86.mode |= SYSMODE_SEG_DS_SS;
944 offset = emu->x86.R_BP + emu->x86.R_DI;
947 offset = emu->x86.R_SI;
950 offset = emu->x86.R_DI;
953 if (emu->cur_mod == 0) {
954 offset = fetch_word_imm(emu);
956 emu->x86.mode |= SYSMODE_SEG_DS_SS;
957 offset = emu->x86.R_BP;
961 offset = emu->x86.R_BX;
964 x86emu_halt_sys(emu);
966 if (emu->cur_mod == 1)
967 offset += (int8_t)fetch_byte_imm(emu);
968 else if (emu->cur_mod == 2)
969 offset += fetch_word_imm(emu);
975 decode_and_fetch_byte(struct x86emu *emu)
977 if (emu->cur_mod != 3) {
978 emu->cur_offset = decode_rl_address(emu);
979 return fetch_data_byte(emu, emu->cur_offset);
981 return *decode_rl_byte_register(emu);
986 decode_and_fetch_word_disp(struct x86emu *emu, int16_t disp)
988 if (emu->cur_mod != 3) {
989 /* TODO: A20 gate emulation */
990 emu->cur_offset = decode_rl_address(emu) + disp;
991 if ((emu->x86.mode & SYSMODE_PREFIX_ADDR) == 0)
992 emu->cur_offset &= 0xffff;
993 return fetch_data_word(emu, emu->cur_offset);
995 return *decode_rl_word_register(emu);
1000 decode_and_fetch_long_disp(struct x86emu *emu, int16_t disp)
1002 if (emu->cur_mod != 3) {
1003 /* TODO: A20 gate emulation */
1004 emu->cur_offset = decode_rl_address(emu) + disp;
1005 if ((emu->x86.mode & SYSMODE_PREFIX_ADDR) == 0)
1006 emu->cur_offset &= 0xffff;
1007 return fetch_data_long(emu, emu->cur_offset);
1009 return *decode_rl_long_register(emu);
1014 decode_and_fetch_word(struct x86emu *emu)
1016 return decode_and_fetch_word_disp(emu, 0);
1020 decode_and_fetch_long(struct x86emu *emu)
1022 return decode_and_fetch_long_disp(emu, 0);
1026 decode_and_fetch_byte_imm8(struct x86emu *emu, uint8_t *imm)
1028 if (emu->cur_mod != 3) {
1029 emu->cur_offset = decode_rl_address(emu);
1030 *imm = fetch_byte_imm(emu);
1031 return fetch_data_byte(emu, emu->cur_offset);
1033 *imm = fetch_byte_imm(emu);
1034 return *decode_rl_byte_register(emu);
1039 decode_and_fetch_word_imm8(struct x86emu *emu, uint8_t *imm)
1041 if (emu->cur_mod != 3) {
1042 emu->cur_offset = decode_rl_address(emu);
1043 *imm = fetch_byte_imm(emu);
1044 return fetch_data_word(emu, emu->cur_offset);
1046 *imm = fetch_byte_imm(emu);
1047 return *decode_rl_word_register(emu);
1052 decode_and_fetch_long_imm8(struct x86emu *emu, uint8_t *imm)
1054 if (emu->cur_mod != 3) {
1055 emu->cur_offset = decode_rl_address(emu);
1056 *imm = fetch_byte_imm(emu);
1057 return fetch_data_long(emu, emu->cur_offset);
1059 *imm = fetch_byte_imm(emu);
1060 return *decode_rl_long_register(emu);
1065 write_back_byte(struct x86emu *emu, uint8_t val)
1067 if (emu->cur_mod != 3)
1068 store_data_byte(emu, emu->cur_offset, val);
1070 *decode_rl_byte_register(emu) = val;
1074 write_back_word(struct x86emu *emu, uint16_t val)
1076 if (emu->cur_mod != 3)
1077 store_data_word(emu, emu->cur_offset, val);
1079 *decode_rl_word_register(emu) = val;
1083 write_back_long(struct x86emu *emu, uint32_t val)
1085 if (emu->cur_mod != 3)
1086 store_data_long(emu, emu->cur_offset, val);
1088 *decode_rl_long_register(emu) = val;
1092 common_inc_word_long(struct x86emu *emu, union x86emu_register *reg)
1094 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1095 reg->I32_reg.e_reg = inc_long(emu, reg->I32_reg.e_reg);
1097 reg->I16_reg.x_reg = inc_word(emu, reg->I16_reg.x_reg);
1101 common_dec_word_long(struct x86emu *emu, union x86emu_register *reg)
1103 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1104 reg->I32_reg.e_reg = dec_long(emu, reg->I32_reg.e_reg);
1106 reg->I16_reg.x_reg = dec_word(emu, reg->I16_reg.x_reg);
1110 common_binop_byte_rm_r(struct x86emu *emu, uint8_t (*binop)(struct x86emu *, uint8_t, uint8_t))
1112 uint32_t destoffset;
1113 uint8_t *destreg, srcval;
1116 fetch_decode_modrm(emu);
1117 srcval = *decode_rh_byte_register(emu);
1118 if (emu->cur_mod != 3) {
1119 destoffset = decode_rl_address(emu);
1120 destval = fetch_data_byte(emu, destoffset);
1121 destval = (*binop)(emu, destval, srcval);
1122 store_data_byte(emu, destoffset, destval);
1124 destreg = decode_rl_byte_register(emu);
1125 *destreg = (*binop)(emu, *destreg, srcval);
1130 common_binop_ns_byte_rm_r(struct x86emu *emu, void (*binop)(struct x86emu *, uint8_t, uint8_t))
1132 uint32_t destoffset;
1133 uint8_t destval, srcval;
1135 fetch_decode_modrm(emu);
1136 srcval = *decode_rh_byte_register(emu);
1137 if (emu->cur_mod != 3) {
1138 destoffset = decode_rl_address(emu);
1139 destval = fetch_data_byte(emu, destoffset);
1141 destval = *decode_rl_byte_register(emu);
1143 (*binop)(emu, destval, srcval);
1147 common_binop_word_rm_r(struct x86emu *emu, uint16_t (*binop)(struct x86emu *, uint16_t, uint16_t))
1149 uint32_t destoffset;
1150 uint16_t destval, *destreg, srcval;
1152 fetch_decode_modrm(emu);
1153 srcval = *decode_rh_word_register(emu);
1154 if (emu->cur_mod != 3) {
1155 destoffset = decode_rl_address(emu);
1156 destval = fetch_data_word(emu, destoffset);
1157 destval = (*binop)(emu, destval, srcval);
1158 store_data_word(emu, destoffset, destval);
1160 destreg = decode_rl_word_register(emu);
1161 *destreg = (*binop)(emu, *destreg, srcval);
1166 common_binop_byte_r_rm(struct x86emu *emu, uint8_t (*binop)(struct x86emu *, uint8_t, uint8_t))
1168 uint8_t *destreg, srcval;
1171 fetch_decode_modrm(emu);
1172 destreg = decode_rh_byte_register(emu);
1173 if (emu->cur_mod != 3) {
1174 srcoffset = decode_rl_address(emu);
1175 srcval = fetch_data_byte(emu, srcoffset);
1177 srcval = *decode_rl_byte_register(emu);
1179 *destreg = (*binop)(emu, *destreg, srcval);
1183 common_binop_long_rm_r(struct x86emu *emu, uint32_t (*binop)(struct x86emu *, uint32_t, uint32_t))
1185 uint32_t destoffset;
1186 uint32_t destval, *destreg, srcval;
1188 fetch_decode_modrm(emu);
1189 srcval = *decode_rh_long_register(emu);
1190 if (emu->cur_mod != 3) {
1191 destoffset = decode_rl_address(emu);
1192 destval = fetch_data_long(emu, destoffset);
1193 destval = (*binop)(emu, destval, srcval);
1194 store_data_long(emu, destoffset, destval);
1196 destreg = decode_rl_long_register(emu);
1197 *destreg = (*binop)(emu, *destreg, srcval);
1202 common_binop_word_long_rm_r(struct x86emu *emu,
1203 uint16_t (*binop16)(struct x86emu *, uint16_t, uint16_t), uint32_t (*binop32)(struct x86emu *, uint32_t, uint32_t))
1205 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1206 common_binop_long_rm_r(emu, binop32);
1208 common_binop_word_rm_r(emu, binop16);
1212 common_binop_ns_word_rm_r(struct x86emu *emu, void (*binop)(struct x86emu *, uint16_t, uint16_t))
1214 uint32_t destoffset;
1215 uint16_t destval, srcval;
1217 fetch_decode_modrm(emu);
1218 srcval = *decode_rh_word_register(emu);
1219 if (emu->cur_mod != 3) {
1220 destoffset = decode_rl_address(emu);
1221 destval = fetch_data_word(emu, destoffset);
1223 destval = *decode_rl_word_register(emu);
1225 (*binop)(emu, destval, srcval);
1230 common_binop_ns_long_rm_r(struct x86emu *emu, void (*binop)(struct x86emu *, uint32_t, uint32_t))
1232 uint32_t destoffset;
1233 uint32_t destval, srcval;
1235 fetch_decode_modrm(emu);
1236 srcval = *decode_rh_long_register(emu);
1237 if (emu->cur_mod != 3) {
1238 destoffset = decode_rl_address(emu);
1239 destval = fetch_data_long(emu, destoffset);
1241 destval = *decode_rl_long_register(emu);
1243 (*binop)(emu, destval, srcval);
1247 common_binop_ns_word_long_rm_r(struct x86emu *emu,
1248 void (*binop16)(struct x86emu *, uint16_t, uint16_t), void (*binop32)(struct x86emu *, uint32_t, uint32_t))
1250 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1251 common_binop_ns_long_rm_r(emu, binop32);
1253 common_binop_ns_word_rm_r(emu, binop16);
1257 common_binop_long_r_rm(struct x86emu *emu, uint32_t (*binop)(struct x86emu *, uint32_t, uint32_t))
1260 uint32_t *destreg, srcval;
1262 fetch_decode_modrm(emu);
1263 destreg = decode_rh_long_register(emu);
1264 if (emu->cur_mod != 3) {
1265 srcoffset = decode_rl_address(emu);
1266 srcval = fetch_data_long(emu, srcoffset);
1268 srcval = *decode_rl_long_register(emu);
1270 *destreg = (*binop)(emu, *destreg, srcval);
1274 common_binop_word_r_rm(struct x86emu *emu, uint16_t (*binop)(struct x86emu *, uint16_t, uint16_t))
1277 uint16_t *destreg, srcval;
1279 fetch_decode_modrm(emu);
1280 destreg = decode_rh_word_register(emu);
1281 if (emu->cur_mod != 3) {
1282 srcoffset = decode_rl_address(emu);
1283 srcval = fetch_data_word(emu, srcoffset);
1285 srcval = *decode_rl_word_register(emu);
1287 *destreg = (*binop)(emu, *destreg, srcval);
1291 common_binop_word_long_r_rm(struct x86emu *emu,
1292 uint16_t (*binop16)(struct x86emu *, uint16_t, uint16_t), uint32_t (*binop32)(struct x86emu *, uint32_t, uint32_t))
1294 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1295 common_binop_long_r_rm(emu, binop32);
1297 common_binop_word_r_rm(emu, binop16);
1301 common_binop_byte_imm(struct x86emu *emu, uint8_t (*binop)(struct x86emu *, uint8_t, uint8_t))
1305 srcval = fetch_byte_imm(emu);
1306 emu->x86.R_AL = (*binop)(emu, emu->x86.R_AL, srcval);
1310 common_binop_word_long_imm(struct x86emu *emu,
1311 uint16_t (*binop16)(struct x86emu *, uint16_t, uint16_t), uint32_t (*binop32)(struct x86emu *, uint32_t, uint32_t))
1313 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1316 srcval = fetch_long_imm(emu);
1317 emu->x86.R_EAX = (*binop32)(emu, emu->x86.R_EAX, srcval);
1321 srcval = fetch_word_imm(emu);
1322 emu->x86.R_AX = (*binop16)(emu, emu->x86.R_AX, srcval);
1327 common_push_word_long(struct x86emu *emu, union x86emu_register *reg)
1329 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1330 push_long(emu, reg->I32_reg.e_reg);
1332 push_word(emu, reg->I16_reg.x_reg);
1336 common_pop_word_long(struct x86emu *emu, union x86emu_register *reg)
1338 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1339 reg->I32_reg.e_reg = pop_long(emu);
1341 reg->I16_reg.x_reg = pop_word(emu);
1345 common_imul_long_IMM(struct x86emu *emu, int byte_imm)
1348 uint32_t *destreg, srcval;
1352 fetch_decode_modrm(emu);
1353 destreg = decode_rh_long_register(emu);
1354 if (emu->cur_mod != 3) {
1355 srcoffset = decode_rl_address(emu);
1356 srcval = fetch_data_long(emu, srcoffset);
1358 srcval = *decode_rl_long_register(emu);
1362 imm = (int8_t)fetch_byte_imm(emu);
1364 imm = fetch_long_imm(emu);
1365 res = (int32_t)srcval * imm;
1367 if (res > 0xffffffff) {
1374 *destreg = (uint32_t)res;
1378 common_imul_word_IMM(struct x86emu *emu, int byte_imm)
1381 uint16_t *destreg, srcval;
1385 fetch_decode_modrm(emu);
1386 destreg = decode_rh_word_register(emu);
1387 if (emu->cur_mod != 3) {
1388 srcoffset = decode_rl_address(emu);
1389 srcval = fetch_data_word(emu, srcoffset);
1391 srcval = *decode_rl_word_register(emu);
1395 imm = (int8_t)fetch_byte_imm(emu);
1397 imm = fetch_word_imm(emu);
1398 res = (int16_t)srcval * imm;
1407 *destreg = (uint16_t) res;
1411 common_imul_imm(struct x86emu *emu, int byte_imm)
1413 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1414 common_imul_long_IMM(emu, byte_imm);
1416 common_imul_word_IMM(emu, byte_imm);
1420 common_jmp_near(struct x86emu *emu, int cond)
1425 offset = (int8_t) fetch_byte_imm(emu);
1426 target = (uint16_t) (emu->x86.R_IP + (int16_t) offset);
1428 emu->x86.R_IP = target;
1432 common_load_far_pointer(struct x86emu *emu, uint16_t *seg)
1437 fetch_decode_modrm(emu);
1438 if (emu->cur_mod == 3)
1439 x86emu_halt_sys(emu);
1441 dstreg = decode_rh_word_register(emu);
1442 srcoffset = decode_rl_address(emu);
1443 *dstreg = fetch_data_word(emu, srcoffset);
1444 *seg = fetch_data_word(emu, srcoffset + 2);
1447 /* Implementation */
1451 * Handles opcode 0x3a
1454 x86emuOp_cmp_byte_R_RM(struct x86emu *emu)
1456 uint8_t *destreg, srcval;
1458 fetch_decode_modrm(emu);
1459 destreg = decode_rh_byte_register(emu);
1460 srcval = decode_and_fetch_byte(emu);
1461 cmp_byte(emu, *destreg, srcval);
1467 * Handles opcode 0x3b
1470 x86emuOp32_cmp_word_R_RM(struct x86emu *emu)
1472 uint32_t srcval, *destreg;
1474 fetch_decode_modrm(emu);
1475 destreg = decode_rh_long_register(emu);
1476 srcval = decode_and_fetch_long(emu);
1477 cmp_long(emu, *destreg, srcval);
1481 x86emuOp16_cmp_word_R_RM(struct x86emu *emu)
1483 uint16_t srcval, *destreg;
1485 fetch_decode_modrm(emu);
1486 destreg = decode_rh_word_register(emu);
1487 srcval = decode_and_fetch_word(emu);
1488 cmp_word(emu, *destreg, srcval);
1492 x86emuOp_cmp_word_R_RM(struct x86emu *emu)
1494 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1495 x86emuOp32_cmp_word_R_RM(emu);
1497 x86emuOp16_cmp_word_R_RM(emu);
1502 * Handles opcode 0x3c
1505 x86emuOp_cmp_byte_AL_IMM(struct x86emu *emu)
1509 srcval = fetch_byte_imm(emu);
1510 cmp_byte(emu, emu->x86.R_AL, srcval);
1515 * Handles opcode 0x3d
1518 x86emuOp32_cmp_word_AX_IMM(struct x86emu *emu)
1522 srcval = fetch_long_imm(emu);
1523 cmp_long(emu, emu->x86.R_EAX, srcval);
1527 x86emuOp16_cmp_word_AX_IMM(struct x86emu *emu)
1531 srcval = fetch_word_imm(emu);
1532 cmp_word(emu, emu->x86.R_AX, srcval);
1536 x86emuOp_cmp_word_AX_IMM(struct x86emu *emu)
1538 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1539 x86emuOp32_cmp_word_AX_IMM(emu);
1541 x86emuOp16_cmp_word_AX_IMM(emu);
1546 * Handles opcode 0x60
1549 x86emuOp_push_all(struct x86emu *emu)
1551 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1552 uint32_t old_sp = emu->x86.R_ESP;
1554 push_long(emu, emu->x86.R_EAX);
1555 push_long(emu, emu->x86.R_ECX);
1556 push_long(emu, emu->x86.R_EDX);
1557 push_long(emu, emu->x86.R_EBX);
1558 push_long(emu, old_sp);
1559 push_long(emu, emu->x86.R_EBP);
1560 push_long(emu, emu->x86.R_ESI);
1561 push_long(emu, emu->x86.R_EDI);
1563 uint16_t old_sp = emu->x86.R_SP;
1565 push_word(emu, emu->x86.R_AX);
1566 push_word(emu, emu->x86.R_CX);
1567 push_word(emu, emu->x86.R_DX);
1568 push_word(emu, emu->x86.R_BX);
1569 push_word(emu, old_sp);
1570 push_word(emu, emu->x86.R_BP);
1571 push_word(emu, emu->x86.R_SI);
1572 push_word(emu, emu->x86.R_DI);
1578 * Handles opcode 0x61
1581 x86emuOp_pop_all(struct x86emu *emu)
1583 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1584 emu->x86.R_EDI = pop_long(emu);
1585 emu->x86.R_ESI = pop_long(emu);
1586 emu->x86.R_EBP = pop_long(emu);
1587 emu->x86.R_ESP += 4; /* skip ESP */
1588 emu->x86.R_EBX = pop_long(emu);
1589 emu->x86.R_EDX = pop_long(emu);
1590 emu->x86.R_ECX = pop_long(emu);
1591 emu->x86.R_EAX = pop_long(emu);
1593 emu->x86.R_DI = pop_word(emu);
1594 emu->x86.R_SI = pop_word(emu);
1595 emu->x86.R_BP = pop_word(emu);
1596 emu->x86.R_SP += 2;/* skip SP */
1597 emu->x86.R_BX = pop_word(emu);
1598 emu->x86.R_DX = pop_word(emu);
1599 emu->x86.R_CX = pop_word(emu);
1600 emu->x86.R_AX = pop_word(emu);
1603 /*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */
1604 /*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */
1609 * Handles opcode 0x68
1612 x86emuOp_push_word_IMM(struct x86emu *emu)
1614 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1617 imm = fetch_long_imm(emu);
1618 push_long(emu, imm);
1622 imm = fetch_word_imm(emu);
1623 push_word(emu, imm);
1629 * Handles opcode 0x6a
1632 x86emuOp_push_byte_IMM(struct x86emu *emu)
1636 imm = (int8_t) fetch_byte_imm(emu);
1637 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1638 push_long(emu, (int32_t) imm);
1640 push_word(emu, imm);
1646 * Handles opcode 0x6c and 0x6d
1649 x86emuOp_ins_word(struct x86emu *emu)
1651 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1660 * Handles opcode 0x6f
1663 x86emuOp_outs_word(struct x86emu *emu)
1665 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1674 * Handles opcode 0x7c
1677 x86emuOp_jump_near_L(struct x86emu *emu)
1681 sf = ACCESS_FLAG(F_SF) != 0;
1682 of = ACCESS_FLAG(F_OF) != 0;
1684 common_jmp_near(emu, sf != of);
1689 * Handles opcode 0x7d
1692 x86emuOp_jump_near_NL(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 0x7e
1707 x86emuOp_jump_near_LE(struct x86emu *emu)
1711 sf = ACCESS_FLAG(F_SF) != 0;
1712 of = ACCESS_FLAG(F_OF) != 0;
1714 common_jmp_near(emu, sf != of || ACCESS_FLAG(F_ZF));
1719 * Handles opcode 0x7f
1722 x86emuOp_jump_near_NLE(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));
1733 uint8_t(*const opc80_byte_operation[]) (struct x86emu *, uint8_t d, uint8_t s) =
1747 * Handles opcode 0x80
1750 x86emuOp_opc80_byte_RM_IMM(struct x86emu *emu)
1752 uint8_t imm, destval;
1755 * Weirdo special case instruction format. Part of the opcode
1756 * held below in "RH". Doubly nested case would result, except
1757 * that the decoded instruction
1759 fetch_decode_modrm(emu);
1760 destval = decode_and_fetch_byte(emu);
1761 imm = fetch_byte_imm(emu);
1762 destval = (*opc80_byte_operation[emu->cur_rh]) (emu, destval, imm);
1763 if (emu->cur_rh != 7)
1764 write_back_byte(emu, destval);
1768 uint16_t(* const opc81_word_operation[]) (struct x86emu *, uint16_t d, uint16_t s) =
1781 uint32_t(* const opc81_long_operation[]) (struct x86emu *, uint32_t d, uint32_t s) =
1795 * Handles opcode 0x81
1798 x86emuOp32_opc81_word_RM_IMM(struct x86emu *emu)
1800 uint32_t destval, imm;
1803 * Weirdo special case instruction format. Part of the opcode
1804 * held below in "RH". Doubly nested case would result, except
1805 * that the decoded instruction
1807 fetch_decode_modrm(emu);
1808 destval = decode_and_fetch_long(emu);
1809 imm = fetch_long_imm(emu);
1810 destval = (*opc81_long_operation[emu->cur_rh]) (emu, destval, imm);
1811 if (emu->cur_rh != 7)
1812 write_back_long(emu, destval);
1816 x86emuOp16_opc81_word_RM_IMM(struct x86emu *emu)
1818 uint16_t destval, imm;
1821 * Weirdo special case instruction format. Part of the opcode
1822 * held below in "RH". Doubly nested case would result, except
1823 * that the decoded instruction
1825 fetch_decode_modrm(emu);
1826 destval = decode_and_fetch_word(emu);
1827 imm = fetch_word_imm(emu);
1828 destval = (*opc81_word_operation[emu->cur_rh]) (emu, destval, imm);
1829 if (emu->cur_rh != 7)
1830 write_back_word(emu, destval);
1834 x86emuOp_opc81_word_RM_IMM(struct x86emu *emu)
1836 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1837 x86emuOp32_opc81_word_RM_IMM(emu);
1839 x86emuOp16_opc81_word_RM_IMM(emu);
1843 uint8_t(* const opc82_byte_operation[]) (struct x86emu *, uint8_t s, uint8_t d) =
1846 or_byte, /* 01 *//* YYY UNUSED ???? */
1849 and_byte, /* 04 *//* YYY UNUSED ???? */
1851 xor_byte, /* 06 *//* YYY UNUSED ???? */
1857 * Handles opcode 0x82
1860 x86emuOp_opc82_byte_RM_IMM(struct x86emu *emu)
1862 uint8_t imm, destval;
1865 * Weirdo special case instruction format. Part of the opcode
1866 * held below in "RH". Doubly nested case would result, except
1867 * that the decoded instruction Similar to opcode 81, except that
1868 * the immediate byte is sign extended to a word length.
1870 fetch_decode_modrm(emu);
1871 destval = decode_and_fetch_byte(emu);
1872 imm = fetch_byte_imm(emu);
1873 destval = (*opc82_byte_operation[emu->cur_rh]) (emu, destval, imm);
1874 if (emu->cur_rh != 7)
1875 write_back_byte(emu, destval);
1879 uint16_t(* const opc83_word_operation[]) (struct x86emu *, uint16_t s, uint16_t d) =
1882 or_word, /* 01 *//* YYY UNUSED ???? */
1885 and_word, /* 04 *//* YYY UNUSED ???? */
1887 xor_word, /* 06 *//* YYY UNUSED ???? */
1892 uint32_t(* const opc83_long_operation[]) (struct x86emu *, uint32_t s, uint32_t d) =
1895 or_long, /* 01 *//* YYY UNUSED ???? */
1898 and_long, /* 04 *//* YYY UNUSED ???? */
1900 xor_long, /* 06 *//* YYY UNUSED ???? */
1906 * Handles opcode 0x83
1909 x86emuOp32_opc83_word_RM_IMM(struct x86emu *emu)
1911 uint32_t destval, imm;
1913 fetch_decode_modrm(emu);
1914 destval = decode_and_fetch_long(emu);
1915 imm = (int8_t) fetch_byte_imm(emu);
1916 destval = (*opc83_long_operation[emu->cur_rh]) (emu, destval, imm);
1917 if (emu->cur_rh != 7)
1918 write_back_long(emu, destval);
1922 x86emuOp16_opc83_word_RM_IMM(struct x86emu *emu)
1924 uint16_t destval, imm;
1926 fetch_decode_modrm(emu);
1927 destval = decode_and_fetch_word(emu);
1928 imm = (int8_t) fetch_byte_imm(emu);
1929 destval = (*opc83_word_operation[emu->cur_rh]) (emu, destval, imm);
1930 if (emu->cur_rh != 7)
1931 write_back_word(emu, destval);
1935 x86emuOp_opc83_word_RM_IMM(struct x86emu *emu)
1937 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1938 x86emuOp32_opc83_word_RM_IMM(emu);
1940 x86emuOp16_opc83_word_RM_IMM(emu);
1945 * Handles opcode 0x86
1948 x86emuOp_xchg_byte_RM_R(struct x86emu *emu)
1950 uint8_t *srcreg, destval, tmp;
1952 fetch_decode_modrm(emu);
1953 destval = decode_and_fetch_byte(emu);
1954 srcreg = decode_rh_byte_register(emu);
1958 write_back_byte(emu, destval);
1963 * Handles opcode 0x87
1966 x86emuOp32_xchg_word_RM_R(struct x86emu *emu)
1968 uint32_t *srcreg, destval, tmp;
1970 fetch_decode_modrm(emu);
1971 destval = decode_and_fetch_long(emu);
1972 srcreg = decode_rh_long_register(emu);
1976 write_back_long(emu, destval);
1980 x86emuOp16_xchg_word_RM_R(struct x86emu *emu)
1982 uint16_t *srcreg, destval, tmp;
1984 fetch_decode_modrm(emu);
1985 destval = decode_and_fetch_word(emu);
1986 srcreg = decode_rh_word_register(emu);
1990 write_back_word(emu, destval);
1994 x86emuOp_xchg_word_RM_R(struct x86emu *emu)
1996 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1997 x86emuOp32_xchg_word_RM_R(emu);
1999 x86emuOp16_xchg_word_RM_R(emu);
2004 * Handles opcode 0x88
2007 x86emuOp_mov_byte_RM_R(struct x86emu *emu)
2009 uint8_t *destreg, *srcreg;
2010 uint32_t destoffset;
2012 fetch_decode_modrm(emu);
2013 srcreg = decode_rh_byte_register(emu);
2014 if (emu->cur_mod != 3) {
2015 destoffset = decode_rl_address(emu);
2016 store_data_byte(emu, destoffset, *srcreg);
2018 destreg = decode_rl_byte_register(emu);
2025 * Handles opcode 0x89
2028 x86emuOp32_mov_word_RM_R(struct x86emu *emu)
2030 uint32_t destoffset;
2031 uint32_t *destreg, srcval;
2033 fetch_decode_modrm(emu);
2034 srcval = *decode_rh_long_register(emu);
2035 if (emu->cur_mod != 3) {
2036 destoffset = decode_rl_address(emu);
2037 store_data_long(emu, destoffset, srcval);
2039 destreg = decode_rl_long_register(emu);
2045 x86emuOp16_mov_word_RM_R(struct x86emu *emu)
2047 uint32_t destoffset;
2048 uint16_t *destreg, srcval;
2050 fetch_decode_modrm(emu);
2051 srcval = *decode_rh_word_register(emu);
2052 if (emu->cur_mod != 3) {
2053 destoffset = decode_rl_address(emu);
2054 store_data_word(emu, destoffset, srcval);
2056 destreg = decode_rl_word_register(emu);
2062 x86emuOp_mov_word_RM_R(struct x86emu *emu)
2064 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2065 x86emuOp32_mov_word_RM_R(emu);
2067 x86emuOp16_mov_word_RM_R(emu);
2072 * Handles opcode 0x8a
2075 x86emuOp_mov_byte_R_RM(struct x86emu *emu)
2079 fetch_decode_modrm(emu);
2080 destreg = decode_rh_byte_register(emu);
2081 *destreg = decode_and_fetch_byte(emu);
2086 * Handles opcode 0x8b
2089 x86emuOp_mov_word_R_RM(struct x86emu *emu)
2091 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2094 fetch_decode_modrm(emu);
2095 destreg = decode_rh_long_register(emu);
2096 *destreg = decode_and_fetch_long(emu);
2100 fetch_decode_modrm(emu);
2101 destreg = decode_rh_word_register(emu);
2102 *destreg = decode_and_fetch_word(emu);
2108 * Handles opcode 0x8c
2111 x86emuOp_mov_word_RM_SR(struct x86emu *emu)
2113 uint16_t *destreg, srcval;
2114 uint32_t destoffset;
2116 fetch_decode_modrm(emu);
2117 srcval = *decode_rh_seg_register(emu);
2118 if (emu->cur_mod != 3) {
2119 destoffset = decode_rl_address(emu);
2120 store_data_word(emu, destoffset, srcval);
2122 destreg = decode_rl_word_register(emu);
2129 * Handles opcode 0x8d
2132 x86emuOp_lea_word_R_M(struct x86emu *emu)
2135 uint32_t destoffset;
2138 * TODO: Need to handle address size prefix!
2140 * lea eax,[eax+ebx*2] ??
2142 fetch_decode_modrm(emu);
2143 if (emu->cur_mod == 3)
2144 x86emu_halt_sys(emu);
2146 srcreg = decode_rh_word_register(emu);
2147 destoffset = decode_rl_address(emu);
2148 *srcreg = (uint16_t) destoffset;
2153 * Handles opcode 0x8e
2156 x86emuOp_mov_word_SR_RM(struct x86emu *emu)
2160 fetch_decode_modrm(emu);
2161 destreg = decode_rh_seg_register(emu);
2162 *destreg = decode_and_fetch_word(emu);
2164 * Clean up, and reset all the R_xSP pointers to the correct
2165 * locations. This is about 3x too much overhead (doing all the
2166 * segreg ptrs when only one is needed, but this instruction
2167 * *cannot* be that common, and this isn't too much work anyway.
2173 * Handles opcode 0x8f
2176 x86emuOp32_pop_RM(struct x86emu *emu)
2178 uint32_t destoffset;
2179 uint32_t destval, *destreg;
2181 fetch_decode_modrm(emu);
2182 if (emu->cur_mod != 3) {
2183 destoffset = decode_rl_address(emu);
2184 destval = pop_long(emu);
2185 store_data_long(emu, destoffset, destval);
2187 destreg = decode_rl_long_register(emu);
2188 *destreg = pop_long(emu);
2193 x86emuOp16_pop_RM(struct x86emu *emu)
2195 uint32_t destoffset;
2196 uint16_t destval, *destreg;
2198 fetch_decode_modrm(emu);
2199 if (emu->cur_mod != 3) {
2200 destoffset = decode_rl_address(emu);
2201 destval = pop_word(emu);
2202 store_data_word(emu, destoffset, destval);
2204 destreg = decode_rl_word_register(emu);
2205 *destreg = pop_word(emu);
2210 x86emuOp_pop_RM(struct x86emu *emu)
2212 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2213 x86emuOp32_pop_RM(emu);
2215 x86emuOp16_pop_RM(emu);
2220 * Handles opcode 0x91
2223 x86emuOp_xchg_word_AX_CX(struct x86emu *emu)
2227 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2228 tmp = emu->x86.R_EAX;
2229 emu->x86.R_EAX = emu->x86.R_ECX;
2230 emu->x86.R_ECX = tmp;
2232 tmp = emu->x86.R_AX;
2233 emu->x86.R_AX = emu->x86.R_CX;
2234 emu->x86.R_CX = (uint16_t) tmp;
2240 * Handles opcode 0x92
2243 x86emuOp_xchg_word_AX_DX(struct x86emu *emu)
2247 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2248 tmp = emu->x86.R_EAX;
2249 emu->x86.R_EAX = emu->x86.R_EDX;
2250 emu->x86.R_EDX = tmp;
2252 tmp = emu->x86.R_AX;
2253 emu->x86.R_AX = emu->x86.R_DX;
2254 emu->x86.R_DX = (uint16_t) tmp;
2260 * Handles opcode 0x93
2263 x86emuOp_xchg_word_AX_BX(struct x86emu *emu)
2267 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2268 tmp = emu->x86.R_EAX;
2269 emu->x86.R_EAX = emu->x86.R_EBX;
2270 emu->x86.R_EBX = tmp;
2272 tmp = emu->x86.R_AX;
2273 emu->x86.R_AX = emu->x86.R_BX;
2274 emu->x86.R_BX = (uint16_t) tmp;
2280 * Handles opcode 0x94
2283 x86emuOp_xchg_word_AX_SP(struct x86emu *emu)
2287 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2288 tmp = emu->x86.R_EAX;
2289 emu->x86.R_EAX = emu->x86.R_ESP;
2290 emu->x86.R_ESP = tmp;
2292 tmp = emu->x86.R_AX;
2293 emu->x86.R_AX = emu->x86.R_SP;
2294 emu->x86.R_SP = (uint16_t) tmp;
2300 * Handles opcode 0x95
2303 x86emuOp_xchg_word_AX_BP(struct x86emu *emu)
2307 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2308 tmp = emu->x86.R_EAX;
2309 emu->x86.R_EAX = emu->x86.R_EBP;
2310 emu->x86.R_EBP = tmp;
2312 tmp = emu->x86.R_AX;
2313 emu->x86.R_AX = emu->x86.R_BP;
2314 emu->x86.R_BP = (uint16_t) tmp;
2320 * Handles opcode 0x96
2323 x86emuOp_xchg_word_AX_SI(struct x86emu *emu)
2327 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2328 tmp = emu->x86.R_EAX;
2329 emu->x86.R_EAX = emu->x86.R_ESI;
2330 emu->x86.R_ESI = tmp;
2332 tmp = emu->x86.R_AX;
2333 emu->x86.R_AX = emu->x86.R_SI;
2334 emu->x86.R_SI = (uint16_t) tmp;
2340 * Handles opcode 0x97
2343 x86emuOp_xchg_word_AX_DI(struct x86emu *emu)
2347 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2348 tmp = emu->x86.R_EAX;
2349 emu->x86.R_EAX = emu->x86.R_EDI;
2350 emu->x86.R_EDI = tmp;
2352 tmp = emu->x86.R_AX;
2353 emu->x86.R_AX = emu->x86.R_DI;
2354 emu->x86.R_DI = (uint16_t) tmp;
2360 * Handles opcode 0x98
2363 x86emuOp_cbw(struct x86emu *emu)
2365 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2366 if (emu->x86.R_AX & 0x8000) {
2367 emu->x86.R_EAX |= 0xffff0000;
2369 emu->x86.R_EAX &= 0x0000ffff;
2372 if (emu->x86.R_AL & 0x80) {
2373 emu->x86.R_AH = 0xff;
2375 emu->x86.R_AH = 0x0;
2382 * Handles opcode 0x99
2385 x86emuOp_cwd(struct x86emu *emu)
2387 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2388 if (emu->x86.R_EAX & 0x80000000) {
2389 emu->x86.R_EDX = 0xffffffff;
2391 emu->x86.R_EDX = 0x0;
2394 if (emu->x86.R_AX & 0x8000) {
2395 emu->x86.R_DX = 0xffff;
2397 emu->x86.R_DX = 0x0;
2404 * Handles opcode 0x9a
2407 x86emuOp_call_far_IMM(struct x86emu *emu)
2409 uint16_t farseg, faroff;
2411 faroff = fetch_word_imm(emu);
2412 farseg = fetch_word_imm(emu);
2415 * Hooked interrupt vectors calling into our "BIOS" will cause problems
2416 * unless all intersegment stuff is checked for BIOS access. Check
2417 * needed here. For moment, let it alone. */
2418 push_word(emu, emu->x86.R_CS);
2419 emu->x86.R_CS = farseg;
2420 push_word(emu, emu->x86.R_IP);
2421 emu->x86.R_IP = faroff;
2426 * Handles opcode 0x9c
2429 x86emuOp_pushf_word(struct x86emu *emu)
2433 /* clear out *all* bits not representing flags, and turn on real bits */
2434 flags = (emu->x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
2435 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2436 push_long(emu, flags);
2438 push_word(emu, (uint16_t) flags);
2444 * Handles opcode 0x9d
2447 x86emuOp_popf_word(struct x86emu *emu)
2449 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2450 emu->x86.R_EFLG = pop_long(emu);
2452 emu->x86.R_FLG = pop_word(emu);
2458 * Handles opcode 0x9e
2461 x86emuOp_sahf(struct x86emu *emu)
2463 /* clear the lower bits of the flag register */
2464 emu->x86.R_FLG &= 0xffffff00;
2465 /* or in the AH register into the flags register */
2466 emu->x86.R_FLG |= emu->x86.R_AH;
2471 * Handles opcode 0x9f
2474 x86emuOp_lahf(struct x86emu *emu)
2476 emu->x86.R_AH = (uint8_t) (emu->x86.R_FLG & 0xff);
2477 /* undocumented TC++ behavior??? Nope. It's documented, but you have
2478 * too look real hard to notice it. */
2479 emu->x86.R_AH |= 0x2;
2484 * Handles opcode 0xa0
2487 x86emuOp_mov_AL_M_IMM(struct x86emu *emu)
2491 offset = fetch_word_imm(emu);
2492 emu->x86.R_AL = fetch_data_byte(emu, offset);
2497 * Handles opcode 0xa1
2500 x86emuOp_mov_AX_M_IMM(struct x86emu *emu)
2504 offset = fetch_word_imm(emu);
2505 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2506 emu->x86.R_EAX = fetch_data_long(emu, offset);
2508 emu->x86.R_AX = fetch_data_word(emu, offset);
2514 * Handles opcode 0xa2
2517 x86emuOp_mov_M_AL_IMM(struct x86emu *emu)
2521 offset = fetch_word_imm(emu);
2522 store_data_byte(emu, offset, emu->x86.R_AL);
2527 * Handles opcode 0xa3
2530 x86emuOp_mov_M_AX_IMM(struct x86emu *emu)
2534 offset = fetch_word_imm(emu);
2535 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2536 store_data_long(emu, offset, emu->x86.R_EAX);
2538 store_data_word(emu, offset, emu->x86.R_AX);
2544 * Handles opcode 0xa4
2547 x86emuOp_movs_byte(struct x86emu *emu)
2553 if (ACCESS_FLAG(F_DF)) /* down */
2558 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2559 /* dont care whether REPE or REPNE */
2560 /* move them until CX is ZERO. */
2561 count = emu->x86.R_CX;
2563 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2566 val = fetch_data_byte(emu, emu->x86.R_SI);
2567 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, val);
2568 emu->x86.R_SI += inc;
2569 emu->x86.R_DI += inc;
2575 * Handles opcode 0xa5
2578 x86emuOp_movs_word(struct x86emu *emu)
2584 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2589 if (ACCESS_FLAG(F_DF)) /* down */
2593 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2594 /* dont care whether REPE or REPNE */
2595 /* move them until CX is ZERO. */
2596 count = emu->x86.R_CX;
2598 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2601 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2602 val = fetch_data_long(emu, emu->x86.R_SI);
2603 store_long(emu, emu->x86.R_ES, emu->x86.R_DI, val);
2605 val = fetch_data_word(emu, emu->x86.R_SI);
2606 store_word(emu, emu->x86.R_ES, emu->x86.R_DI, (uint16_t) val);
2608 emu->x86.R_SI += inc;
2609 emu->x86.R_DI += inc;
2615 * Handles opcode 0xa6
2618 x86emuOp_cmps_byte(struct x86emu *emu)
2623 if (ACCESS_FLAG(F_DF)) /* down */
2628 if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2630 /* move them until CX is ZERO. */
2631 while (emu->x86.R_CX != 0) {
2632 val1 = fetch_data_byte(emu, emu->x86.R_SI);
2633 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2634 cmp_byte(emu, val1, val2);
2636 emu->x86.R_SI += inc;
2637 emu->x86.R_DI += inc;
2638 if (ACCESS_FLAG(F_ZF) == 0)
2641 emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2642 } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2644 /* move them until CX is ZERO. */
2645 while (emu->x86.R_CX != 0) {
2646 val1 = fetch_data_byte(emu, emu->x86.R_SI);
2647 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2648 cmp_byte(emu, val1, val2);
2650 emu->x86.R_SI += inc;
2651 emu->x86.R_DI += inc;
2652 if (ACCESS_FLAG(F_ZF))
2653 break; /* zero flag set means equal */
2655 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2657 val1 = fetch_data_byte(emu, emu->x86.R_SI);
2658 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2659 cmp_byte(emu, val1, val2);
2660 emu->x86.R_SI += inc;
2661 emu->x86.R_DI += inc;
2667 * Handles opcode 0xa7
2670 x86emuOp_cmps_word(struct x86emu *emu)
2672 uint32_t val1, val2;
2675 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2676 if (ACCESS_FLAG(F_DF)) /* down */
2681 if (ACCESS_FLAG(F_DF)) /* down */
2686 if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2688 /* move them until CX is ZERO. */
2689 while (emu->x86.R_CX != 0) {
2690 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2691 val1 = fetch_data_long(emu, emu->x86.R_SI);
2692 val2 = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
2693 cmp_long(emu, val1, val2);
2695 val1 = fetch_data_word(emu, emu->x86.R_SI);
2696 val2 = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
2697 cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
2700 emu->x86.R_SI += inc;
2701 emu->x86.R_DI += inc;
2702 if (ACCESS_FLAG(F_ZF) == 0)
2705 emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2706 } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2708 /* move them until CX is ZERO. */
2709 while (emu->x86.R_CX != 0) {
2710 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2711 val1 = fetch_data_long(emu, emu->x86.R_SI);
2712 val2 = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
2713 cmp_long(emu, val1, val2);
2715 val1 = fetch_data_word(emu, emu->x86.R_SI);
2716 val2 = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
2717 cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
2720 emu->x86.R_SI += inc;
2721 emu->x86.R_DI += inc;
2722 if (ACCESS_FLAG(F_ZF))
2723 break; /* zero flag set means equal */
2725 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2727 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2728 val1 = fetch_data_long(emu, emu->x86.R_SI);
2729 val2 = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
2730 cmp_long(emu, val1, val2);
2732 val1 = fetch_data_word(emu, emu->x86.R_SI);
2733 val2 = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
2734 cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
2736 emu->x86.R_SI += inc;
2737 emu->x86.R_DI += inc;
2743 * Handles opcode 0xa9
2746 x86emuOp_test_AX_IMM(struct x86emu *emu)
2748 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2749 test_long(emu, emu->x86.R_EAX, fetch_long_imm(emu));
2751 test_word(emu, emu->x86.R_AX, fetch_word_imm(emu));
2757 * Handles opcode 0xaa
2760 x86emuOp_stos_byte(struct x86emu *emu)
2764 if (ACCESS_FLAG(F_DF)) /* down */
2768 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2769 /* dont care whether REPE or REPNE */
2770 /* move them until CX is ZERO. */
2771 while (emu->x86.R_CX != 0) {
2772 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_AL);
2774 emu->x86.R_DI += inc;
2776 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2778 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_AL);
2779 emu->x86.R_DI += inc;
2785 * Handles opcode 0xab
2788 x86emuOp_stos_word(struct x86emu *emu)
2793 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2798 if (ACCESS_FLAG(F_DF)) /* down */
2802 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2803 /* dont care whether REPE or REPNE */
2804 /* move them until CX is ZERO. */
2805 count = emu->x86.R_CX;
2807 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2810 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2811 store_long(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_EAX);
2813 store_word(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_AX);
2815 emu->x86.R_DI += inc;
2821 * Handles opcode 0xac
2824 x86emuOp_lods_byte(struct x86emu *emu)
2828 if (ACCESS_FLAG(F_DF)) /* down */
2832 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2833 /* dont care whether REPE or REPNE */
2834 /* move them until CX is ZERO. */
2835 while (emu->x86.R_CX != 0) {
2836 emu->x86.R_AL = fetch_data_byte(emu, emu->x86.R_SI);
2838 emu->x86.R_SI += inc;
2840 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2842 emu->x86.R_AL = fetch_data_byte(emu, emu->x86.R_SI);
2843 emu->x86.R_SI += inc;
2849 * Handles opcode 0xad
2852 x86emuOp_lods_word(struct x86emu *emu)
2857 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2862 if (ACCESS_FLAG(F_DF)) /* down */
2866 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2867 /* dont care whether REPE or REPNE */
2868 /* move them until CX is ZERO. */
2869 count = emu->x86.R_CX;
2871 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2874 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2875 emu->x86.R_EAX = fetch_data_long(emu, emu->x86.R_SI);
2877 emu->x86.R_AX = fetch_data_word(emu, emu->x86.R_SI);
2879 emu->x86.R_SI += inc;
2885 * Handles opcode 0xae
2888 x86emuOp_scas_byte(struct x86emu *emu)
2893 if (ACCESS_FLAG(F_DF)) /* down */
2897 if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2899 /* move them until CX is ZERO. */
2900 while (emu->x86.R_CX != 0) {
2901 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2902 cmp_byte(emu, emu->x86.R_AL, val2);
2904 emu->x86.R_DI += inc;
2905 if (ACCESS_FLAG(F_ZF) == 0)
2908 emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2909 } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2911 /* move them until CX is ZERO. */
2912 while (emu->x86.R_CX != 0) {
2913 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2914 cmp_byte(emu, emu->x86.R_AL, val2);
2916 emu->x86.R_DI += inc;
2917 if (ACCESS_FLAG(F_ZF))
2918 break; /* zero flag set means equal */
2920 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2922 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2923 cmp_byte(emu, emu->x86.R_AL, val2);
2924 emu->x86.R_DI += inc;
2930 * Handles opcode 0xaf
2933 x86emuOp_scas_word(struct x86emu *emu)
2938 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2943 if (ACCESS_FLAG(F_DF)) /* down */
2946 if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2948 /* move them until CX is ZERO. */
2949 while (emu->x86.R_CX != 0) {
2950 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2951 val = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
2952 cmp_long(emu, emu->x86.R_EAX, val);
2954 val = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
2955 cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
2958 emu->x86.R_DI += inc;
2959 if (ACCESS_FLAG(F_ZF) == 0)
2962 emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2963 } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2965 /* move them until CX is ZERO. */
2966 while (emu->x86.R_CX != 0) {
2967 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2968 val = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
2969 cmp_long(emu, emu->x86.R_EAX, val);
2971 val = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
2972 cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
2975 emu->x86.R_DI += inc;
2976 if (ACCESS_FLAG(F_ZF))
2977 break; /* zero flag set means equal */
2979 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2981 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2982 val = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
2983 cmp_long(emu, emu->x86.R_EAX, val);
2985 val = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
2986 cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
2988 emu->x86.R_DI += inc;
2994 * Handles opcode 0xb8
2997 x86emuOp_mov_word_AX_IMM(struct x86emu *emu)
2999 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3000 emu->x86.R_EAX = fetch_long_imm(emu);
3002 emu->x86.R_AX = fetch_word_imm(emu);
3007 * Handles opcode 0xb9
3010 x86emuOp_mov_word_CX_IMM(struct x86emu *emu)
3012 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3013 emu->x86.R_ECX = fetch_long_imm(emu);
3015 emu->x86.R_CX = fetch_word_imm(emu);
3020 * Handles opcode 0xba
3023 x86emuOp_mov_word_DX_IMM(struct x86emu *emu)
3025 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3026 emu->x86.R_EDX = fetch_long_imm(emu);
3028 emu->x86.R_DX = fetch_word_imm(emu);
3033 * Handles opcode 0xbb
3036 x86emuOp_mov_word_BX_IMM(struct x86emu *emu)
3038 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3039 emu->x86.R_EBX = fetch_long_imm(emu);
3041 emu->x86.R_BX = fetch_word_imm(emu);
3046 * Handles opcode 0xbc
3049 x86emuOp_mov_word_SP_IMM(struct x86emu *emu)
3051 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3052 emu->x86.R_ESP = fetch_long_imm(emu);
3054 emu->x86.R_SP = fetch_word_imm(emu);
3059 * Handles opcode 0xbd
3062 x86emuOp_mov_word_BP_IMM(struct x86emu *emu)
3064 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3065 emu->x86.R_EBP = fetch_long_imm(emu);
3067 emu->x86.R_BP = fetch_word_imm(emu);
3072 * Handles opcode 0xbe
3075 x86emuOp_mov_word_SI_IMM(struct x86emu *emu)
3077 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3078 emu->x86.R_ESI = fetch_long_imm(emu);
3080 emu->x86.R_SI = fetch_word_imm(emu);
3085 * Handles opcode 0xbf
3088 x86emuOp_mov_word_DI_IMM(struct x86emu *emu)
3090 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3091 emu->x86.R_EDI = fetch_long_imm(emu);
3093 emu->x86.R_DI = fetch_word_imm(emu);
3095 /* used by opcodes c0, d0, and d2. */
3097 uint8_t(* const opcD0_byte_operation[]) (struct x86emu *, uint8_t d, uint8_t s) =
3105 shl_byte, /* sal_byte === shl_byte by definition */
3111 * Handles opcode 0xc0
3114 x86emuOp_opcC0_byte_RM_MEM(struct x86emu *emu)
3116 uint8_t destval, amt;
3119 * Yet another weirdo special case instruction format. Part of
3120 * the opcode held below in "RH". Doubly nested case would
3121 * result, except that the decoded instruction
3123 fetch_decode_modrm(emu);
3124 /* know operation, decode the mod byte to find the addressing mode. */
3125 destval = decode_and_fetch_byte_imm8(emu, &amt);
3126 destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, amt);
3127 write_back_byte(emu, destval);
3129 /* used by opcodes c1, d1, and d3. */
3131 uint16_t(* const opcD1_word_operation[]) (struct x86emu *, uint16_t s, uint8_t d) =
3139 shl_word, /* sal_byte === shl_byte by definition */
3142 /* used by opcodes c1, d1, and d3. */
3144 uint32_t(* const opcD1_long_operation[]) (struct x86emu *, uint32_t s, uint8_t d) =
3152 shl_long, /* sal_byte === shl_byte by definition */
3158 * Handles opcode 0xc1
3161 x86emuOp_opcC1_word_RM_MEM(struct x86emu *emu)
3166 * Yet another weirdo special case instruction format. Part of
3167 * the opcode held below in "RH". Doubly nested case would
3168 * result, except that the decoded instruction
3170 fetch_decode_modrm(emu);
3171 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3174 destval = decode_and_fetch_long_imm8(emu, &amt);
3175 destval = (*opcD1_long_operation[emu->cur_rh]) (emu, destval, amt);
3176 write_back_long(emu, destval);
3180 destval = decode_and_fetch_word_imm8(emu, &amt);
3181 destval = (*opcD1_word_operation[emu->cur_rh]) (emu, destval, amt);
3182 write_back_word(emu, destval);
3188 * Handles opcode 0xc2
3191 x86emuOp_ret_near_IMM(struct x86emu *emu)
3195 imm = fetch_word_imm(emu);
3196 emu->x86.R_IP = pop_word(emu);
3197 emu->x86.R_SP += imm;
3202 * Handles opcode 0xc6
3205 x86emuOp_mov_byte_RM_IMM(struct x86emu *emu)
3208 uint32_t destoffset;
3211 fetch_decode_modrm(emu);
3212 if (emu->cur_rh != 0)
3213 x86emu_halt_sys(emu);
3214 if (emu->cur_mod != 3) {
3215 destoffset = decode_rl_address(emu);
3216 imm = fetch_byte_imm(emu);
3217 store_data_byte(emu, destoffset, imm);
3219 destreg = decode_rl_byte_register(emu);
3220 imm = fetch_byte_imm(emu);
3227 * Handles opcode 0xc7
3230 x86emuOp32_mov_word_RM_IMM(struct x86emu *emu)
3232 uint32_t destoffset;
3233 uint32_t imm, *destreg;
3235 fetch_decode_modrm(emu);
3236 if (emu->cur_rh != 0)
3237 x86emu_halt_sys(emu);
3239 if (emu->cur_mod != 3) {
3240 destoffset = decode_rl_address(emu);
3241 imm = fetch_long_imm(emu);
3242 store_data_long(emu, destoffset, imm);
3244 destreg = decode_rl_long_register(emu);
3245 imm = fetch_long_imm(emu);
3251 x86emuOp16_mov_word_RM_IMM(struct x86emu *emu)
3253 uint32_t destoffset;
3254 uint16_t imm, *destreg;
3256 fetch_decode_modrm(emu);
3257 if (emu->cur_rh != 0)
3258 x86emu_halt_sys(emu);
3260 if (emu->cur_mod != 3) {
3261 destoffset = decode_rl_address(emu);
3262 imm = fetch_word_imm(emu);
3263 store_data_word(emu, destoffset, imm);
3265 destreg = decode_rl_word_register(emu);
3266 imm = fetch_word_imm(emu);
3272 x86emuOp_mov_word_RM_IMM(struct x86emu *emu)
3274 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3275 x86emuOp32_mov_word_RM_IMM(emu);
3277 x86emuOp16_mov_word_RM_IMM(emu);
3282 * Handles opcode 0xc8
3285 x86emuOp_enter(struct x86emu *emu)
3287 uint16_t local, frame_pointer;
3291 local = fetch_word_imm(emu);
3292 nesting = fetch_byte_imm(emu);
3293 push_word(emu, emu->x86.R_BP);
3294 frame_pointer = emu->x86.R_SP;
3296 for (i = 1; i < nesting; i++) {
3298 push_word(emu, fetch_word(emu, emu->x86.R_SS, emu->x86.R_BP));
3300 push_word(emu, frame_pointer);
3302 emu->x86.R_BP = frame_pointer;
3303 emu->x86.R_SP = (uint16_t) (emu->x86.R_SP - local);
3308 * Handles opcode 0xc9
3311 x86emuOp_leave(struct x86emu *emu)
3313 emu->x86.R_SP = emu->x86.R_BP;
3314 emu->x86.R_BP = pop_word(emu);
3319 * Handles opcode 0xca
3322 x86emuOp_ret_far_IMM(struct x86emu *emu)
3326 imm = fetch_word_imm(emu);
3327 emu->x86.R_IP = pop_word(emu);
3328 emu->x86.R_CS = pop_word(emu);
3329 emu->x86.R_SP += imm;
3334 * Handles opcode 0xcb
3337 x86emuOp_ret_far(struct x86emu *emu)
3339 emu->x86.R_IP = pop_word(emu);
3340 emu->x86.R_CS = pop_word(emu);
3345 * Handles opcode 0xcc
3348 x86emuOp_int3(struct x86emu *emu)
3350 x86emu_intr_dispatch(emu, 3);
3355 * Handles opcode 0xcd
3358 x86emuOp_int_IMM(struct x86emu *emu)
3362 intnum = fetch_byte_imm(emu);
3363 x86emu_intr_dispatch(emu, intnum);
3368 * Handles opcode 0xce
3371 x86emuOp_into(struct x86emu *emu)
3373 if (ACCESS_FLAG(F_OF))
3374 x86emu_intr_dispatch(emu, 4);
3379 * Handles opcode 0xcf
3382 x86emuOp_iret(struct x86emu *emu)
3384 emu->x86.R_IP = pop_word(emu);
3385 emu->x86.R_CS = pop_word(emu);
3386 emu->x86.R_FLG = pop_word(emu);
3391 * Handles opcode 0xd0
3394 x86emuOp_opcD0_byte_RM_1(struct x86emu *emu)
3398 fetch_decode_modrm(emu);
3399 destval = decode_and_fetch_byte(emu);
3400 destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, 1);
3401 write_back_byte(emu, destval);
3406 * Handles opcode 0xd1
3409 x86emuOp_opcD1_word_RM_1(struct x86emu *emu)
3411 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3414 fetch_decode_modrm(emu);
3415 destval = decode_and_fetch_long(emu);
3416 destval = (*opcD1_long_operation[emu->cur_rh]) (emu, destval, 1);
3417 write_back_long(emu, destval);
3421 fetch_decode_modrm(emu);
3422 destval = decode_and_fetch_word(emu);
3423 destval = (*opcD1_word_operation[emu->cur_rh]) (emu, destval, 1);
3424 write_back_word(emu, destval);
3430 * Handles opcode 0xd2
3433 x86emuOp_opcD2_byte_RM_CL(struct x86emu *emu)
3437 fetch_decode_modrm(emu);
3438 destval = decode_and_fetch_byte(emu);
3439 destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, emu->x86.R_CL);
3440 write_back_byte(emu, destval);
3445 * Handles opcode 0xd3
3448 x86emuOp_opcD3_word_RM_CL(struct x86emu *emu)
3450 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3453 fetch_decode_modrm(emu);
3454 destval = decode_and_fetch_long(emu);
3455 destval = (*opcD1_long_operation[emu->cur_rh]) (emu, destval, emu->x86.R_CL);
3456 write_back_long(emu, destval);
3460 fetch_decode_modrm(emu);
3461 destval = decode_and_fetch_word(emu);
3462 destval = (*opcD1_word_operation[emu->cur_rh]) (emu, destval, emu->x86.R_CL);
3463 write_back_word(emu, destval);
3469 * Handles opcode 0xd4
3472 x86emuOp_aam(struct x86emu *emu)
3476 a = fetch_byte_imm(emu); /* this is a stupid encoding. */
3478 /* fix: add base decoding aam_word(uint8_t val, int base a) */
3479 x86emu_halt_sys(emu);
3481 /* note the type change here --- returning AL and AH in AX. */
3482 emu->x86.R_AX = aam_word(emu, emu->x86.R_AL);
3487 * Handles opcode 0xd5
3490 x86emuOp_aad(struct x86emu *emu)
3494 a = fetch_byte_imm(emu);
3496 /* fix: add base decoding aad_word(uint16_t val, int base a) */
3497 x86emu_halt_sys(emu);
3499 emu->x86.R_AX = aad_word(emu, emu->x86.R_AX);
3501 /* opcode 0xd6 ILLEGAL OPCODE */
3506 * Handles opcode 0xd7
3509 x86emuOp_xlat(struct x86emu *emu)
3513 addr = (uint16_t) (emu->x86.R_BX + (uint8_t) emu->x86.R_AL);
3514 emu->x86.R_AL = fetch_data_byte(emu, addr);
3519 x86emuOp_esc_coprocess_d8(struct x86emu *emu)
3524 x86emuOp_esc_coprocess_d9(struct x86emu *emu)
3526 fetch_decode_modrm(emu);
3527 if (emu->cur_mod != 3)
3528 decode_rl_address(emu);
3532 x86emuOp_esc_coprocess_da(struct x86emu *emu)
3534 fetch_decode_modrm(emu);
3535 if (emu->cur_mod != 3)
3536 decode_rl_address(emu);
3540 x86emuOp_esc_coprocess_db(struct x86emu *emu)
3542 fetch_decode_modrm(emu);
3543 if (emu->cur_mod != 3)
3544 decode_rl_address(emu);
3548 x86emuOp_esc_coprocess_dc(struct x86emu *emu)
3550 fetch_decode_modrm(emu);
3551 if (emu->cur_mod != 3)
3552 decode_rl_address(emu);
3556 x86emuOp_esc_coprocess_dd(struct x86emu *emu)
3558 fetch_decode_modrm(emu);
3559 if (emu->cur_mod != 3)
3560 decode_rl_address(emu);
3564 x86emuOp_esc_coprocess_de(struct x86emu *emu)
3566 fetch_decode_modrm(emu);
3567 if (emu->cur_mod != 3)
3568 decode_rl_address(emu);
3572 x86emuOp_esc_coprocess_df(struct x86emu *emu)
3574 fetch_decode_modrm(emu);
3575 if (emu->cur_mod != 3)
3576 decode_rl_address(emu);
3582 * Handles opcode 0xe0
3585 x86emuOp_loopne(struct x86emu *emu)
3589 ip = (int8_t) fetch_byte_imm(emu);
3590 ip += (int16_t) emu->x86.R_IP;
3592 if (emu->x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */
3598 * Handles opcode 0xe1
3601 x86emuOp_loope(struct x86emu *emu)
3605 ip = (int8_t) fetch_byte_imm(emu);
3606 ip += (int16_t) emu->x86.R_IP;
3608 if (emu->x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */
3614 * Handles opcode 0xe2
3617 x86emuOp_loop(struct x86emu *emu)
3621 ip = (int8_t) fetch_byte_imm(emu);
3622 ip += (int16_t) emu->x86.R_IP;
3624 if (emu->x86.R_CX != 0)
3630 * Handles opcode 0xe3
3633 x86emuOp_jcxz(struct x86emu *emu)
3638 /* jump to byte offset if overflow flag is set */
3639 offset = (int8_t) fetch_byte_imm(emu);
3640 target = (uint16_t) (emu->x86.R_IP + offset);
3641 if (emu->x86.R_CX == 0)
3642 emu->x86.R_IP = target;
3647 * Handles opcode 0xe4
3650 x86emuOp_in_byte_AL_IMM(struct x86emu *emu)
3654 port = (uint8_t) fetch_byte_imm(emu);
3655 emu->x86.R_AL = (*emu->emu_inb) (emu, port);
3660 * Handles opcode 0xe5
3663 x86emuOp_in_word_AX_IMM(struct x86emu *emu)
3667 port = (uint8_t) fetch_byte_imm(emu);
3668 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3669 emu->x86.R_EAX = (*emu->emu_inl) (emu, port);
3671 emu->x86.R_AX = (*emu->emu_inw) (emu, port);
3677 * Handles opcode 0xe6
3680 x86emuOp_out_byte_IMM_AL(struct x86emu *emu)
3684 port = (uint8_t) fetch_byte_imm(emu);
3685 (*emu->emu_outb) (emu, port, emu->x86.R_AL);
3690 * Handles opcode 0xe7
3693 x86emuOp_out_word_IMM_AX(struct x86emu *emu)
3697 port = (uint8_t) fetch_byte_imm(emu);
3698 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3699 (*emu->emu_outl) (emu, port, emu->x86.R_EAX);
3701 (*emu->emu_outw) (emu, port, emu->x86.R_AX);
3707 * Handles opcode 0xe8
3710 x86emuOp_call_near_IMM(struct x86emu *emu)
3714 ip = (int16_t) fetch_word_imm(emu);
3715 ip += (int16_t) emu->x86.R_IP; /* CHECK SIGN */
3716 push_word(emu, emu->x86.R_IP);
3722 * Handles opcode 0xe9
3725 x86emuOp_jump_near_IMM(struct x86emu *emu)
3729 ip = (int16_t) fetch_word_imm(emu);
3730 ip += (int16_t) emu->x86.R_IP;
3731 emu->x86.R_IP = (uint16_t) ip;
3736 * Handles opcode 0xea
3739 x86emuOp_jump_far_IMM(struct x86emu *emu)
3743 ip = fetch_word_imm(emu);
3744 cs = fetch_word_imm(emu);
3751 * Handles opcode 0xeb
3754 x86emuOp_jump_byte_IMM(struct x86emu *emu)
3759 offset = (int8_t) fetch_byte_imm(emu);
3760 target = (uint16_t) (emu->x86.R_IP + offset);
3761 emu->x86.R_IP = target;
3766 * Handles opcode 0xec
3769 x86emuOp_in_byte_AL_DX(struct x86emu *emu)
3771 emu->x86.R_AL = (*emu->emu_inb) (emu, emu->x86.R_DX);
3776 * Handles opcode 0xed
3779 x86emuOp_in_word_AX_DX(struct x86emu *emu)
3781 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3782 emu->x86.R_EAX = (*emu->emu_inl) (emu, emu->x86.R_DX);
3784 emu->x86.R_AX = (*emu->emu_inw) (emu, emu->x86.R_DX);
3790 * Handles opcode 0xee
3793 x86emuOp_out_byte_DX_AL(struct x86emu *emu)
3795 (*emu->emu_outb) (emu, emu->x86.R_DX, emu->x86.R_AL);
3800 * Handles opcode 0xef
3803 x86emuOp_out_word_DX_AX(struct x86emu *emu)
3805 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3806 (*emu->emu_outl) (emu, emu->x86.R_DX, emu->x86.R_EAX);
3808 (*emu->emu_outw) (emu, emu->x86.R_DX, emu->x86.R_AX);
3814 * Handles opcode 0xf0
3817 x86emuOp_lock(struct x86emu *emu)
3820 /*opcode 0xf1 ILLEGAL OPERATION */
3825 * Handles opcode 0xf5
3828 x86emuOp_cmc(struct x86emu *emu)
3830 if (ACCESS_FLAG(F_CF))
3838 * Handles opcode 0xf6
3841 x86emuOp_opcF6_byte_RM(struct x86emu *emu)
3843 uint8_t destval, srcval;
3845 /* long, drawn out code follows. Double switch for a total of 32
3847 fetch_decode_modrm(emu);
3848 if (emu->cur_rh == 1)
3849 x86emu_halt_sys(emu);
3851 if (emu->cur_rh == 0) {
3852 destval = decode_and_fetch_byte_imm8(emu, &srcval);
3853 test_byte(emu, destval, srcval);
3856 destval = decode_and_fetch_byte(emu);
3857 switch (emu->cur_rh) {
3860 write_back_byte(emu, destval);
3863 destval = neg_byte(emu, destval);
3864 write_back_byte(emu, destval);
3867 mul_byte(emu, destval);
3870 imul_byte(emu, destval);
3873 div_byte(emu, destval);
3876 idiv_byte(emu, destval);
3883 * Handles opcode 0xf7
3886 x86emuOp32_opcF7_word_RM(struct x86emu *emu)
3888 uint32_t destval, srcval;
3890 /* long, drawn out code follows. Double switch for a total of 32
3892 fetch_decode_modrm(emu);
3893 if (emu->cur_rh == 1)
3894 x86emu_halt_sys(emu);
3896 if (emu->cur_rh == 0) {
3897 if (emu->cur_mod != 3) {
3898 uint32_t destoffset;
3900 destoffset = decode_rl_address(emu);
3901 srcval = fetch_long_imm(emu);
3902 destval = fetch_data_long(emu, destoffset);
3904 srcval = fetch_long_imm(emu);
3905 destval = *decode_rl_long_register(emu);
3907 test_long(emu, destval, srcval);
3910 destval = decode_and_fetch_long(emu);
3911 switch (emu->cur_rh) {
3914 write_back_long(emu, destval);
3917 destval = neg_long(emu, destval);
3918 write_back_long(emu, destval);
3921 mul_long(emu, destval);
3924 imul_long(emu, destval);
3927 div_long(emu, destval);
3930 idiv_long(emu, destval);
3935 x86emuOp16_opcF7_word_RM(struct x86emu *emu)
3937 uint16_t destval, srcval;
3939 /* long, drawn out code follows. Double switch for a total of 32
3941 fetch_decode_modrm(emu);
3942 if (emu->cur_rh == 1)
3943 x86emu_halt_sys(emu);
3945 if (emu->cur_rh == 0) {
3946 if (emu->cur_mod != 3) {
3947 uint32_t destoffset;
3949 destoffset = decode_rl_address(emu);
3950 srcval = fetch_word_imm(emu);
3951 destval = fetch_data_word(emu, destoffset);
3953 srcval = fetch_word_imm(emu);
3954 destval = *decode_rl_word_register(emu);
3956 test_word(emu, destval, srcval);
3959 destval = decode_and_fetch_word(emu);
3960 switch (emu->cur_rh) {
3963 write_back_word(emu, destval);
3966 destval = neg_word(emu, destval);
3967 write_back_word(emu, destval);
3970 mul_word(emu, destval);
3973 imul_word(emu, destval);
3976 div_word(emu, destval);
3979 idiv_word(emu, destval);
3984 x86emuOp_opcF7_word_RM(struct x86emu *emu)
3986 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3987 x86emuOp32_opcF7_word_RM(emu);
3989 x86emuOp16_opcF7_word_RM(emu);
3994 * Handles opcode 0xfe
3997 x86emuOp_opcFE_byte_RM(struct x86emu *emu)
4000 uint32_t destoffset;
4003 /* Yet another special case instruction. */
4004 fetch_decode_modrm(emu);
4005 if (emu->cur_mod != 3) {
4006 destoffset = decode_rl_address(emu);
4007 switch (emu->cur_rh) {
4008 case 0: /* inc word ptr ... */
4009 destval = fetch_data_byte(emu, destoffset);
4010 destval = inc_byte(emu, destval);
4011 store_data_byte(emu, destoffset, destval);
4013 case 1: /* dec word ptr ... */
4014 destval = fetch_data_byte(emu, destoffset);
4015 destval = dec_byte(emu, destval);
4016 store_data_byte(emu, destoffset, destval);
4020 destreg = decode_rl_byte_register(emu);
4021 switch (emu->cur_rh) {
4023 *destreg = inc_byte(emu, *destreg);
4026 *destreg = dec_byte(emu, *destreg);
4034 * Handles opcode 0xff
4037 x86emuOp32_opcFF_word_RM(struct x86emu *emu)
4039 uint32_t destoffset = 0;
4040 uint32_t destval, *destreg;
4042 if (emu->cur_mod != 3) {
4043 destoffset = decode_rl_address(emu);
4044 destval = fetch_data_long(emu, destoffset);
4045 switch (emu->cur_rh) {
4046 case 0: /* inc word ptr ... */
4047 destval = inc_long(emu, destval);
4048 store_data_long(emu, destoffset, destval);
4050 case 1: /* dec word ptr ... */
4051 destval = dec_long(emu, destval);
4052 store_data_long(emu, destoffset, destval);
4054 case 6: /* push word ptr ... */
4055 push_long(emu, destval);
4059 destreg = decode_rl_long_register(emu);
4060 switch (emu->cur_rh) {
4062 *destreg = inc_long(emu, *destreg);
4065 *destreg = dec_long(emu, *destreg);
4068 push_long(emu, *destreg);
4075 x86emuOp16_opcFF_word_RM(struct x86emu *emu)
4077 uint32_t destoffset = 0;
4081 if (emu->cur_mod != 3) {
4082 destoffset = decode_rl_address(emu);
4083 destval = fetch_data_word(emu, destoffset);
4084 switch (emu->cur_rh) {
4086 destval = inc_word(emu, destval);
4087 store_data_word(emu, destoffset, destval);
4089 case 1: /* dec word ptr ... */
4090 destval = dec_word(emu, destval);
4091 store_data_word(emu, destoffset, destval);
4093 case 6: /* push word ptr ... */
4094 push_word(emu, destval);
4098 destreg = decode_rl_word_register(emu);
4099 switch (emu->cur_rh) {
4101 *destreg = inc_word(emu, *destreg);
4104 *destreg = dec_word(emu, *destreg);
4107 push_word(emu, *destreg);
4114 x86emuOp_opcFF_word_RM(struct x86emu *emu)
4116 uint32_t destoffset = 0;
4117 uint16_t destval, destval2;
4119 /* Yet another special case instruction. */
4120 fetch_decode_modrm(emu);
4121 if ((emu->cur_mod == 3 && (emu->cur_rh == 3 || emu->cur_rh == 5)) || emu->cur_rh == 7)
4122 x86emu_halt_sys(emu);
4123 if (emu->cur_rh == 0 || emu->cur_rh == 1 || emu->cur_rh == 6) {
4124 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
4125 x86emuOp32_opcFF_word_RM(emu);
4127 x86emuOp16_opcFF_word_RM(emu);
4131 if (emu->cur_mod != 3) {
4132 destoffset = decode_rl_address(emu);
4133 destval = fetch_data_word(emu, destoffset);
4134 switch (emu->cur_rh) {
4135 case 3: /* call far ptr ... */
4136 destval2 = fetch_data_word(emu, destoffset + 2);
4137 push_word(emu, emu->x86.R_CS);
4138 emu->x86.R_CS = destval2;
4139 push_word(emu, emu->x86.R_IP);
4140 emu->x86.R_IP = destval;
4142 case 5: /* jmp far ptr ... */
4143 destval2 = fetch_data_word(emu, destoffset + 2);
4144 emu->x86.R_IP = destval;
4145 emu->x86.R_CS = destval2;
4149 destval = *decode_rl_word_register(emu);
4152 switch (emu->cur_rh) {
4153 case 2: /* call word ptr */
4154 push_word(emu, emu->x86.R_IP);
4155 emu->x86.R_IP = destval;
4158 emu->x86.R_IP = destval;
4164 * * Single byte operation code table:
4167 x86emu_exec_one_byte(struct x86emu * emu)
4171 op1 = fetch_byte_imm(emu);
4175 common_binop_byte_rm_r(emu, add_byte);
4178 common_binop_word_long_rm_r(emu, add_word, add_long);
4181 common_binop_byte_r_rm(emu, add_byte);
4184 common_binop_word_long_r_rm(emu, add_word, add_long);
4187 common_binop_byte_imm(emu, add_byte);
4190 common_binop_word_long_imm(emu, add_word, add_long);
4193 push_word(emu, emu->x86.R_ES);
4196 emu->x86.R_ES = pop_word(emu);
4200 common_binop_byte_rm_r(emu, or_byte);
4203 common_binop_word_long_rm_r(emu, or_word, or_long);
4206 common_binop_byte_r_rm(emu, or_byte);
4209 common_binop_word_long_r_rm(emu, or_word, or_long);
4212 common_binop_byte_imm(emu, or_byte);
4215 common_binop_word_long_imm(emu, or_word, or_long);
4218 push_word(emu, emu->x86.R_CS);
4221 x86emu_exec_two_byte(emu);
4225 common_binop_byte_rm_r(emu, adc_byte);
4228 common_binop_word_long_rm_r(emu, adc_word, adc_long);
4231 common_binop_byte_r_rm(emu, adc_byte);
4234 common_binop_word_long_r_rm(emu, adc_word, adc_long);
4237 common_binop_byte_imm(emu, adc_byte);
4240 common_binop_word_long_imm(emu, adc_word, adc_long);
4243 push_word(emu, emu->x86.R_SS);
4246 emu->x86.R_SS = pop_word(emu);
4250 common_binop_byte_rm_r(emu, sbb_byte);
4253 common_binop_word_long_rm_r(emu, sbb_word, sbb_long);
4256 common_binop_byte_r_rm(emu, sbb_byte);
4259 common_binop_word_long_r_rm(emu, sbb_word, sbb_long);
4262 common_binop_byte_imm(emu, sbb_byte);
4265 common_binop_word_long_imm(emu, sbb_word, sbb_long);
4268 push_word(emu, emu->x86.R_DS);
4271 emu->x86.R_DS = pop_word(emu);
4275 common_binop_byte_rm_r(emu, and_byte);
4278 common_binop_word_long_rm_r(emu, and_word, and_long);
4281 common_binop_byte_r_rm(emu, and_byte);
4284 common_binop_word_long_r_rm(emu, and_word, and_long);
4287 common_binop_byte_imm(emu, and_byte);
4290 common_binop_word_long_imm(emu, and_word, and_long);
4293 emu->x86.mode |= SYSMODE_SEGOVR_ES;
4296 emu->x86.R_AL = daa_byte(emu, emu->x86.R_AL);
4300 common_binop_byte_rm_r(emu, sub_byte);
4303 common_binop_word_long_rm_r(emu, sub_word, sub_long);
4306 common_binop_byte_r_rm(emu, sub_byte);
4309 common_binop_word_long_r_rm(emu, sub_word, sub_long);
4312 common_binop_byte_imm(emu, sub_byte);
4315 common_binop_word_long_imm(emu, sub_word, sub_long);
4318 emu->x86.mode |= SYSMODE_SEGOVR_CS;
4321 emu->x86.R_AL = das_byte(emu, emu->x86.R_AL);
4325 common_binop_byte_rm_r(emu, xor_byte);
4328 common_binop_word_long_rm_r(emu, xor_word, xor_long);
4331 common_binop_byte_r_rm(emu, xor_byte);
4334 common_binop_word_long_r_rm(emu, xor_word, xor_long);
4337 common_binop_byte_imm(emu, xor_byte);
4340 common_binop_word_long_imm(emu, xor_word, xor_long);
4343 emu->x86.mode |= SYSMODE_SEGOVR_SS;
4346 emu->x86.R_AX = aaa_word(emu, emu->x86.R_AX);
4350 common_binop_ns_byte_rm_r(emu, cmp_byte_no_return);
4353 common_binop_ns_word_long_rm_r(emu, cmp_word_no_return,
4354 cmp_long_no_return);
4357 x86emuOp_cmp_byte_R_RM(emu);
4360 x86emuOp_cmp_word_R_RM(emu);
4363 x86emuOp_cmp_byte_AL_IMM(emu);
4366 x86emuOp_cmp_word_AX_IMM(emu);
4369 emu->x86.mode |= SYSMODE_SEGOVR_DS;
4372 emu->x86.R_AX = aas_word(emu, emu->x86.R_AX);
4376 common_inc_word_long(emu, &emu->x86.register_a);
4379 common_inc_word_long(emu, &emu->x86.register_c);
4382 common_inc_word_long(emu, &emu->x86.register_d);
4385 common_inc_word_long(emu, &emu->x86.register_b);
4388 common_inc_word_long(emu, &emu->x86.register_sp);
4391 common_inc_word_long(emu, &emu->x86.register_bp);
4394 common_inc_word_long(emu, &emu->x86.register_si);
4397 common_inc_word_long(emu, &emu->x86.register_di);
4401 common_dec_word_long(emu, &emu->x86.register_a);
4404 common_dec_word_long(emu, &emu->x86.register_c);
4407 common_dec_word_long(emu, &emu->x86.register_d);
4410 common_dec_word_long(emu, &emu->x86.register_b);
4413 common_dec_word_long(emu, &emu->x86.register_sp);
4416 common_dec_word_long(emu, &emu->x86.register_bp);
4419 common_dec_word_long(emu, &emu->x86.register_si);
4422 common_dec_word_long(emu, &emu->x86.register_di);
4426 common_push_word_long(emu, &emu->x86.register_a);
4429 common_push_word_long(emu, &emu->x86.register_c);
4432 common_push_word_long(emu, &emu->x86.register_d);
4435 common_push_word_long(emu, &emu->x86.register_b);
4438 common_push_word_long(emu, &emu->x86.register_sp);
4441 common_push_word_long(emu, &emu->x86.register_bp);
4444 common_push_word_long(emu, &emu->x86.register_si);
4447 common_push_word_long(emu, &emu->x86.register_di);
4451 common_pop_word_long(emu, &emu->x86.register_a);
4454 common_pop_word_long(emu, &emu->x86.register_c);
4457 common_pop_word_long(emu, &emu->x86.register_d);
4460 common_pop_word_long(emu, &emu->x86.register_b);
4463 common_pop_word_long(emu, &emu->x86.register_sp);
4466 common_pop_word_long(emu, &emu->x86.register_bp);
4469 common_pop_word_long(emu, &emu->x86.register_si);
4472 common_pop_word_long(emu, &emu->x86.register_di);
4476 x86emuOp_push_all(emu);
4479 x86emuOp_pop_all(emu);
4484 emu->x86.mode |= SYSMODE_SEGOVR_FS;
4487 emu->x86.mode |= SYSMODE_SEGOVR_GS;
4490 emu->x86.mode |= SYSMODE_PREFIX_DATA;
4493 emu->x86.mode |= SYSMODE_PREFIX_ADDR;
4497 x86emuOp_push_word_IMM(emu);
4500 common_imul_imm(emu, 0);
4503 x86emuOp_push_byte_IMM(emu);
4506 common_imul_imm(emu, 1);
4512 x86emuOp_ins_word(emu);
4518 x86emuOp_outs_word(emu);
4522 common_jmp_near(emu, ACCESS_FLAG(F_OF));
4525 common_jmp_near(emu, !ACCESS_FLAG(F_OF));
4528 common_jmp_near(emu, ACCESS_FLAG(F_CF));
4531 common_jmp_near(emu, !ACCESS_FLAG(F_CF));
4534 common_jmp_near(emu, ACCESS_FLAG(F_ZF));
4537 common_jmp_near(emu, !ACCESS_FLAG(F_ZF));
4540 common_jmp_near(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
4543 common_jmp_near(emu, !ACCESS_FLAG(F_CF) && !ACCESS_FLAG(F_ZF));
4547 common_jmp_near(emu, ACCESS_FLAG(F_SF));
4550 common_jmp_near(emu, !ACCESS_FLAG(F_SF));
4553 common_jmp_near(emu, ACCESS_FLAG(F_PF));
4556 common_jmp_near(emu, !ACCESS_FLAG(F_PF));
4559 x86emuOp_jump_near_L(emu);
4562 x86emuOp_jump_near_NL(emu);
4565 x86emuOp_jump_near_LE(emu);
4568 x86emuOp_jump_near_NLE(emu);
4572 x86emuOp_opc80_byte_RM_IMM(emu);
4575 x86emuOp_opc81_word_RM_IMM(emu);
4578 x86emuOp_opc82_byte_RM_IMM(emu);
4581 x86emuOp_opc83_word_RM_IMM(emu);
4584 common_binop_ns_byte_rm_r(emu, test_byte);
4587 common_binop_ns_word_long_rm_r(emu, test_word, test_long);
4590 x86emuOp_xchg_byte_RM_R(emu);
4593 x86emuOp_xchg_word_RM_R(emu);
4597 x86emuOp_mov_byte_RM_R(emu);
4600 x86emuOp_mov_word_RM_R(emu);
4603 x86emuOp_mov_byte_R_RM(emu);
4606 x86emuOp_mov_word_R_RM(emu);
4609 x86emuOp_mov_word_RM_SR(emu);
4612 x86emuOp_lea_word_R_M(emu);
4615 x86emuOp_mov_word_SR_RM(emu);
4618 x86emuOp_pop_RM(emu);
4625 x86emuOp_xchg_word_AX_CX(emu);
4628 x86emuOp_xchg_word_AX_DX(emu);
4631 x86emuOp_xchg_word_AX_BX(emu);
4634 x86emuOp_xchg_word_AX_SP(emu);
4637 x86emuOp_xchg_word_AX_BP(emu);
4640 x86emuOp_xchg_word_AX_SI(emu);
4643 x86emuOp_xchg_word_AX_DI(emu);
4653 x86emuOp_call_far_IMM(emu);
4659 x86emuOp_pushf_word(emu);
4662 x86emuOp_popf_word(emu);
4672 x86emuOp_mov_AL_M_IMM(emu);
4675 x86emuOp_mov_AX_M_IMM(emu);
4678 x86emuOp_mov_M_AL_IMM(emu);
4681 x86emuOp_mov_M_AX_IMM(emu);
4684 x86emuOp_movs_byte(emu);
4687 x86emuOp_movs_word(emu);
4690 x86emuOp_cmps_byte(emu);
4693 x86emuOp_cmps_word(emu);
4697 test_byte(emu, emu->x86.R_AL, fetch_byte_imm(emu));
4700 x86emuOp_test_AX_IMM(emu);
4703 x86emuOp_stos_byte(emu);
4706 x86emuOp_stos_word(emu);
4709 x86emuOp_lods_byte(emu);
4712 x86emuOp_lods_word(emu);
4715 x86emuOp_scas_byte(emu);
4718 x86emuOp_scas_word(emu);
4722 emu->x86.R_AL = fetch_byte_imm(emu);
4725 emu->x86.R_CL = fetch_byte_imm(emu);
4728 emu->x86.R_DL = fetch_byte_imm(emu);
4731 emu->x86.R_BL = fetch_byte_imm(emu);
4734 emu->x86.R_AH = fetch_byte_imm(emu);
4737 emu->x86.R_CH = fetch_byte_imm(emu);
4740 emu->x86.R_DH = fetch_byte_imm(emu);
4743 emu->x86.R_BH = fetch_byte_imm(emu);
4747 x86emuOp_mov_word_AX_IMM(emu);
4750 x86emuOp_mov_word_CX_IMM(emu);
4753 x86emuOp_mov_word_DX_IMM(emu);
4756 x86emuOp_mov_word_BX_IMM(emu);
4760 x86emuOp_mov_word_SP_IMM(emu);
4763 x86emuOp_mov_word_BP_IMM(emu);
4766 x86emuOp_mov_word_SI_IMM(emu);
4769 x86emuOp_mov_word_DI_IMM(emu);
4773 x86emuOp_opcC0_byte_RM_MEM(emu);
4776 x86emuOp_opcC1_word_RM_MEM(emu);
4779 x86emuOp_ret_near_IMM(emu);
4782 emu->x86.R_IP = pop_word(emu);
4785 common_load_far_pointer(emu, &emu->x86.R_ES);
4788 common_load_far_pointer(emu, &emu->x86.R_DS);
4791 x86emuOp_mov_byte_RM_IMM(emu);
4794 x86emuOp_mov_word_RM_IMM(emu);
4797 x86emuOp_enter(emu);
4800 x86emuOp_leave(emu);
4803 x86emuOp_ret_far_IMM(emu);
4806 x86emuOp_ret_far(emu);
4812 x86emuOp_int_IMM(emu);
4822 x86emuOp_opcD0_byte_RM_1(emu);
4825 x86emuOp_opcD1_word_RM_1(emu);
4828 x86emuOp_opcD2_byte_RM_CL(emu);
4831 x86emuOp_opcD3_word_RM_CL(emu);
4839 /* 0xd6 Undocumented SETALC instruction */
4844 x86emuOp_esc_coprocess_d8(emu);
4847 x86emuOp_esc_coprocess_d9(emu);
4850 x86emuOp_esc_coprocess_da(emu);
4853 x86emuOp_esc_coprocess_db(emu);
4856 x86emuOp_esc_coprocess_dc(emu);
4859 x86emuOp_esc_coprocess_dd(emu);
4862 x86emuOp_esc_coprocess_de(emu);
4865 x86emuOp_esc_coprocess_df(emu);
4869 x86emuOp_loopne(emu);
4872 x86emuOp_loope(emu);
4881 x86emuOp_in_byte_AL_IMM(emu);
4884 x86emuOp_in_word_AX_IMM(emu);
4887 x86emuOp_out_byte_IMM_AL(emu);
4890 x86emuOp_out_word_IMM_AX(emu);
4894 x86emuOp_call_near_IMM(emu);
4897 x86emuOp_jump_near_IMM(emu);
4900 x86emuOp_jump_far_IMM(emu);
4903 x86emuOp_jump_byte_IMM(emu);
4906 x86emuOp_in_byte_AL_DX(emu);
4909 x86emuOp_in_word_AX_DX(emu);
4912 x86emuOp_out_byte_DX_AL(emu);
4915 x86emuOp_out_word_DX_AX(emu);
4922 emu->x86.mode |= SYSMODE_PREFIX_REPNE;
4925 emu->x86.mode |= SYSMODE_PREFIX_REPE;
4928 x86emu_halt_sys(emu);
4934 x86emuOp_opcF6_byte_RM(emu);
4937 x86emuOp_opcF7_word_RM(emu);
4959 x86emuOp_opcFE_byte_RM(emu);
4962 x86emuOp_opcFF_word_RM(emu);
4965 x86emu_halt_sys(emu);
4968 if (op1 != 0x26 && op1 != 0x2e && op1 != 0x36 && op1 != 0x3e &&
4970 emu->x86.mode &= ~SYSMODE_CLRMASK;
4974 common_jmp_long(struct x86emu *emu, int cond)
4978 target = (int16_t) fetch_word_imm(emu);
4979 target += (int16_t) emu->x86.R_IP;
4981 emu->x86.R_IP = (uint16_t) target;
4985 common_set_byte(struct x86emu *emu, int cond)
4987 uint32_t destoffset;
4988 uint8_t *destreg, destval;
4990 fetch_decode_modrm(emu);
4991 destval = cond ? 0x01 : 0x00;
4992 if (emu->cur_mod != 3) {
4993 destoffset = decode_rl_address(emu);
4994 store_data_byte(emu, destoffset, destval);
4996 destreg = decode_rl_byte_register(emu);
5002 common_bitstring32(struct x86emu *emu, int op)
5005 uint32_t srcval, *shiftreg, mask;
5007 fetch_decode_modrm(emu);
5008 shiftreg = decode_rh_long_register(emu);
5009 srcval = decode_and_fetch_long_disp(emu, (int16_t) *shiftreg >> 5);
5010 bit = *shiftreg & 0x1F;
5012 CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5018 write_back_long(emu, srcval | mask);
5021 write_back_long(emu, srcval & ~mask);
5024 write_back_long(emu, srcval ^ mask);
5030 common_bitstring16(struct x86emu *emu, int op)
5033 uint16_t srcval, *shiftreg, mask;
5035 fetch_decode_modrm(emu);
5036 shiftreg = decode_rh_word_register(emu);
5037 srcval = decode_and_fetch_word_disp(emu, (int16_t) *shiftreg >> 4);
5038 bit = *shiftreg & 0xF;
5040 CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5046 write_back_word(emu, srcval | mask);
5049 write_back_word(emu, srcval & ~mask);
5052 write_back_word(emu, srcval ^ mask);
5058 common_bitstring(struct x86emu *emu, int op)
5060 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5061 common_bitstring32(emu, op);
5063 common_bitstring16(emu, op);
5067 common_bitsearch32(struct x86emu *emu, int diff)
5069 uint32_t srcval, *dstreg;
5071 fetch_decode_modrm(emu);
5072 dstreg = decode_rh_long_register(emu);
5073 srcval = decode_and_fetch_long(emu);
5074 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
5075 for (*dstreg = 0; *dstreg < 32; *dstreg += diff) {
5076 if ((srcval >> *dstreg) & 1)
5082 common_bitsearch16(struct x86emu *emu, int diff)
5084 uint16_t srcval, *dstreg;
5086 fetch_decode_modrm(emu);
5087 dstreg = decode_rh_word_register(emu);
5088 srcval = decode_and_fetch_word(emu);
5089 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
5090 for (*dstreg = 0; *dstreg < 16; *dstreg += diff) {
5091 if ((srcval >> *dstreg) & 1)
5097 common_bitsearch(struct x86emu *emu, int diff)
5099 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5100 common_bitsearch32(emu, diff);
5102 common_bitsearch16(emu, diff);
5106 common_shift32(struct x86emu *emu, int shift_left, int use_cl)
5109 uint32_t destval, *shiftreg;
5111 fetch_decode_modrm(emu);
5112 shiftreg = decode_rh_long_register(emu);
5114 destval = decode_and_fetch_long(emu);
5115 shift = emu->x86.R_CL;
5117 destval = decode_and_fetch_long_imm8(emu, &shift);
5120 destval = shld_long(emu, destval, *shiftreg, shift);
5122 destval = shrd_long(emu, destval, *shiftreg, shift);
5123 write_back_long(emu, destval);
5127 common_shift16(struct x86emu *emu, int shift_left, int use_cl)
5130 uint16_t destval, *shiftreg;
5132 fetch_decode_modrm(emu);
5133 shiftreg = decode_rh_word_register(emu);
5135 destval = decode_and_fetch_word(emu);
5136 shift = emu->x86.R_CL;
5138 destval = decode_and_fetch_word_imm8(emu, &shift);
5141 destval = shld_word(emu, destval, *shiftreg, shift);
5143 destval = shrd_word(emu, destval, *shiftreg, shift);
5144 write_back_word(emu, destval);
5148 common_shift(struct x86emu *emu, int shift_left, int use_cl)
5150 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5151 common_shift32(emu, shift_left, use_cl);
5153 common_shift16(emu, shift_left, use_cl);
5156 /*----------------------------- Implementation ----------------------------*/
5157 #define xorl(a,b) ((a) && !(b)) || (!(a) && (b))
5162 * Handles opcode 0x0f,0x31
5165 x86emuOp2_rdtsc(struct x86emu *emu)
5167 emu->x86.R_EAX = emu->cur_cycles & 0xffffffff;
5168 emu->x86.R_EDX = emu->cur_cycles >> 32;
5173 * Handles opcode 0x0f,0xa0
5176 x86emuOp2_push_FS(struct x86emu *emu)
5178 push_word(emu, emu->x86.R_FS);
5183 * Handles opcode 0x0f,0xa1
5186 x86emuOp2_pop_FS(struct x86emu *emu)
5188 emu->x86.R_FS = pop_word(emu);
5193 * Handles opcode 0x0f,0xa1
5195 #if defined(__i386__) || defined(__amd64__)
5197 hw_cpuid(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d)
5199 __asm__ __volatile__("cpuid"
5200 : "=a" (*a), "=b" (*b),
5201 "=c" (*c), "=d" (*d)
5202 : "a" (*a), "c" (*c)
5207 x86emuOp2_cpuid(struct x86emu *emu)
5209 #if defined(__i386__) || defined(__amd64__)
5210 hw_cpuid(&emu->x86.R_EAX, &emu->x86.R_EBX, &emu->x86.R_ECX,
5213 switch (emu->x86.R_EAX) {
5216 #if !defined(__i386__) && !defined(__amd64__)
5217 /* "GenuineIntel" */
5218 emu->x86.R_EBX = 0x756e6547;
5219 emu->x86.R_EDX = 0x49656e69;
5220 emu->x86.R_ECX = 0x6c65746e;
5224 #if !defined(__i386__) && !defined(__amd64__)
5225 emu->x86.R_EAX = 0x00000480;
5226 emu->x86.R_EBX = emu->x86.R_ECX = 0;
5227 emu->x86.R_EDX = 0x00000002;
5229 emu->x86.R_EDX &= 0x00000012;
5233 emu->x86.R_EAX = emu->x86.R_EBX = emu->x86.R_ECX =
5241 * Handles opcode 0x0f,0xa3
5244 x86emuOp2_bt_R(struct x86emu *emu)
5246 common_bitstring(emu, 0);
5251 * Handles opcode 0x0f,0xa4
5254 x86emuOp2_shld_IMM(struct x86emu *emu)
5256 common_shift(emu, 1, 0);
5261 * Handles opcode 0x0f,0xa5
5264 x86emuOp2_shld_CL(struct x86emu *emu)
5266 common_shift(emu, 1, 1);
5271 * Handles opcode 0x0f,0xa8
5274 x86emuOp2_push_GS(struct x86emu *emu)
5276 push_word(emu, emu->x86.R_GS);
5281 * Handles opcode 0x0f,0xa9
5284 x86emuOp2_pop_GS(struct x86emu *emu)
5286 emu->x86.R_GS = pop_word(emu);
5291 * Handles opcode 0x0f,0xab
5294 x86emuOp2_bts_R(struct x86emu *emu)
5296 common_bitstring(emu, 1);
5301 * Handles opcode 0x0f,0xac
5304 x86emuOp2_shrd_IMM(struct x86emu *emu)
5306 common_shift(emu, 0, 0);
5311 * Handles opcode 0x0f,0xad
5314 x86emuOp2_shrd_CL(struct x86emu *emu)
5316 common_shift(emu, 0, 1);
5321 * Handles opcode 0x0f,0xaf
5324 x86emuOp2_32_imul_R_RM(struct x86emu *emu)
5326 uint32_t *destreg, srcval;
5329 fetch_decode_modrm(emu);
5330 destreg = decode_rh_long_register(emu);
5331 srcval = decode_and_fetch_long(emu);
5332 res = (int32_t) *destreg * (int32_t)srcval;
5333 if (res > 0xffffffff) {
5340 *destreg = (uint32_t) res;
5344 x86emuOp2_16_imul_R_RM(struct x86emu *emu)
5346 uint16_t *destreg, srcval;
5349 fetch_decode_modrm(emu);
5350 destreg = decode_rh_word_register(emu);
5351 srcval = decode_and_fetch_word(emu);
5352 res = (int16_t) * destreg * (int16_t)srcval;
5360 *destreg = (uint16_t) res;
5364 x86emuOp2_imul_R_RM(struct x86emu *emu)
5366 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5367 x86emuOp2_32_imul_R_RM(emu);
5369 x86emuOp2_16_imul_R_RM(emu);
5374 * Handles opcode 0x0f,0xb2
5377 x86emuOp2_lss_R_IMM(struct x86emu *emu)
5379 common_load_far_pointer(emu, &emu->x86.R_SS);
5384 * Handles opcode 0x0f,0xb3
5387 x86emuOp2_btr_R(struct x86emu *emu)
5389 common_bitstring(emu, 2);
5394 * Handles opcode 0x0f,0xb4
5397 x86emuOp2_lfs_R_IMM(struct x86emu *emu)
5399 common_load_far_pointer(emu, &emu->x86.R_FS);
5404 * Handles opcode 0x0f,0xb5
5407 x86emuOp2_lgs_R_IMM(struct x86emu *emu)
5409 common_load_far_pointer(emu, &emu->x86.R_GS);
5414 * Handles opcode 0x0f,0xb6
5417 x86emuOp2_32_movzx_byte_R_RM(struct x86emu *emu)
5421 fetch_decode_modrm(emu);
5422 destreg = decode_rh_long_register(emu);
5423 *destreg = decode_and_fetch_byte(emu);
5427 x86emuOp2_16_movzx_byte_R_RM(struct x86emu *emu)
5431 fetch_decode_modrm(emu);
5432 destreg = decode_rh_word_register(emu);
5433 *destreg = decode_and_fetch_byte(emu);
5437 x86emuOp2_movzx_byte_R_RM(struct x86emu *emu)
5439 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5440 x86emuOp2_32_movzx_byte_R_RM(emu);
5442 x86emuOp2_16_movzx_byte_R_RM(emu);
5447 * Handles opcode 0x0f,0xb7
5450 x86emuOp2_movzx_word_R_RM(struct x86emu *emu)
5454 fetch_decode_modrm(emu);
5455 destreg = decode_rh_long_register(emu);
5456 *destreg = decode_and_fetch_word(emu);
5461 * Handles opcode 0x0f,0xba
5464 x86emuOp2_32_btX_I(struct x86emu *emu)
5467 uint32_t srcval, mask;
5470 fetch_decode_modrm(emu);
5471 if (emu->cur_rh < 4)
5472 x86emu_halt_sys(emu);
5474 srcval = decode_and_fetch_long_imm8(emu, &shift);
5476 mask = (0x1 << bit);
5478 switch (emu->cur_rh) {
5480 write_back_long(emu, srcval | mask);
5483 write_back_long(emu, srcval & ~mask);
5486 write_back_long(emu, srcval ^ mask);
5489 CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5493 x86emuOp2_16_btX_I(struct x86emu *emu)
5497 uint16_t srcval, mask;
5500 fetch_decode_modrm(emu);
5501 if (emu->cur_rh < 4)
5502 x86emu_halt_sys(emu);
5504 srcval = decode_and_fetch_word_imm8(emu, &shift);
5506 mask = (0x1 << bit);
5507 switch (emu->cur_rh) {
5509 write_back_word(emu, srcval | mask);
5512 write_back_word(emu, srcval & ~mask);
5515 write_back_word(emu, srcval ^ mask);
5518 CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5522 x86emuOp2_btX_I(struct x86emu *emu)
5524 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5525 x86emuOp2_32_btX_I(emu);
5527 x86emuOp2_16_btX_I(emu);
5532 * Handles opcode 0x0f,0xbb
5535 x86emuOp2_btc_R(struct x86emu *emu)
5537 common_bitstring(emu, 3);
5542 * Handles opcode 0x0f,0xbc
5545 x86emuOp2_bsf(struct x86emu *emu)
5547 common_bitsearch(emu, +1);
5552 * Handles opcode 0x0f,0xbd
5555 x86emuOp2_bsr(struct x86emu *emu)
5557 common_bitsearch(emu, -1);
5562 * Handles opcode 0x0f,0xbe
5565 x86emuOp2_32_movsx_byte_R_RM(struct x86emu *emu)
5569 destreg = decode_rh_long_register(emu);
5570 *destreg = (int32_t)(int8_t)decode_and_fetch_byte(emu);
5574 x86emuOp2_16_movsx_byte_R_RM(struct x86emu *emu)
5578 fetch_decode_modrm(emu);
5579 destreg = decode_rh_word_register(emu);
5580 *destreg = (int16_t)(int8_t)decode_and_fetch_byte(emu);
5584 x86emuOp2_movsx_byte_R_RM(struct x86emu *emu)
5586 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5587 x86emuOp2_32_movsx_byte_R_RM(emu);
5589 x86emuOp2_16_movsx_byte_R_RM(emu);
5594 * Handles opcode 0x0f,0xbf
5597 x86emuOp2_movsx_word_R_RM(struct x86emu *emu)
5601 fetch_decode_modrm(emu);
5602 destreg = decode_rh_long_register(emu);
5603 *destreg = (int32_t)(int16_t)decode_and_fetch_word(emu);
5607 x86emu_exec_two_byte(struct x86emu * emu)
5611 op2 = fetch_byte_imm(emu);
5614 /* 0x00 Group F (ring 0 PM) */
5615 /* 0x01 Group G (ring 0 PM) */
5616 /* 0x02 lar (ring 0 PM) */
5617 /* 0x03 lsl (ring 0 PM) */
5618 /* 0x05 loadall (undocumented) */
5619 /* 0x06 clts (ring 0 PM) */
5620 /* 0x07 loadall (undocumented) */
5621 /* 0x08 invd (ring 0 PM) */
5622 /* 0x09 wbinvd (ring 0 PM) */
5624 /* 0x20 mov reg32(op2); break;creg (ring 0 PM) */
5625 /* 0x21 mov reg32(op2); break;dreg (ring 0 PM) */
5626 /* 0x22 mov creg(op2); break;reg32 (ring 0 PM) */
5627 /* 0x23 mov dreg(op2); break;reg32 (ring 0 PM) */
5628 /* 0x24 mov reg32(op2); break;treg (ring 0 PM) */
5629 /* 0x26 mov treg(op2); break;reg32 (ring 0 PM) */
5632 x86emuOp2_rdtsc(emu);
5636 common_jmp_long(emu, ACCESS_FLAG(F_OF));
5639 common_jmp_long(emu, !ACCESS_FLAG(F_OF));
5642 common_jmp_long(emu, ACCESS_FLAG(F_CF));
5645 common_jmp_long(emu, !ACCESS_FLAG(F_CF));
5648 common_jmp_long(emu, ACCESS_FLAG(F_ZF));
5651 common_jmp_long(emu, !ACCESS_FLAG(F_ZF));
5654 common_jmp_long(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
5657 common_jmp_long(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)));
5660 common_jmp_long(emu, ACCESS_FLAG(F_SF));
5663 common_jmp_long(emu, !ACCESS_FLAG(F_SF));
5666 common_jmp_long(emu, ACCESS_FLAG(F_PF));
5669 common_jmp_long(emu, !ACCESS_FLAG(F_PF));
5672 common_jmp_long(emu, xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)));
5675 common_jmp_long(emu, !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF))));
5678 common_jmp_long(emu,
5679 (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || ACCESS_FLAG(F_ZF)));
5682 common_jmp_long(emu,
5683 !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || ACCESS_FLAG(F_ZF)));
5687 common_set_byte(emu, ACCESS_FLAG(F_OF));
5690 common_set_byte(emu, !ACCESS_FLAG(F_OF));
5693 common_set_byte(emu, ACCESS_FLAG(F_CF));
5696 common_set_byte(emu, !ACCESS_FLAG(F_CF));
5699 common_set_byte(emu, ACCESS_FLAG(F_ZF));
5702 common_set_byte(emu, !ACCESS_FLAG(F_ZF));
5705 common_set_byte(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
5708 common_set_byte(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)));
5711 common_set_byte(emu, ACCESS_FLAG(F_SF));
5714 common_set_byte(emu, !ACCESS_FLAG(F_SF));
5717 common_set_byte(emu, ACCESS_FLAG(F_PF));
5720 common_set_byte(emu, !ACCESS_FLAG(F_PF));
5723 common_set_byte(emu, xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)));
5726 common_set_byte(emu, xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)));
5729 common_set_byte(emu,
5730 (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
5731 ACCESS_FLAG(F_ZF)));
5734 common_set_byte(emu,
5735 !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
5736 ACCESS_FLAG(F_ZF)));
5740 x86emuOp2_push_FS(emu);
5743 x86emuOp2_pop_FS(emu);
5746 x86emuOp2_cpuid(emu);
5749 x86emuOp2_bt_R(emu);
5752 x86emuOp2_shld_IMM(emu);
5755 x86emuOp2_shld_CL(emu);
5758 x86emuOp2_push_GS(emu);
5761 x86emuOp2_pop_GS(emu);
5764 x86emuOp2_bts_R(emu);
5767 x86emuOp2_shrd_IMM(emu);
5770 x86emuOp2_shrd_CL(emu);
5773 x86emuOp2_imul_R_RM(emu);
5776 /* 0xb0 TODO: cmpxchg */
5777 /* 0xb1 TODO: cmpxchg */
5779 x86emuOp2_lss_R_IMM(emu);
5782 x86emuOp2_btr_R(emu);
5785 x86emuOp2_lfs_R_IMM(emu);
5788 x86emuOp2_lgs_R_IMM(emu);
5791 x86emuOp2_movzx_byte_R_RM(emu);
5794 x86emuOp2_movzx_word_R_RM(emu);
5797 x86emuOp2_btX_I(emu);
5800 x86emuOp2_btc_R(emu);
5809 x86emuOp2_movsx_byte_R_RM(emu);
5812 x86emuOp2_movsx_word_R_RM(emu);
5815 /* 0xc0 TODO: xadd */
5816 /* 0xc1 TODO: xadd */
5817 /* 0xc8 TODO: bswap */
5818 /* 0xc9 TODO: bswap */
5819 /* 0xca TODO: bswap */
5820 /* 0xcb TODO: bswap */
5821 /* 0xcc TODO: bswap */
5822 /* 0xcd TODO: bswap */
5823 /* 0xce TODO: bswap */
5824 /* 0xcf TODO: bswap */
5827 x86emu_halt_sys(emu);
5833 * Carry Chain Calculation
5835 * This represents a somewhat expensive calculation which is
5836 * apparently required to emulate the setting of the OF and AF flag.
5837 * The latter is not so important, but the former is. The overflow
5838 * flag is the XOR of the top two bits of the carry chain for an
5839 * addition (similar for subtraction). Since we do not want to
5840 * simulate the addition in a bitwise manner, we try to calculate the
5841 * carry chain given the two operands and the result.
5843 * So, given the following table, which represents the addition of two
5844 * bits, we can derive a formula for the carry chain.
5856 * Construction of table for cout:
5860 * |------------------
5864 * By inspection, one gets: cc = ab + r'(a + b)
5866 * That represents alot of operations, but NO CHOICE....
5868 * Borrow Chain Calculation.
5870 * The following table represents the subtraction of two bits, from
5871 * which we can derive a formula for the borrow chain.
5883 * Construction of table for cout:
5887 * |------------------
5891 * By inspection, one gets: bc = a'b + r(a' + b)
5895 /*------------------------- Global Variables ------------------------------*/
5897 static uint32_t x86emu_parity_tab[8] =
5908 #define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
5909 #define XOR2(x) (((x) ^ ((x)>>1)) & 0x1)
5914 * Implements the AAA instruction and side effects.
5917 aaa_word(struct x86emu *emu, uint16_t d)
5920 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
5929 res = (uint16_t) (d & 0xFF0F);
5931 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
5932 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
5938 * Implements the AAA instruction and side effects.
5941 aas_word(struct x86emu *emu, uint16_t d)
5944 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
5953 res = (uint16_t) (d & 0xFF0F);
5955 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
5956 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
5962 * Implements the AAD instruction and side effects.
5965 aad_word(struct x86emu *emu, uint16_t d)
5970 hb = (uint8_t) ((d >> 8) & 0xff);
5971 lb = (uint8_t) ((d & 0xff));
5972 l = (uint16_t) ((lb + 10 * hb) & 0xFF);
5977 CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
5978 CONDITIONAL_SET_FLAG(l == 0, F_ZF);
5979 CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
5985 * Implements the AAM instruction and side effects.
5988 aam_word(struct x86emu *emu, uint8_t d)
5992 h = (uint16_t) (d / 10);
5993 l = (uint16_t) (d % 10);
5994 l |= (uint16_t) (h << 8);
5999 CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
6000 CONDITIONAL_SET_FLAG(l == 0, F_ZF);
6001 CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
6007 * Implements the ADC instruction and side effects.
6010 adc_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6012 uint32_t res; /* all operands in native machine order */
6015 if (ACCESS_FLAG(F_CF))
6020 CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
6021 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6022 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6023 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6025 /* calculate the carry chain SEE NOTE AT TOP. */
6026 cc = (s & d) | ((~res) & (s | d));
6027 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
6028 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6029 return (uint8_t) res;
6034 * Implements the ADC instruction and side effects.
6037 adc_word(struct x86emu *emu, uint16_t d, uint16_t s)
6039 uint32_t res; /* all operands in native machine order */
6042 if (ACCESS_FLAG(F_CF))
6047 CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
6048 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6049 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6050 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6052 /* calculate the carry chain SEE NOTE AT TOP. */
6053 cc = (s & d) | ((~res) & (s | d));
6054 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
6055 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6056 return (uint16_t) res;
6061 * Implements the ADC instruction and side effects.
6064 adc_long(struct x86emu *emu, uint32_t d, uint32_t s)
6066 uint32_t lo; /* all operands in native machine order */
6071 if (ACCESS_FLAG(F_CF)) {
6072 lo = 1 + (d & 0xFFFF) + (s & 0xFFFF);
6075 lo = (d & 0xFFFF) + (s & 0xFFFF);
6078 hi = (lo >> 16) + (d >> 16) + (s >> 16);
6080 CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
6081 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6082 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6083 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6085 /* calculate the carry chain SEE NOTE AT TOP. */
6086 cc = (s & d) | ((~res) & (s | d));
6087 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
6088 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6094 * Implements the ADD instruction and side effects.
6097 add_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6099 uint32_t res; /* all operands in native machine order */
6103 CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
6104 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6105 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6106 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6108 /* calculate the carry chain SEE NOTE AT TOP. */
6109 cc = (s & d) | ((~res) & (s | d));
6110 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
6111 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6112 return (uint8_t) res;
6117 * Implements the ADD instruction and side effects.
6120 add_word(struct x86emu *emu, uint16_t d, uint16_t s)
6122 uint32_t res; /* all operands in native machine order */
6126 CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
6127 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6128 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6129 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6131 /* calculate the carry chain SEE NOTE AT TOP. */
6132 cc = (s & d) | ((~res) & (s | d));
6133 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
6134 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6135 return (uint16_t) res;
6140 * Implements the ADD instruction and side effects.
6143 add_long(struct x86emu *emu, uint32_t d, uint32_t s)
6145 uint32_t lo; /* all operands in native machine order */
6150 lo = (d & 0xFFFF) + (s & 0xFFFF);
6152 hi = (lo >> 16) + (d >> 16) + (s >> 16);
6154 CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
6155 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6156 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6157 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6159 /* calculate the carry chain SEE NOTE AT TOP. */
6160 cc = (s & d) | ((~res) & (s | d));
6161 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
6162 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6169 * Implements the AND instruction and side effects.
6172 and_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6174 uint8_t res; /* all operands in native machine order */
6182 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6183 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6184 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6190 * Implements the AND instruction and side effects.
6193 and_word(struct x86emu *emu, uint16_t d, uint16_t s)
6195 uint16_t res; /* all operands in native machine order */
6203 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6204 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6205 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6211 * Implements the AND instruction and side effects.
6214 and_long(struct x86emu *emu, uint32_t d, uint32_t s)
6216 uint32_t res; /* all operands in native machine order */
6224 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6225 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6226 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6232 * Implements the CMP instruction and side effects.
6235 cmp_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6237 uint32_t res; /* all operands in native machine order */
6242 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6243 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6244 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6246 /* calculate the borrow chain. See note at top */
6247 bc = (res & (~d | s)) | (~d & s);
6248 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
6249 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6250 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6255 cmp_byte_no_return(struct x86emu *emu, uint8_t d, uint8_t s)
6257 cmp_byte(emu, d, s);
6262 * Implements the CMP instruction and side effects.
6265 cmp_word(struct x86emu *emu, uint16_t d, uint16_t s)
6267 uint32_t res; /* all operands in native machine order */
6271 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6272 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6273 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6275 /* calculate the borrow chain. See note at top */
6276 bc = (res & (~d | s)) | (~d & s);
6277 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
6278 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6279 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6284 cmp_word_no_return(struct x86emu *emu, uint16_t d, uint16_t s)
6286 cmp_word(emu, d, s);
6291 * Implements the CMP instruction and side effects.
6294 cmp_long(struct x86emu *emu, uint32_t d, uint32_t s)
6296 uint32_t res; /* all operands in native machine order */
6300 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6301 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6302 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6304 /* calculate the borrow chain. See note at top */
6305 bc = (res & (~d | s)) | (~d & s);
6306 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
6307 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6308 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6313 cmp_long_no_return(struct x86emu *emu, uint32_t d, uint32_t s)
6315 cmp_long(emu, d, s);
6320 * Implements the DAA instruction and side effects.
6323 daa_byte(struct x86emu *emu, uint8_t d)
6326 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
6330 if (res > 0x9F || ACCESS_FLAG(F_CF)) {
6334 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6335 CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF);
6336 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6337 return (uint8_t) res;
6342 * Implements the DAS instruction and side effects.
6345 das_byte(struct x86emu *emu, uint8_t d)
6347 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
6351 if (d > 0x9F || ACCESS_FLAG(F_CF)) {
6355 CONDITIONAL_SET_FLAG(d & 0x80, F_SF);
6356 CONDITIONAL_SET_FLAG(d == 0, F_ZF);
6357 CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF);
6363 * Implements the DEC instruction and side effects.
6366 dec_byte(struct x86emu *emu, uint8_t d)
6368 uint32_t res; /* all operands in native machine order */
6372 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6373 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6374 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6376 /* calculate the borrow chain. See note at top */
6377 /* based on sub_byte, uses s==1. */
6378 bc = (res & (~d | 1)) | (~d & 1);
6379 /* carry flag unchanged */
6380 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6381 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6382 return (uint8_t) res;
6387 * Implements the DEC instruction and side effects.
6390 dec_word(struct x86emu *emu, uint16_t d)
6392 uint32_t res; /* all operands in native machine order */
6396 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6397 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6398 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6400 /* calculate the borrow chain. See note at top */
6401 /* based on the sub_byte routine, with s==1 */
6402 bc = (res & (~d | 1)) | (~d & 1);
6403 /* carry flag unchanged */
6404 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6405 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6406 return (uint16_t) res;
6411 * Implements the DEC instruction and side effects.
6414 dec_long(struct x86emu *emu, uint32_t d)
6416 uint32_t res; /* all operands in native machine order */
6421 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6422 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6423 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6425 /* calculate the borrow chain. See note at top */
6426 bc = (res & (~d | 1)) | (~d & 1);
6427 /* carry flag unchanged */
6428 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6429 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6435 * Implements the INC instruction and side effects.
6438 inc_byte(struct x86emu *emu, uint8_t d)
6440 uint32_t res; /* all operands in native machine order */
6444 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6445 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6446 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6448 /* calculate the carry chain SEE NOTE AT TOP. */
6449 cc = ((1 & d) | (~res)) & (1 | d);
6450 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
6451 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6452 return (uint8_t) res;
6457 * Implements the INC instruction and side effects.
6460 inc_word(struct x86emu *emu, uint16_t d)
6462 uint32_t res; /* all operands in native machine order */
6466 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6467 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6468 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6470 /* calculate the carry chain SEE NOTE AT TOP. */
6471 cc = (1 & d) | ((~res) & (1 | d));
6472 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
6473 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6474 return (uint16_t) res;
6479 * Implements the INC instruction and side effects.
6482 inc_long(struct x86emu *emu, uint32_t d)
6484 uint32_t res; /* all operands in native machine order */
6488 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6489 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6490 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6492 /* calculate the carry chain SEE NOTE AT TOP. */
6493 cc = (1 & d) | ((~res) & (1 | d));
6494 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
6495 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6501 * Implements the OR instruction and side effects.
6504 or_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6506 uint8_t res; /* all operands in native machine order */
6512 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6513 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6514 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6520 * Implements the OR instruction and side effects.
6523 or_word(struct x86emu *emu, uint16_t d, uint16_t s)
6525 uint16_t res; /* all operands in native machine order */
6528 /* set the carry flag to be bit 8 */
6532 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6533 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6534 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6540 * Implements the OR instruction and side effects.
6543 or_long(struct x86emu *emu, uint32_t d, uint32_t s)
6545 uint32_t res; /* all operands in native machine order */
6549 /* set the carry flag to be bit 8 */
6553 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6554 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6555 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6561 * Implements the OR instruction and side effects.
6564 neg_byte(struct x86emu *emu, uint8_t s)
6569 CONDITIONAL_SET_FLAG(s != 0, F_CF);
6570 res = (uint8_t) - s;
6571 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6572 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6573 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6574 /* calculate the borrow chain --- modified such that d=0.
6575 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for
6576 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6577 * res&0xfff... == res. Similarly ~d&s == s. So the simplified
6580 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6581 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6587 * Implements the OR instruction and side effects.
6590 neg_word(struct x86emu *emu, uint16_t s)
6595 CONDITIONAL_SET_FLAG(s != 0, F_CF);
6596 res = (uint16_t) - s;
6597 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6598 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6599 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6601 /* calculate the borrow chain --- modified such that d=0.
6602 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for
6603 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6604 * res&0xfff... == res. Similarly ~d&s == s. So the simplified
6607 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6608 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6614 * Implements the OR instruction and side effects.
6617 neg_long(struct x86emu *emu, uint32_t s)
6622 CONDITIONAL_SET_FLAG(s != 0, F_CF);
6623 res = (uint32_t) - s;
6624 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6625 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6626 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6628 /* calculate the borrow chain --- modified such that d=0.
6629 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for
6630 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6631 * res&0xfff... == res. Similarly ~d&s == s. So the simplified
6634 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6635 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6641 * Implements the RCL instruction and side effects.
6644 rcl_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6646 unsigned int res, cnt, mask, cf;
6648 /* s is the rotate distance. It varies from 0 - 8. */
6651 * CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
6653 * want to rotate through the carry by "s" bits. We could loop, but
6654 * that's inefficient. So the width is 9, and we split into three
6657 * The new carry flag (was B_n) the stuff in B_n-1 .. B_0 the stuff in
6660 * The new rotate is done mod 9, and given this, for a rotation of n bits
6661 * (mod 9) the new carry flag is then located n bits from the MSB.
6662 * The low part is then shifted up cnt bits, and the high part is or'd
6663 * in. Using CAPS for new values, and lowercase for the original
6664 * values, this can be expressed as:
6666 * IF n > 0 1) CF <- b_(8-n) 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0
6667 * 3) B_(n-1) <- cf 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */
6669 if ((cnt = s % 9) != 0) {
6670 /* extract the new CARRY FLAG. */
6672 cf = (d >> (8 - cnt)) & 0x1;
6674 /* get the low stuff which rotated into the range B_7 .. B_cnt */
6675 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 */
6676 /* note that the right hand side done by the mask */
6677 res = (d << cnt) & 0xff;
6679 /* now the high stuff which rotated around into the positions
6681 /* B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */
6682 /* shift it downward, 7-(n-2) = 9-n positions. and mask off
6683 * the result before or'ing in. */
6684 mask = (1 << (cnt - 1)) - 1;
6685 res |= (d >> (9 - cnt)) & mask;
6687 /* if the carry flag was set, or it in. */
6688 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
6690 res |= 1 << (cnt - 1);
6692 /* set the new carry flag, based on the variable "cf" */
6693 CONDITIONAL_SET_FLAG(cf, F_CF);
6694 /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and
6695 * the most significant bit. Blecck. */
6696 /* parenthesized this expression since it appears to be
6697 * causing OF to be misset */
6698 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
6702 return (uint8_t) res;
6707 * Implements the RCL instruction and side effects.
6710 rcl_word(struct x86emu *emu, uint16_t d, uint8_t s)
6712 unsigned int res, cnt, mask, cf;
6715 if ((cnt = s % 17) != 0) {
6716 cf = (d >> (16 - cnt)) & 0x1;
6717 res = (d << cnt) & 0xffff;
6718 mask = (1 << (cnt - 1)) - 1;
6719 res |= (d >> (17 - cnt)) & mask;
6720 if (ACCESS_FLAG(F_CF)) {
6721 res |= 1 << (cnt - 1);
6723 CONDITIONAL_SET_FLAG(cf, F_CF);
6724 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
6727 return (uint16_t) res;
6732 * Implements the RCL instruction and side effects.
6735 rcl_long(struct x86emu *emu, uint32_t d, uint8_t s)
6737 uint32_t res, cnt, mask, cf;
6740 if ((cnt = s % 33) != 0) {
6741 cf = (d >> (32 - cnt)) & 0x1;
6742 res = (d << cnt) & 0xffffffff;
6743 mask = (1 << (cnt - 1)) - 1;
6744 res |= (d >> (33 - cnt)) & mask;
6745 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
6746 res |= 1 << (cnt - 1);
6748 CONDITIONAL_SET_FLAG(cf, F_CF);
6749 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
6757 * Implements the RCR instruction and side effects.
6760 rcr_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6763 uint32_t mask, cf, ocf = 0;
6765 /* rotate right through carry */
6766 /* s is the rotate distance. It varies from 0 - 8. d is the byte
6771 * CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
6773 * The new rotate is done mod 9, and given this, for a rotation of n bits
6774 * (mod 9) the new carry flag is then located n bits from the LSB.
6775 * The low part is then shifted up cnt bits, and the high part is or'd
6776 * in. Using CAPS for new values, and lowercase for the original
6777 * values, this can be expressed as:
6779 * IF n > 0 1) CF <- b_(n-1) 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
6780 * 3) B_(8-n) <- cf 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */
6782 if ((cnt = s % 9) != 0) {
6783 /* extract the new CARRY FLAG. */
6787 /* note hackery here. Access_flag(..) evaluates to
6788 * either 0 if flag not set non-zero if flag is set.
6789 * doing access_flag(..) != 0 casts that into either
6790 * 0..1 in any representation of the flags register
6791 * (i.e. packed bit array or unpacked.) */
6792 ocf = ACCESS_FLAG(F_CF) != 0;
6794 cf = (d >> (cnt - 1)) & 0x1;
6796 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */
6797 /* note that the right hand side done by the mask This is
6798 * effectively done by shifting the object to the right. The
6799 * result must be masked, in case the object came in and was
6800 * treated as a negative number. Needed??? */
6802 mask = (1 << (8 - cnt)) - 1;
6803 res = (d >> cnt) & mask;
6805 /* now the high stuff which rotated around into the positions
6807 /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */
6808 /* shift it downward, 7-(n-2) = 9-n positions. and mask off
6809 * the result before or'ing in. */
6810 res |= (d << (9 - cnt));
6812 /* if the carry flag was set, or it in. */
6813 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
6815 res |= 1 << (8 - cnt);
6817 /* set the new carry flag, based on the variable "cf" */
6818 CONDITIONAL_SET_FLAG(cf, F_CF);
6819 /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and
6820 * the most significant bit. Blecck. */
6821 /* parenthesized... */
6823 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
6827 return (uint8_t) res;
6832 * Implements the RCR instruction and side effects.
6835 rcr_word(struct x86emu *emu, uint16_t d, uint8_t s)
6838 uint32_t mask, cf, ocf = 0;
6840 /* rotate right through carry */
6842 if ((cnt = s % 17) != 0) {
6845 ocf = ACCESS_FLAG(F_CF) != 0;
6847 cf = (d >> (cnt - 1)) & 0x1;
6848 mask = (1 << (16 - cnt)) - 1;
6849 res = (d >> cnt) & mask;
6850 res |= (d << (17 - cnt));
6851 if (ACCESS_FLAG(F_CF)) {
6852 res |= 1 << (16 - cnt);
6854 CONDITIONAL_SET_FLAG(cf, F_CF);
6856 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
6860 return (uint16_t) res;
6865 * Implements the RCR instruction and side effects.
6868 rcr_long(struct x86emu *emu, uint32_t d, uint8_t s)
6871 uint32_t mask, cf, ocf = 0;
6873 /* rotate right through carry */
6875 if ((cnt = s % 33) != 0) {
6878 ocf = ACCESS_FLAG(F_CF) != 0;
6880 cf = (d >> (cnt - 1)) & 0x1;
6881 mask = (1 << (32 - cnt)) - 1;
6882 res = (d >> cnt) & mask;
6884 res |= (d << (33 - cnt));
6885 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
6886 res |= 1 << (32 - cnt);
6888 CONDITIONAL_SET_FLAG(cf, F_CF);
6890 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
6899 * Implements the ROL instruction and side effects.
6902 rol_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6904 unsigned int res, cnt, mask;
6907 /* s is the rotate distance. It varies from 0 - 8. d is the byte
6914 * The new rotate is done mod 8. Much simpler than the "rcl" or "rcr"
6917 * IF n > 0 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) 2) B_(n-1) ..
6918 * B_(0) <- b_(7) .. b_(8-n) */
6920 if ((cnt = s % 8) != 0) {
6921 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */
6924 /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */
6925 mask = (1 << cnt) - 1;
6926 res |= (d >> (8 - cnt)) & mask;
6928 /* set the new carry flag, Note that it is the low order bit
6929 * of the result!!! */
6930 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
6931 /* OVERFLOW is set *IFF* s==1, then it is the xor of CF and
6932 * the most significant bit. Blecck. */
6933 CONDITIONAL_SET_FLAG(s == 1 &&
6934 XOR2((res & 0x1) + ((res >> 6) & 0x2)),
6937 /* set the new carry flag, Note that it is the low order bit
6938 * of the result!!! */
6939 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
6941 return (uint8_t) res;
6946 * Implements the ROL instruction and side effects.
6949 rol_word(struct x86emu *emu, uint16_t d, uint8_t s)
6951 unsigned int res, cnt, mask;
6954 if ((cnt = s % 16) != 0) {
6956 mask = (1 << cnt) - 1;
6957 res |= (d >> (16 - cnt)) & mask;
6958 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
6959 CONDITIONAL_SET_FLAG(s == 1 &&
6960 XOR2((res & 0x1) + ((res >> 14) & 0x2)),
6963 /* set the new carry flag, Note that it is the low order bit
6964 * of the result!!! */
6965 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
6967 return (uint16_t) res;
6972 * Implements the ROL instruction and side effects.
6975 rol_long(struct x86emu *emu, uint32_t d, uint8_t s)
6977 uint32_t res, cnt, mask;
6980 if ((cnt = s % 32) != 0) {
6982 mask = (1 << cnt) - 1;
6983 res |= (d >> (32 - cnt)) & mask;
6984 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
6985 CONDITIONAL_SET_FLAG(s == 1 &&
6986 XOR2((res & 0x1) + ((res >> 30) & 0x2)),
6989 /* set the new carry flag, Note that it is the low order bit
6990 * of the result!!! */
6991 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
6998 * Implements the ROR instruction and side effects.
7001 ror_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7003 unsigned int res, cnt, mask;
7006 /* s is the rotate distance. It varies from 0 - 8. d is the byte
7013 * The rotate is done mod 8.
7015 * IF n > 0 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) 2) B_(7) ..
7016 * B_(8-n) <- b_(n-1) .. b_(0) */
7018 if ((cnt = s % 8) != 0) { /* not a typo, do nada if cnt==0 */
7019 /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */
7020 res = (d << (8 - cnt));
7022 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */
7023 mask = (1 << (8 - cnt)) - 1;
7024 res |= (d >> (cnt)) & mask;
7026 /* set the new carry flag, Note that it is the low order bit
7027 * of the result!!! */
7028 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
7029 /* OVERFLOW is set *IFF* s==1, then it is the xor of the two
7030 * most significant bits. Blecck. */
7031 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
7032 } else if (s != 0) {
7033 /* set the new carry flag, Note that it is the low order bit
7034 * of the result!!! */
7035 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
7037 return (uint8_t) res;
7042 * Implements the ROR instruction and side effects.
7045 ror_word(struct x86emu *emu, uint16_t d, uint8_t s)
7047 unsigned int res, cnt, mask;
7050 if ((cnt = s % 16) != 0) {
7051 res = (d << (16 - cnt));
7052 mask = (1 << (16 - cnt)) - 1;
7053 res |= (d >> (cnt)) & mask;
7054 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
7055 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
7056 } else if (s != 0) {
7057 /* set the new carry flag, Note that it is the low order bit
7058 * of the result!!! */
7059 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
7061 return (uint16_t) res;
7066 * Implements the ROR instruction and side effects.
7069 ror_long(struct x86emu *emu, uint32_t d, uint8_t s)
7071 uint32_t res, cnt, mask;
7074 if ((cnt = s % 32) != 0) {
7075 res = (d << (32 - cnt));
7076 mask = (1 << (32 - cnt)) - 1;
7077 res |= (d >> (cnt)) & mask;
7078 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
7079 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
7080 } else if (s != 0) {
7081 /* set the new carry flag, Note that it is the low order bit
7082 * of the result!!! */
7083 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
7090 * Implements the SHL instruction and side effects.
7093 shl_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7095 unsigned int cnt, res, cf;
7100 /* last bit shifted out goes into carry flag */
7103 cf = d & (1 << (8 - cnt));
7104 CONDITIONAL_SET_FLAG(cf, F_CF);
7105 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7106 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7107 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7113 /* Needs simplification. */
7114 CONDITIONAL_SET_FLAG(
7115 (((res & 0x80) == 0x80) ^
7116 (ACCESS_FLAG(F_CF) != 0)),
7117 /* was (emu->x86.R_FLG&F_CF)==F_CF)), */
7124 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80, F_CF);
7130 return (uint8_t) res;
7135 * Implements the SHL instruction and side effects.
7138 shl_word(struct x86emu *emu, uint16_t d, uint8_t s)
7140 unsigned int cnt, res, cf;
7146 cf = d & (1 << (16 - cnt));
7147 CONDITIONAL_SET_FLAG(cf, F_CF);
7148 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7149 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7150 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7156 CONDITIONAL_SET_FLAG(
7157 (((res & 0x8000) == 0x8000) ^
7158 (ACCESS_FLAG(F_CF) != 0)),
7165 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF);
7171 return (uint16_t) res;
7176 * Implements the SHL instruction and side effects.
7179 shl_long(struct x86emu *emu, uint32_t d, uint8_t s)
7181 unsigned int cnt, res, cf;
7187 cf = d & (1 << (32 - cnt));
7188 CONDITIONAL_SET_FLAG(cf, F_CF);
7189 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7190 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7191 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7196 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
7197 (ACCESS_FLAG(F_CF) != 0)), F_OF);
7203 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF);
7214 * Implements the SHR instruction and side effects.
7217 shr_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7219 unsigned int cnt, res, cf;
7224 cf = d & (1 << (cnt - 1));
7226 CONDITIONAL_SET_FLAG(cf, F_CF);
7227 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7228 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7229 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7235 CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
7241 CONDITIONAL_SET_FLAG((d >> (s - 1)) & 0x1, F_CF);
7247 return (uint8_t) res;
7252 * Implements the SHR instruction and side effects.
7255 shr_word(struct x86emu *emu, uint16_t d, uint8_t s)
7257 unsigned int cnt, res, cf;
7262 cf = d & (1 << (cnt - 1));
7264 CONDITIONAL_SET_FLAG(cf, F_CF);
7265 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7266 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7267 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7273 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
7285 return (uint16_t) res;
7290 * Implements the SHR instruction and side effects.
7293 shr_long(struct x86emu *emu, uint32_t d, uint8_t s)
7295 unsigned int cnt, res, cf;
7300 cf = d & (1 << (cnt - 1));
7302 CONDITIONAL_SET_FLAG(cf, F_CF);
7303 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7304 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7305 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7310 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
7327 * Implements the SAR instruction and side effects.
7330 sar_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7332 unsigned int cnt, res, cf, mask, sf;
7337 if (cnt > 0 && cnt < 8) {
7338 mask = (1 << (8 - cnt)) - 1;
7339 cf = d & (1 << (cnt - 1));
7340 res = (d >> cnt) & mask;
7341 CONDITIONAL_SET_FLAG(cf, F_CF);
7345 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7346 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7347 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7348 } else if (cnt >= 8) {
7363 return (uint8_t) res;
7368 * Implements the SAR instruction and side effects.
7371 sar_word(struct x86emu *emu, uint16_t d, uint8_t s)
7373 unsigned int cnt, res, cf, mask, sf;
7378 if (cnt > 0 && cnt < 16) {
7379 mask = (1 << (16 - cnt)) - 1;
7380 cf = d & (1 << (cnt - 1));
7381 res = (d >> cnt) & mask;
7382 CONDITIONAL_SET_FLAG(cf, F_CF);
7386 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7387 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7388 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7389 } else if (cnt >= 16) {
7404 return (uint16_t) res;
7409 * Implements the SAR instruction and side effects.
7412 sar_long(struct x86emu *emu, uint32_t d, uint8_t s)
7414 uint32_t cnt, res, cf, mask, sf;
7416 sf = d & 0x80000000;
7419 if (cnt > 0 && cnt < 32) {
7420 mask = (1 << (32 - cnt)) - 1;
7421 cf = d & (1 << (cnt - 1));
7422 res = (d >> cnt) & mask;
7423 CONDITIONAL_SET_FLAG(cf, F_CF);
7427 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7428 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7429 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7430 } else if (cnt >= 32) {
7450 * Implements the SHLD instruction and side effects.
7453 shld_word(struct x86emu *emu, uint16_t d, uint16_t fill, uint8_t s)
7455 unsigned int cnt, res, cf;
7460 res = (d << cnt) | (fill >> (16 - cnt));
7461 cf = d & (1 << (16 - cnt));
7462 CONDITIONAL_SET_FLAG(cf, F_CF);
7463 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7464 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7465 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7470 CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
7471 (ACCESS_FLAG(F_CF) != 0)), F_OF);
7477 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF);
7483 return (uint16_t) res;
7488 * Implements the SHLD instruction and side effects.
7491 shld_long(struct x86emu *emu, uint32_t d, uint32_t fill, uint8_t s)
7493 unsigned int cnt, res, cf;
7498 res = (d << cnt) | (fill >> (32 - cnt));
7499 cf = d & (1 << (32 - cnt));
7500 CONDITIONAL_SET_FLAG(cf, F_CF);
7501 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7502 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7503 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7508 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
7509 (ACCESS_FLAG(F_CF) != 0)), F_OF);
7515 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF);
7526 * Implements the SHRD instruction and side effects.
7529 shrd_word(struct x86emu *emu, uint16_t d, uint16_t fill, uint8_t s)
7531 unsigned int cnt, res, cf;
7536 cf = d & (1 << (cnt - 1));
7537 res = (d >> cnt) | (fill << (16 - cnt));
7538 CONDITIONAL_SET_FLAG(cf, F_CF);
7539 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7540 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7541 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7547 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
7559 return (uint16_t) res;
7564 * Implements the SHRD instruction and side effects.
7567 shrd_long(struct x86emu *emu, uint32_t d, uint32_t fill, uint8_t s)
7569 unsigned int cnt, res, cf;
7574 cf = d & (1 << (cnt - 1));
7575 res = (d >> cnt) | (fill << (32 - cnt));
7576 CONDITIONAL_SET_FLAG(cf, F_CF);
7577 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7578 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7579 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7584 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
7601 * Implements the SBB instruction and side effects.
7604 sbb_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7606 uint32_t res; /* all operands in native machine order */
7609 if (ACCESS_FLAG(F_CF))
7613 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7614 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7615 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7617 /* calculate the borrow chain. See note at top */
7618 bc = (res & (~d | s)) | (~d & s);
7619 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
7620 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
7621 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7622 return (uint8_t) res;
7627 * Implements the SBB instruction and side effects.
7630 sbb_word(struct x86emu *emu, uint16_t d, uint16_t s)
7632 uint32_t res; /* all operands in native machine order */
7635 if (ACCESS_FLAG(F_CF))
7639 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7640 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7641 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7643 /* calculate the borrow chain. See note at top */
7644 bc = (res & (~d | s)) | (~d & s);
7645 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
7646 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
7647 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7648 return (uint16_t) res;
7653 * Implements the SBB instruction and side effects.
7656 sbb_long(struct x86emu *emu, uint32_t d, uint32_t s)
7658 uint32_t res; /* all operands in native machine order */
7661 if (ACCESS_FLAG(F_CF))
7665 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7666 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7667 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7669 /* calculate the borrow chain. See note at top */
7670 bc = (res & (~d | s)) | (~d & s);
7671 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
7672 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
7673 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7679 * Implements the SUB instruction and side effects.
7682 sub_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7684 uint32_t res; /* all operands in native machine order */
7688 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7689 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7690 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7692 /* calculate the borrow chain. See note at top */
7693 bc = (res & (~d | s)) | (~d & s);
7694 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
7695 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
7696 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7697 return (uint8_t) res;
7702 * Implements the SUB instruction and side effects.
7705 sub_word(struct x86emu *emu, uint16_t d, uint16_t s)
7707 uint32_t res; /* all operands in native machine order */
7711 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7712 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7713 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7715 /* calculate the borrow chain. See note at top */
7716 bc = (res & (~d | s)) | (~d & s);
7717 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
7718 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
7719 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7720 return (uint16_t) res;
7725 * Implements the SUB instruction and side effects.
7728 sub_long(struct x86emu *emu, uint32_t d, uint32_t s)
7730 uint32_t res; /* all operands in native machine order */
7734 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7735 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7736 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7738 /* calculate the borrow chain. See note at top */
7739 bc = (res & (~d | s)) | (~d & s);
7740 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
7741 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
7742 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7748 * Implements the TEST instruction and side effects.
7751 test_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7753 uint32_t res; /* all operands in native machine order */
7758 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7759 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7760 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7761 /* AF == dont care */
7767 * Implements the TEST instruction and side effects.
7770 test_word(struct x86emu *emu, uint16_t d, uint16_t s)
7772 uint32_t res; /* all operands in native machine order */
7777 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7778 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7779 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7780 /* AF == dont care */
7786 * Implements the TEST instruction and side effects.
7789 test_long(struct x86emu *emu, uint32_t d, uint32_t s)
7791 uint32_t res; /* all operands in native machine order */
7796 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7797 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7798 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7799 /* AF == dont care */
7805 * Implements the XOR instruction and side effects.
7808 xor_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7810 uint8_t res; /* all operands in native machine order */
7814 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7815 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7816 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
7824 * Implements the XOR instruction and side effects.
7827 xor_word(struct x86emu *emu, uint16_t d, uint16_t s)
7829 uint16_t res; /* all operands in native machine order */
7833 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7834 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7835 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7843 * Implements the XOR instruction and side effects.
7846 xor_long(struct x86emu *emu, uint32_t d, uint32_t s)
7848 uint32_t res; /* all operands in native machine order */
7852 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7853 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7854 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7862 * Implements the IMUL instruction and side effects.
7865 imul_byte(struct x86emu *emu, uint8_t s)
7867 int16_t res = (int16_t) ((int8_t) emu->x86.R_AL * (int8_t) s);
7869 emu->x86.R_AX = res;
7870 if (((emu->x86.R_AL & 0x80) == 0 && emu->x86.R_AH == 0x00) ||
7871 ((emu->x86.R_AL & 0x80) != 0 && emu->x86.R_AH == 0xFF)) {
7882 * Implements the IMUL instruction and side effects.
7885 imul_word(struct x86emu *emu, uint16_t s)
7887 int32_t res = (int16_t) emu->x86.R_AX * (int16_t) s;
7889 emu->x86.R_AX = (uint16_t) res;
7890 emu->x86.R_DX = (uint16_t) (res >> 16);
7891 if (((emu->x86.R_AX & 0x8000) == 0 && emu->x86.R_DX == 0x00) ||
7892 ((emu->x86.R_AX & 0x8000) != 0 && emu->x86.R_DX == 0xFF)) {
7903 * Implements the IMUL instruction and side effects.
7906 imul_long(struct x86emu *emu, uint32_t s)
7910 res = (int64_t)(int32_t)emu->x86.R_EAX * (int32_t)s;
7911 emu->x86.R_EAX = (uint32_t)res;
7912 emu->x86.R_EDX = ((uint64_t)res) >> 32;
7913 if (((emu->x86.R_EAX & 0x80000000) == 0 && emu->x86.R_EDX == 0x00) ||
7914 ((emu->x86.R_EAX & 0x80000000) != 0 && emu->x86.R_EDX == 0xFF)) {
7925 * Implements the MUL instruction and side effects.
7928 mul_byte(struct x86emu *emu, uint8_t s)
7930 uint16_t res = (uint16_t) (emu->x86.R_AL * s);
7932 emu->x86.R_AX = res;
7933 if (emu->x86.R_AH == 0) {
7944 * Implements the MUL instruction and side effects.
7947 mul_word(struct x86emu *emu, uint16_t s)
7949 uint32_t res = emu->x86.R_AX * s;
7951 emu->x86.R_AX = (uint16_t) res;
7952 emu->x86.R_DX = (uint16_t) (res >> 16);
7953 if (emu->x86.R_DX == 0) {
7964 * Implements the MUL instruction and side effects.
7967 mul_long(struct x86emu *emu, uint32_t s)
7969 uint64_t res = (uint64_t) emu->x86.R_EAX * s;
7971 emu->x86.R_EAX = (uint32_t) res;
7972 emu->x86.R_EDX = (uint32_t) (res >> 32);
7974 if (emu->x86.R_EDX == 0) {
7985 * Implements the IDIV instruction and side effects.
7988 idiv_byte(struct x86emu *emu, uint8_t s)
7990 int32_t dvd, div, mod;
7992 dvd = (int16_t) emu->x86.R_AX;
7994 x86emu_intr_raise(emu, 8);
7997 div = dvd / (int8_t) s;
7998 mod = dvd % (int8_t) s;
7999 if (div > 0x7f || div < -0x7f) {
8000 x86emu_intr_raise(emu, 8);
8003 emu->x86.R_AL = (int8_t) div;
8004 emu->x86.R_AH = (int8_t) mod;
8009 * Implements the IDIV instruction and side effects.
8012 idiv_word(struct x86emu *emu, uint16_t s)
8014 int32_t dvd, div, mod;
8016 dvd = (((int32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX;
8018 x86emu_intr_raise(emu, 8);
8021 div = dvd / (int16_t) s;
8022 mod = dvd % (int16_t) s;
8023 if (div > 0x7fff || div < -0x7fff) {
8024 x86emu_intr_raise(emu, 8);
8029 CONDITIONAL_SET_FLAG(div == 0, F_ZF);
8030 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
8032 emu->x86.R_AX = (uint16_t) div;
8033 emu->x86.R_DX = (uint16_t) mod;
8038 * Implements the IDIV instruction and side effects.
8041 idiv_long(struct x86emu *emu, uint32_t s)
8043 int64_t dvd, div, mod;
8045 dvd = (((int64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX;
8047 x86emu_intr_raise(emu, 8);
8050 div = dvd / (int32_t) s;
8051 mod = dvd % (int32_t) s;
8052 if (div > 0x7fffffff || div < -0x7fffffff) {
8053 x86emu_intr_raise(emu, 8);
8060 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
8062 emu->x86.R_EAX = (uint32_t) div;
8063 emu->x86.R_EDX = (uint32_t) mod;
8068 * Implements the DIV instruction and side effects.
8071 div_byte(struct x86emu *emu, uint8_t s)
8073 uint32_t dvd, div, mod;
8075 dvd = emu->x86.R_AX;
8077 x86emu_intr_raise(emu, 8);
8080 div = dvd / (uint8_t) s;
8081 mod = dvd % (uint8_t) s;
8083 x86emu_intr_raise(emu, 8);
8086 emu->x86.R_AL = (uint8_t) div;
8087 emu->x86.R_AH = (uint8_t) mod;
8092 * Implements the DIV instruction and side effects.
8095 div_word(struct x86emu *emu, uint16_t s)
8097 uint32_t dvd, div, mod;
8099 dvd = (((uint32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX;
8101 x86emu_intr_raise(emu, 8);
8104 div = dvd / (uint16_t) s;
8105 mod = dvd % (uint16_t) s;
8107 x86emu_intr_raise(emu, 8);
8112 CONDITIONAL_SET_FLAG(div == 0, F_ZF);
8113 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
8115 emu->x86.R_AX = (uint16_t) div;
8116 emu->x86.R_DX = (uint16_t) mod;
8121 * Implements the DIV instruction and side effects.
8124 div_long(struct x86emu *emu, uint32_t s)
8126 uint64_t dvd, div, mod;
8128 dvd = (((uint64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX;
8130 x86emu_intr_raise(emu, 8);
8133 div = dvd / (uint32_t) s;
8134 mod = dvd % (uint32_t) s;
8135 if (div > 0xffffffff) {
8136 x86emu_intr_raise(emu, 8);
8143 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
8145 emu->x86.R_EAX = (uint32_t) div;
8146 emu->x86.R_EDX = (uint32_t) mod;
8151 * Implements the IN string instruction and side effects.
8154 ins(struct x86emu *emu, int size)
8158 if (ACCESS_FLAG(F_DF)) {
8161 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
8162 /* dont care whether REPE or REPNE */
8163 /* in until CX is ZERO. */
8164 uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ?
8165 emu->x86.R_ECX : emu->x86.R_CX);
8169 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
8170 (*emu->emu_inb) (emu, emu->x86.R_DX));
8171 emu->x86.R_DI += inc;
8177 store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
8178 (*emu->emu_inw) (emu, emu->x86.R_DX));
8179 emu->x86.R_DI += inc;
8184 store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
8185 (*emu->emu_inl) (emu, emu->x86.R_DX));
8186 emu->x86.R_DI += inc;
8191 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
8194 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
8198 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
8199 (*emu->emu_inb) (emu, emu->x86.R_DX));
8202 store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
8203 (*emu->emu_inw) (emu, emu->x86.R_DX));
8206 store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
8207 (*emu->emu_inl) (emu, emu->x86.R_DX));
8210 emu->x86.R_DI += inc;
8216 * Implements the OUT string instruction and side effects.
8219 outs(struct x86emu *emu, int size)
8223 if (ACCESS_FLAG(F_DF)) {
8226 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
8227 /* dont care whether REPE or REPNE */
8228 /* out until CX is ZERO. */
8229 uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ?
8230 emu->x86.R_ECX : emu->x86.R_CX);
8234 (*emu->emu_outb) (emu, emu->x86.R_DX,
8235 fetch_byte(emu, emu->x86.R_ES, emu->x86.R_SI));
8236 emu->x86.R_SI += inc;
8242 (*emu->emu_outw) (emu, emu->x86.R_DX,
8243 fetch_word(emu, emu->x86.R_ES, emu->x86.R_SI));
8244 emu->x86.R_SI += inc;
8249 (*emu->emu_outl) (emu, emu->x86.R_DX,
8250 fetch_long(emu, emu->x86.R_ES, emu->x86.R_SI));
8251 emu->x86.R_SI += inc;
8256 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
8259 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
8263 (*emu->emu_outb) (emu, emu->x86.R_DX,
8264 fetch_byte(emu, emu->x86.R_ES, emu->x86.R_SI));
8267 (*emu->emu_outw) (emu, emu->x86.R_DX,
8268 fetch_word(emu, emu->x86.R_ES, emu->x86.R_SI));
8271 (*emu->emu_outl) (emu, emu->x86.R_DX,
8272 fetch_long(emu, emu->x86.R_ES, emu->x86.R_SI));
8275 emu->x86.R_SI += inc;
8281 * Pushes a word onto the stack.
8283 * NOTE: Do not inline this, as (*emu->emu_wrX) is already inline!
8286 push_word(struct x86emu *emu, uint16_t w)
8289 store_word(emu, emu->x86.R_SS, emu->x86.R_SP, w);
8294 * Pushes a long onto the stack.
8296 * NOTE: Do not inline this, as (*emu->emu_wrX) is already inline!
8299 push_long(struct x86emu *emu, uint32_t w)
8302 store_long(emu, emu->x86.R_SS, emu->x86.R_SP, w);
8307 * Pops a word from the stack.
8309 * NOTE: Do not inline this, as (*emu->emu_rdX) is already inline!
8312 pop_word(struct x86emu *emu)
8316 res = fetch_word(emu, emu->x86.R_SS, emu->x86.R_SP);
8323 * Pops a long from the stack.
8325 * NOTE: Do not inline this, as (*emu->emu_rdX) is already inline!
8328 pop_long(struct x86emu *emu)
8332 res = fetch_long(emu, emu->x86.R_SS, emu->x86.R_SP);