Try to fixup the mess of mdoc(7)/man(7) mixture as created by the merge.
[netbsd-mini2440.git] / common / lib / libx86emu / x86emu.c
blob79e0c9737c295baacdb53de7b7113e0bc3187a31
1 /* $NetBSD: x86emu.c,v 1.6 2009/02/03 19:14:52 joerg Exp $ */
3 /****************************************************************************
5 * Realmode X86 Emulator Library
7 * Copyright (C) 1996-1999 SciTech Software, Inc.
8 * Copyright (C) David Mosberger-Tang
9 * Copyright (C) 1999 Egbert Eich
10 * Copyright (C) 2007 Joerg Sonnenberger
12 * ========================================================================
14 * Permission to use, copy, modify, distribute, and sell this software and
15 * its documentation for any purpose is hereby granted without fee,
16 * provided that the above copyright notice appear in all copies and that
17 * both that copyright notice and this permission notice appear in
18 * supporting documentation, and that the name of the authors not be used
19 * in advertising or publicity pertaining to distribution of the software
20 * without specific, written prior permission. The authors makes no
21 * representations about the suitability of this software for any purpose.
22 * It is provided "as is" without express or implied warranty.
24 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
25 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
26 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
27 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
28 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
29 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
30 * PERFORMANCE OF THIS SOFTWARE.
32 ****************************************************************************/
34 #ifndef _KERNEL
35 #include <stdbool.h>
36 #endif
38 #include <x86emu/x86emu.h>
39 #include <x86emu/x86emu_regs.h>
41 static void x86emu_intr_raise (struct X86EMU *, uint8_t type);
43 static void X86EMU_exec_one_byte(struct X86EMU *);
44 static void X86EMU_exec_two_byte(struct X86EMU *);
46 static void fetch_decode_modrm (struct X86EMU *);
47 static uint8_t fetch_byte_imm (struct X86EMU *);
48 static uint16_t fetch_word_imm (struct X86EMU *);
49 static uint32_t fetch_long_imm (struct X86EMU *);
50 static uint8_t fetch_data_byte (struct X86EMU *, uint32_t offset);
51 static uint8_t fetch_byte (struct X86EMU *, uint segment, uint32_t offset);
52 static uint16_t fetch_data_word (struct X86EMU *, uint32_t offset);
53 static uint16_t fetch_word (struct X86EMU *, uint32_t segment, uint32_t offset);
54 static uint32_t fetch_data_long (struct X86EMU *, uint32_t offset);
55 static uint32_t fetch_long (struct X86EMU *, uint32_t segment, uint32_t offset);
56 static void store_data_byte (struct X86EMU *, uint32_t offset, uint8_t val);
57 static void store_byte (struct X86EMU *, uint32_t segment, uint32_t offset, uint8_t val);
58 static void store_data_word (struct X86EMU *, uint32_t offset, uint16_t val);
59 static void store_word (struct X86EMU *, uint32_t segment, uint32_t offset, uint16_t val);
60 static void store_data_long (struct X86EMU *, uint32_t offset, uint32_t val);
61 static void store_long (struct X86EMU *, uint32_t segment, uint32_t offset, uint32_t val);
62 static uint8_t* decode_rl_byte_register(struct X86EMU *);
63 static uint16_t* decode_rl_word_register(struct X86EMU *);
64 static uint32_t* decode_rl_long_register(struct X86EMU *);
65 static uint8_t* decode_rh_byte_register(struct X86EMU *);
66 static uint16_t* decode_rh_word_register(struct X86EMU *);
67 static uint32_t* decode_rh_long_register(struct X86EMU *);
68 static uint16_t* decode_rh_seg_register(struct X86EMU *);
69 static uint32_t decode_rl_address(struct X86EMU *);
71 static uint8_t decode_and_fetch_byte(struct X86EMU *);
72 static uint16_t decode_and_fetch_word(struct X86EMU *);
73 static uint32_t decode_and_fetch_long(struct X86EMU *);
75 static uint8_t decode_and_fetch_byte_imm8(struct X86EMU *, uint8_t *);
76 static uint16_t decode_and_fetch_word_imm8(struct X86EMU *, uint8_t *);
77 static uint32_t decode_and_fetch_long_imm8(struct X86EMU *, uint8_t *);
79 static uint16_t decode_and_fetch_word_disp(struct X86EMU *, int16_t);
80 static uint32_t decode_and_fetch_long_disp(struct X86EMU *, int16_t);
82 static void write_back_byte(struct X86EMU *, uint8_t);
83 static void write_back_word(struct X86EMU *, uint16_t);
84 static void write_back_long(struct X86EMU *, uint32_t);
86 static uint16_t aaa_word (struct X86EMU *, uint16_t d);
87 static uint16_t aas_word (struct X86EMU *, uint16_t d);
88 static uint16_t aad_word (struct X86EMU *, uint16_t d);
89 static uint16_t aam_word (struct X86EMU *, uint8_t d);
90 static uint8_t adc_byte (struct X86EMU *, uint8_t d, uint8_t s);
91 static uint16_t adc_word (struct X86EMU *, uint16_t d, uint16_t s);
92 static uint32_t adc_long (struct X86EMU *, uint32_t d, uint32_t s);
93 static uint8_t add_byte (struct X86EMU *, uint8_t d, uint8_t s);
94 static uint16_t add_word (struct X86EMU *, uint16_t d, uint16_t s);
95 static uint32_t add_long (struct X86EMU *, uint32_t d, uint32_t s);
96 static uint8_t and_byte (struct X86EMU *, uint8_t d, uint8_t s);
97 static uint16_t and_word (struct X86EMU *, uint16_t d, uint16_t s);
98 static uint32_t and_long (struct X86EMU *, uint32_t d, uint32_t s);
99 static uint8_t cmp_byte (struct X86EMU *, uint8_t d, uint8_t s);
100 static uint16_t cmp_word (struct X86EMU *, uint16_t d, uint16_t s);
101 static uint32_t cmp_long (struct X86EMU *, uint32_t d, uint32_t s);
102 static void cmp_byte_no_return (struct X86EMU *, uint8_t d, uint8_t s);
103 static void cmp_word_no_return (struct X86EMU *, uint16_t d, uint16_t s);
104 static void cmp_long_no_return (struct X86EMU *, uint32_t d, uint32_t s);
105 static uint8_t daa_byte (struct X86EMU *, uint8_t d);
106 static uint8_t das_byte (struct X86EMU *, uint8_t d);
107 static uint8_t dec_byte (struct X86EMU *, uint8_t d);
108 static uint16_t dec_word (struct X86EMU *, uint16_t d);
109 static uint32_t dec_long (struct X86EMU *, uint32_t d);
110 static uint8_t inc_byte (struct X86EMU *, uint8_t d);
111 static uint16_t inc_word (struct X86EMU *, uint16_t d);
112 static uint32_t inc_long (struct X86EMU *, uint32_t d);
113 static uint8_t or_byte (struct X86EMU *, uint8_t d, uint8_t s);
114 static uint16_t or_word (struct X86EMU *, uint16_t d, uint16_t s);
115 static uint32_t or_long (struct X86EMU *, uint32_t d, uint32_t s);
116 static uint8_t neg_byte (struct X86EMU *, uint8_t s);
117 static uint16_t neg_word (struct X86EMU *, uint16_t s);
118 static uint32_t neg_long (struct X86EMU *, uint32_t s);
119 static uint8_t rcl_byte (struct X86EMU *, uint8_t d, uint8_t s);
120 static uint16_t rcl_word (struct X86EMU *, uint16_t d, uint8_t s);
121 static uint32_t rcl_long (struct X86EMU *, uint32_t d, uint8_t s);
122 static uint8_t rcr_byte (struct X86EMU *, uint8_t d, uint8_t s);
123 static uint16_t rcr_word (struct X86EMU *, uint16_t d, uint8_t s);
124 static uint32_t rcr_long (struct X86EMU *, uint32_t d, uint8_t s);
125 static uint8_t rol_byte (struct X86EMU *, uint8_t d, uint8_t s);
126 static uint16_t rol_word (struct X86EMU *, uint16_t d, uint8_t s);
127 static uint32_t rol_long (struct X86EMU *, uint32_t d, uint8_t s);
128 static uint8_t ror_byte (struct X86EMU *, uint8_t d, uint8_t s);
129 static uint16_t ror_word (struct X86EMU *, uint16_t d, uint8_t s);
130 static uint32_t ror_long (struct X86EMU *, uint32_t d, uint8_t s);
131 static uint8_t shl_byte (struct X86EMU *, uint8_t d, uint8_t s);
132 static uint16_t shl_word (struct X86EMU *, uint16_t d, uint8_t s);
133 static uint32_t shl_long (struct X86EMU *, uint32_t d, uint8_t s);
134 static uint8_t shr_byte (struct X86EMU *, uint8_t d, uint8_t s);
135 static uint16_t shr_word (struct X86EMU *, uint16_t d, uint8_t s);
136 static uint32_t shr_long (struct X86EMU *, uint32_t d, uint8_t s);
137 static uint8_t sar_byte (struct X86EMU *, uint8_t d, uint8_t s);
138 static uint16_t sar_word (struct X86EMU *, uint16_t d, uint8_t s);
139 static uint32_t sar_long (struct X86EMU *, uint32_t d, uint8_t s);
140 static uint16_t shld_word (struct X86EMU *, uint16_t d, uint16_t fill, uint8_t s);
141 static uint32_t shld_long (struct X86EMU *, uint32_t d, uint32_t fill, uint8_t s);
142 static uint16_t shrd_word (struct X86EMU *, uint16_t d, uint16_t fill, uint8_t s);
143 static uint32_t shrd_long (struct X86EMU *, uint32_t d, uint32_t fill, uint8_t s);
144 static uint8_t sbb_byte (struct X86EMU *, uint8_t d, uint8_t s);
145 static uint16_t sbb_word (struct X86EMU *, uint16_t d, uint16_t s);
146 static uint32_t sbb_long (struct X86EMU *, uint32_t d, uint32_t s);
147 static uint8_t sub_byte (struct X86EMU *, uint8_t d, uint8_t s);
148 static uint16_t sub_word (struct X86EMU *, uint16_t d, uint16_t s);
149 static uint32_t sub_long (struct X86EMU *, uint32_t d, uint32_t s);
150 static void test_byte (struct X86EMU *, uint8_t d, uint8_t s);
151 static void test_word (struct X86EMU *, uint16_t d, uint16_t s);
152 static void test_long (struct X86EMU *, uint32_t d, uint32_t s);
153 static uint8_t xor_byte (struct X86EMU *, uint8_t d, uint8_t s);
154 static uint16_t xor_word (struct X86EMU *, uint16_t d, uint16_t s);
155 static uint32_t xor_long (struct X86EMU *, uint32_t d, uint32_t s);
156 static void imul_byte (struct X86EMU *, uint8_t s);
157 static void imul_word (struct X86EMU *, uint16_t s);
158 static void imul_long (struct X86EMU *, uint32_t s);
159 static void mul_byte (struct X86EMU *, uint8_t s);
160 static void mul_word (struct X86EMU *, uint16_t s);
161 static void mul_long (struct X86EMU *, uint32_t s);
162 static void idiv_byte (struct X86EMU *, uint8_t s);
163 static void idiv_word (struct X86EMU *, uint16_t s);
164 static void idiv_long (struct X86EMU *, uint32_t s);
165 static void div_byte (struct X86EMU *, uint8_t s);
166 static void div_word (struct X86EMU *, uint16_t s);
167 static void div_long (struct X86EMU *, uint32_t s);
168 static void ins (struct X86EMU *, int size);
169 static void outs (struct X86EMU *, int size);
170 static void push_word (struct X86EMU *, uint16_t w);
171 static void push_long (struct X86EMU *, uint32_t w);
172 static uint16_t pop_word (struct X86EMU *);
173 static uint32_t pop_long (struct X86EMU *);
175 /****************************************************************************
176 REMARKS:
177 Handles any pending asychronous interrupts.
178 ****************************************************************************/
179 static void
180 x86emu_intr_dispatch(struct X86EMU *emu, uint8_t intno)
182 if (emu->_X86EMU_intrTab[intno]) {
183 (*emu->_X86EMU_intrTab[intno]) (emu, intno);
184 } else {
185 push_word(emu, (uint16_t) emu->x86.R_FLG);
186 CLEAR_FLAG(F_IF);
187 CLEAR_FLAG(F_TF);
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);
195 static void
196 x86emu_intr_handle(struct X86EMU *emu)
198 uint8_t intno;
200 if (emu->x86.intr & INTR_SYNCH) {
201 intno = emu->x86.intno;
202 emu->x86.intr = 0;
203 x86emu_intr_dispatch(emu, intno);
206 /****************************************************************************
207 PARAMETERS:
208 intrnum - Interrupt number to raise
210 REMARKS:
211 Raise the specified interrupt to be handled before the execution of the
212 next instruction.
213 ****************************************************************************/
214 void
215 x86emu_intr_raise(struct X86EMU *emu, uint8_t intrnum)
217 emu->x86.intno = intrnum;
218 emu->x86.intr |= INTR_SYNCH;
220 /****************************************************************************
221 REMARKS:
222 Main execution loop for the emulator. We return from here when the system
223 halts, which is normally caused by a stack fault when we return from the
224 original real mode call.
225 ****************************************************************************/
226 void
227 X86EMU_exec(struct X86EMU *emu)
229 emu->x86.intr = 0;
231 #ifdef _KERNEL
232 if (setjmp(&emu->exec_state))
233 return;
234 #else
235 if (setjmp(emu->exec_state))
236 return;
237 #endif
239 for (;;) {
240 if (emu->x86.intr) {
241 if (((emu->x86.intr & INTR_SYNCH) && (emu->x86.intno == 0 || emu->x86.intno == 2)) ||
242 !ACCESS_FLAG(F_IF)) {
243 x86emu_intr_handle(emu);
246 if (emu->x86.R_CS == 0 && emu->x86.R_IP == 0)
247 return;
248 X86EMU_exec_one_byte(emu);
249 ++emu->cur_cycles;
253 void
254 X86EMU_exec_call(struct X86EMU *emu, uint16_t seg, uint16_t off)
256 push_word(emu, 0);
257 push_word(emu, 0);
258 emu->x86.R_CS = seg;
259 emu->x86.R_IP = off;
261 X86EMU_exec(emu);
264 void
265 X86EMU_exec_intr(struct X86EMU *emu, uint8_t intr)
267 push_word(emu, emu->x86.R_FLG);
268 CLEAR_FLAG(F_IF);
269 CLEAR_FLAG(F_TF);
270 push_word(emu, 0);
271 push_word(emu, 0);
272 emu->x86.R_CS = (*emu->emu_rdw)(emu, intr * 4 + 2);
273 emu->x86.R_IP = (*emu->emu_rdw)(emu, intr * 4);
274 emu->x86.intr = 0;
276 X86EMU_exec(emu);
278 /****************************************************************************
279 REMARKS:
280 Halts the system by setting the halted system flag.
281 ****************************************************************************/
282 void
283 X86EMU_halt_sys(struct X86EMU *emu)
285 #ifdef _KERNEL
286 longjmp(&emu->exec_state);
287 #else
288 longjmp(emu->exec_state, 1);
289 #endif
291 /****************************************************************************
292 PARAMETERS:
293 mod - Mod value from decoded byte
294 regh - Reg h value from decoded byte
295 regl - Reg l value from decoded byte
297 REMARKS:
298 Raise the specified interrupt to be handled before the execution of the
299 next instruction.
301 NOTE: Do not inline this function, as (*emu->emu_rdb) is already inline!
302 ****************************************************************************/
303 static void
304 fetch_decode_modrm(struct X86EMU *emu)
306 int fetched;
308 fetched = fetch_byte_imm(emu);
309 emu->cur_mod = (fetched >> 6) & 0x03;
310 emu->cur_rh = (fetched >> 3) & 0x07;
311 emu->cur_rl = (fetched >> 0) & 0x07;
313 /****************************************************************************
314 RETURNS:
315 Immediate byte value read from instruction queue
317 REMARKS:
318 This function returns the immediate byte from the instruction queue, and
319 moves the instruction pointer to the next value.
321 NOTE: Do not inline this function, as (*emu->emu_rdb) is already inline!
322 ****************************************************************************/
323 static uint8_t
324 fetch_byte_imm(struct X86EMU *emu)
326 uint8_t fetched;
328 fetched = fetch_byte(emu, emu->x86.R_CS, emu->x86.R_IP);
329 emu->x86.R_IP++;
330 return fetched;
332 /****************************************************************************
333 RETURNS:
334 Immediate word value read from instruction queue
336 REMARKS:
337 This function returns the immediate byte from the instruction queue, and
338 moves the instruction pointer to the next value.
340 NOTE: Do not inline this function, as (*emu->emu_rdw) is already inline!
341 ****************************************************************************/
342 static uint16_t
343 fetch_word_imm(struct X86EMU *emu)
345 uint16_t fetched;
347 fetched = fetch_word(emu, emu->x86.R_CS, emu->x86.R_IP);
348 emu->x86.R_IP += 2;
349 return fetched;
351 /****************************************************************************
352 RETURNS:
353 Immediate lone value read from instruction queue
355 REMARKS:
356 This function returns the immediate byte from the instruction queue, and
357 moves the instruction pointer to the next value.
359 NOTE: Do not inline this function, as (*emu->emu_rdw) is already inline!
360 ****************************************************************************/
361 static uint32_t
362 fetch_long_imm(struct X86EMU *emu)
364 uint32_t fetched;
366 fetched = fetch_long(emu, emu->x86.R_CS, emu->x86.R_IP);
367 emu->x86.R_IP += 4;
368 return fetched;
370 /****************************************************************************
371 RETURNS:
372 Value of the default data segment
374 REMARKS:
375 Inline function that returns the default data segment for the current
376 instruction.
378 On the x86 processor, the default segment is not always DS if there is
379 no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to
380 addresses relative to SS (ie: on the stack). So, at the minimum, all
381 decodings of addressing modes would have to set/clear a bit describing
382 whether the access is relative to DS or SS. That is the function of the
383 cpu-state-varible emu->x86.mode. There are several potential states:
385 repe prefix seen (handled elsewhere)
386 repne prefix seen (ditto)
388 cs segment override
389 ds segment override
390 es segment override
391 fs segment override
392 gs segment override
393 ss segment override
395 ds/ss select (in absense of override)
397 Each of the above 7 items are handled with a bit in the mode field.
398 ****************************************************************************/
399 static uint32_t
400 get_data_segment(struct X86EMU *emu)
402 switch (emu->x86.mode & SYSMODE_SEGMASK) {
403 case 0: /* default case: use ds register */
404 case SYSMODE_SEGOVR_DS:
405 case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS:
406 return emu->x86.R_DS;
407 case SYSMODE_SEG_DS_SS:/* non-overridden, use ss register */
408 return emu->x86.R_SS;
409 case SYSMODE_SEGOVR_CS:
410 case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS:
411 return emu->x86.R_CS;
412 case SYSMODE_SEGOVR_ES:
413 case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS:
414 return emu->x86.R_ES;
415 case SYSMODE_SEGOVR_FS:
416 case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS:
417 return emu->x86.R_FS;
418 case SYSMODE_SEGOVR_GS:
419 case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS:
420 return emu->x86.R_GS;
421 case SYSMODE_SEGOVR_SS:
422 case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS:
423 return emu->x86.R_SS;
425 X86EMU_halt_sys(emu);
427 /****************************************************************************
428 PARAMETERS:
429 offset - Offset to load data from
431 RETURNS:
432 Byte value read from the absolute memory location.
434 NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
435 ****************************************************************************/
436 static uint8_t
437 fetch_data_byte(struct X86EMU *emu, uint32_t offset)
439 return fetch_byte(emu, get_data_segment(emu), offset);
441 /****************************************************************************
442 PARAMETERS:
443 offset - Offset to load data from
445 RETURNS:
446 Word value read from the absolute memory location.
448 NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
449 ****************************************************************************/
450 static uint16_t
451 fetch_data_word(struct X86EMU *emu, uint32_t offset)
453 return fetch_word(emu, get_data_segment(emu), offset);
455 /****************************************************************************
456 PARAMETERS:
457 offset - Offset to load data from
459 RETURNS:
460 Long value read from the absolute memory location.
462 NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
463 ****************************************************************************/
464 static uint32_t
465 fetch_data_long(struct X86EMU *emu, uint32_t offset)
467 return fetch_long(emu, get_data_segment(emu), offset);
469 /****************************************************************************
470 PARAMETERS:
471 segment - Segment to load data from
472 offset - Offset to load data from
474 RETURNS:
475 Byte value read from the absolute memory location.
477 NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
478 ****************************************************************************/
479 static uint8_t
480 fetch_byte(struct X86EMU *emu, uint32_t segment, uint32_t offset)
482 return (*emu->emu_rdb) (emu, ((uint32_t) segment << 4) + offset);
484 /****************************************************************************
485 PARAMETERS:
486 segment - Segment to load data from
487 offset - Offset to load data from
489 RETURNS:
490 Word value read from the absolute memory location.
492 NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
493 ****************************************************************************/
494 static uint16_t
495 fetch_word(struct X86EMU *emu, uint32_t segment, uint32_t offset)
497 return (*emu->emu_rdw) (emu, ((uint32_t) segment << 4) + offset);
499 /****************************************************************************
500 PARAMETERS:
501 segment - Segment to load data from
502 offset - Offset to load data from
504 RETURNS:
505 Long value read from the absolute memory location.
507 NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
508 ****************************************************************************/
509 static uint32_t
510 fetch_long(struct X86EMU *emu, uint32_t segment, uint32_t offset)
512 return (*emu->emu_rdl) (emu, ((uint32_t) segment << 4) + offset);
514 /****************************************************************************
515 PARAMETERS:
516 offset - Offset to store data at
517 val - Value to store
519 REMARKS:
520 Writes a word value to an segmented memory location. The segment used is
521 the current 'default' segment, which may have been overridden.
523 NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
524 ****************************************************************************/
525 static void
526 store_data_byte(struct X86EMU *emu, uint32_t offset, uint8_t val)
528 store_byte(emu, get_data_segment(emu), offset, val);
530 /****************************************************************************
531 PARAMETERS:
532 offset - Offset to store data at
533 val - Value to store
535 REMARKS:
536 Writes a word value to an segmented memory location. The segment used is
537 the current 'default' segment, which may have been overridden.
539 NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
540 ****************************************************************************/
541 static void
542 store_data_word(struct X86EMU *emu, uint32_t offset, uint16_t val)
544 store_word(emu, get_data_segment(emu), offset, val);
546 /****************************************************************************
547 PARAMETERS:
548 offset - Offset to store data at
549 val - Value to store
551 REMARKS:
552 Writes a long value to an segmented memory location. The segment used is
553 the current 'default' segment, which may have been overridden.
555 NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
556 ****************************************************************************/
557 static void
558 store_data_long(struct X86EMU *emu, uint32_t offset, uint32_t val)
560 store_long(emu, get_data_segment(emu), offset, val);
562 /****************************************************************************
563 PARAMETERS:
564 segment - Segment to store data at
565 offset - Offset to store data at
566 val - Value to store
568 REMARKS:
569 Writes a byte value to an absolute memory location.
571 NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
572 ****************************************************************************/
573 static void
574 store_byte(struct X86EMU *emu, uint32_t segment, uint32_t offset, uint8_t val)
576 (*emu->emu_wrb) (emu, ((uint32_t) segment << 4) + offset, val);
578 /****************************************************************************
579 PARAMETERS:
580 segment - Segment to store data at
581 offset - Offset to store data at
582 val - Value to store
584 REMARKS:
585 Writes a word value to an absolute memory location.
587 NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
588 ****************************************************************************/
589 static void
590 store_word(struct X86EMU *emu, uint32_t segment, uint32_t offset, uint16_t val)
592 (*emu->emu_wrw) (emu, ((uint32_t) segment << 4) + offset, val);
594 /****************************************************************************
595 PARAMETERS:
596 segment - Segment to store data at
597 offset - Offset to store data at
598 val - Value to store
600 REMARKS:
601 Writes a long value to an absolute memory location.
603 NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
604 ****************************************************************************/
605 static void
606 store_long(struct X86EMU *emu, uint32_t segment, uint32_t offset, uint32_t val)
608 (*emu->emu_wrl) (emu, ((uint32_t) segment << 4) + offset, val);
610 /****************************************************************************
611 PARAMETERS:
612 reg - Register to decode
614 RETURNS:
615 Pointer to the appropriate register
617 REMARKS:
618 Return a pointer to the register given by the R/RM field of the
619 modrm byte, for byte operands. Also enables the decoding of instructions.
620 ****************************************************************************/
621 static uint8_t *
622 decode_rm_byte_register(struct X86EMU *emu, int reg)
624 switch (reg) {
625 case 0:
626 return &emu->x86.R_AL;
627 case 1:
628 return &emu->x86.R_CL;
629 case 2:
630 return &emu->x86.R_DL;
631 case 3:
632 return &emu->x86.R_BL;
633 case 4:
634 return &emu->x86.R_AH;
635 case 5:
636 return &emu->x86.R_CH;
637 case 6:
638 return &emu->x86.R_DH;
639 case 7:
640 return &emu->x86.R_BH;
641 default:
642 X86EMU_halt_sys(emu);
646 static uint8_t *
647 decode_rl_byte_register(struct X86EMU *emu)
649 return decode_rm_byte_register(emu, emu->cur_rl);
652 static uint8_t *
653 decode_rh_byte_register(struct X86EMU *emu)
655 return decode_rm_byte_register(emu, emu->cur_rh);
657 /****************************************************************************
658 PARAMETERS:
659 reg - Register to decode
661 RETURNS:
662 Pointer to the appropriate register
664 REMARKS:
665 Return a pointer to the register given by the R/RM field of the
666 modrm byte, for word operands. Also enables the decoding of instructions.
667 ****************************************************************************/
668 static uint16_t *
669 decode_rm_word_register(struct X86EMU *emu, int reg)
671 switch (reg) {
672 case 0:
673 return &emu->x86.R_AX;
674 case 1:
675 return &emu->x86.R_CX;
676 case 2:
677 return &emu->x86.R_DX;
678 case 3:
679 return &emu->x86.R_BX;
680 case 4:
681 return &emu->x86.R_SP;
682 case 5:
683 return &emu->x86.R_BP;
684 case 6:
685 return &emu->x86.R_SI;
686 case 7:
687 return &emu->x86.R_DI;
688 default:
689 X86EMU_halt_sys(emu);
693 static uint16_t *
694 decode_rl_word_register(struct X86EMU *emu)
696 return decode_rm_word_register(emu, emu->cur_rl);
699 static uint16_t *
700 decode_rh_word_register(struct X86EMU *emu)
702 return decode_rm_word_register(emu, emu->cur_rh);
704 /****************************************************************************
705 PARAMETERS:
706 reg - Register to decode
708 RETURNS:
709 Pointer to the appropriate register
711 REMARKS:
712 Return a pointer to the register given by the R/RM field of the
713 modrm byte, for dword operands. Also enables the decoding of instructions.
714 ****************************************************************************/
715 static uint32_t *
716 decode_rm_long_register(struct X86EMU *emu, int reg)
718 switch (reg) {
719 case 0:
720 return &emu->x86.R_EAX;
721 case 1:
722 return &emu->x86.R_ECX;
723 case 2:
724 return &emu->x86.R_EDX;
725 case 3:
726 return &emu->x86.R_EBX;
727 case 4:
728 return &emu->x86.R_ESP;
729 case 5:
730 return &emu->x86.R_EBP;
731 case 6:
732 return &emu->x86.R_ESI;
733 case 7:
734 return &emu->x86.R_EDI;
735 default:
736 X86EMU_halt_sys(emu);
740 static uint32_t *
741 decode_rl_long_register(struct X86EMU *emu)
743 return decode_rm_long_register(emu, emu->cur_rl);
746 static uint32_t *
747 decode_rh_long_register(struct X86EMU *emu)
749 return decode_rm_long_register(emu, emu->cur_rh);
752 /****************************************************************************
753 PARAMETERS:
754 reg - Register to decode
756 RETURNS:
757 Pointer to the appropriate register
759 REMARKS:
760 Return a pointer to the register given by the R/RM field of the
761 modrm byte, for word operands, modified from above for the weirdo
762 special case of segreg operands. Also enables the decoding of instructions.
763 ****************************************************************************/
764 static uint16_t *
765 decode_rh_seg_register(struct X86EMU *emu)
767 switch (emu->cur_rh) {
768 case 0:
769 return &emu->x86.R_ES;
770 case 1:
771 return &emu->x86.R_CS;
772 case 2:
773 return &emu->x86.R_SS;
774 case 3:
775 return &emu->x86.R_DS;
776 case 4:
777 return &emu->x86.R_FS;
778 case 5:
779 return &emu->x86.R_GS;
780 default:
781 X86EMU_halt_sys(emu);
786 * return offset from the SIB Byte
788 static uint32_t
789 decode_sib_address(struct X86EMU *emu, int sib, int mod)
791 uint32_t base = 0, i = 0, scale = 1;
793 switch (sib & 0x07) {
794 case 0:
795 base = emu->x86.R_EAX;
796 break;
797 case 1:
798 base = emu->x86.R_ECX;
799 break;
800 case 2:
801 base = emu->x86.R_EDX;
802 break;
803 case 3:
804 base = emu->x86.R_EBX;
805 break;
806 case 4:
807 base = emu->x86.R_ESP;
808 emu->x86.mode |= SYSMODE_SEG_DS_SS;
809 break;
810 case 5:
811 if (mod == 0) {
812 base = fetch_long_imm(emu);
813 } else {
814 base = emu->x86.R_EBP;
815 emu->x86.mode |= SYSMODE_SEG_DS_SS;
817 break;
818 case 6:
819 base = emu->x86.R_ESI;
820 break;
821 case 7:
822 base = emu->x86.R_EDI;
823 break;
825 switch ((sib >> 3) & 0x07) {
826 case 0:
827 i = emu->x86.R_EAX;
828 break;
829 case 1:
830 i = emu->x86.R_ECX;
831 break;
832 case 2:
833 i = emu->x86.R_EDX;
834 break;
835 case 3:
836 i = emu->x86.R_EBX;
837 break;
838 case 4:
839 i = 0;
840 break;
841 case 5:
842 i = emu->x86.R_EBP;
843 break;
844 case 6:
845 i = emu->x86.R_ESI;
846 break;
847 case 7:
848 i = emu->x86.R_EDI;
849 break;
851 scale = 1 << ((sib >> 6) & 0x03);
852 return base + (i * scale);
854 /****************************************************************************
855 PARAMETERS:
856 rm - RM value to decode
858 RETURNS:
859 Offset in memory for the address decoding
861 REMARKS:
862 Return the offset given by mod=00, mod=01 or mod=10 addressing.
863 Also enables the decoding of instructions.
864 ****************************************************************************/
865 static uint32_t
866 decode_rl_address(struct X86EMU *emu)
868 if (emu->x86.mode & SYSMODE_PREFIX_ADDR) {
869 uint32_t offset, sib;
870 /* 32-bit addressing */
871 switch (emu->cur_rl) {
872 case 0:
873 offset = emu->x86.R_EAX;
874 break;
875 case 1:
876 offset = emu->x86.R_ECX;
877 break;
878 case 2:
879 offset = emu->x86.R_EDX;
880 break;
881 case 3:
882 offset = emu->x86.R_EBX;
883 break;
884 case 4:
885 sib = fetch_byte_imm(emu);
886 offset = decode_sib_address(emu, sib, 0);
887 break;
888 case 5:
889 if (emu->cur_mod == 0) {
890 offset = fetch_long_imm(emu);
891 } else {
892 emu->x86.mode |= SYSMODE_SEG_DS_SS;
893 offset = emu->x86.R_EBP;
895 break;
896 case 6:
897 offset = emu->x86.R_ESI;
898 break;
899 case 7:
900 offset = emu->x86.R_EDI;
901 break;
902 default:
903 X86EMU_halt_sys(emu);
905 if (emu->cur_mod == 1)
906 offset += (int8_t)fetch_byte_imm(emu);
907 else if (emu->cur_mod == 2)
908 offset += fetch_long_imm(emu);
909 return offset;
910 } else {
911 uint16_t offset;
913 /* 16-bit addressing */
914 switch (emu->cur_rl) {
915 case 0:
916 offset = emu->x86.R_BX + emu->x86.R_SI;
917 break;
918 case 1:
919 offset = emu->x86.R_BX + emu->x86.R_DI;
920 break;
921 case 2:
922 emu->x86.mode |= SYSMODE_SEG_DS_SS;
923 offset = emu->x86.R_BP + emu->x86.R_SI;
924 break;
925 case 3:
926 emu->x86.mode |= SYSMODE_SEG_DS_SS;
927 offset = emu->x86.R_BP + emu->x86.R_DI;
928 break;
929 case 4:
930 offset = emu->x86.R_SI;
931 break;
932 case 5:
933 offset = emu->x86.R_DI;
934 break;
935 case 6:
936 if (emu->cur_mod == 0) {
937 offset = fetch_word_imm(emu);
938 } else {
939 emu->x86.mode |= SYSMODE_SEG_DS_SS;
940 offset = emu->x86.R_BP;
942 break;
943 case 7:
944 offset = emu->x86.R_BX;
945 break;
946 default:
947 X86EMU_halt_sys(emu);
949 if (emu->cur_mod == 1)
950 offset += (int8_t)fetch_byte_imm(emu);
951 else if (emu->cur_mod == 2)
952 offset += fetch_word_imm(emu);
953 return offset;
957 static uint8_t
958 decode_and_fetch_byte(struct X86EMU *emu)
960 if (emu->cur_mod != 3) {
961 emu->cur_offset = decode_rl_address(emu);
962 return fetch_data_byte(emu, emu->cur_offset);
963 } else {
964 return *decode_rl_byte_register(emu);
968 static uint16_t
969 decode_and_fetch_word_disp(struct X86EMU *emu, int16_t disp)
971 if (emu->cur_mod != 3) {
972 /* TODO: A20 gate emulation */
973 emu->cur_offset = decode_rl_address(emu) + disp;
974 if ((emu->x86.mode & SYSMODE_PREFIX_ADDR) == 0)
975 emu->cur_offset &= 0xffff;
976 return fetch_data_word(emu, emu->cur_offset);
977 } else {
978 return *decode_rl_word_register(emu);
982 static uint32_t
983 decode_and_fetch_long_disp(struct X86EMU *emu, int16_t disp)
985 if (emu->cur_mod != 3) {
986 /* TODO: A20 gate emulation */
987 emu->cur_offset = decode_rl_address(emu) + disp;
988 if ((emu->x86.mode & SYSMODE_PREFIX_ADDR) == 0)
989 emu->cur_offset &= 0xffff;
990 return fetch_data_long(emu, emu->cur_offset);
991 } else {
992 return *decode_rl_long_register(emu);
996 uint16_t
997 decode_and_fetch_word(struct X86EMU *emu)
999 return decode_and_fetch_word_disp(emu, 0);
1002 uint32_t
1003 decode_and_fetch_long(struct X86EMU *emu)
1005 return decode_and_fetch_long_disp(emu, 0);
1008 uint8_t
1009 decode_and_fetch_byte_imm8(struct X86EMU *emu, uint8_t *imm)
1011 if (emu->cur_mod != 3) {
1012 emu->cur_offset = decode_rl_address(emu);
1013 *imm = fetch_byte_imm(emu);
1014 return fetch_data_byte(emu, emu->cur_offset);
1015 } else {
1016 *imm = fetch_byte_imm(emu);
1017 return *decode_rl_byte_register(emu);
1021 static uint16_t
1022 decode_and_fetch_word_imm8(struct X86EMU *emu, uint8_t *imm)
1024 if (emu->cur_mod != 3) {
1025 emu->cur_offset = decode_rl_address(emu);
1026 *imm = fetch_byte_imm(emu);
1027 return fetch_data_word(emu, emu->cur_offset);
1028 } else {
1029 *imm = fetch_byte_imm(emu);
1030 return *decode_rl_word_register(emu);
1034 static uint32_t
1035 decode_and_fetch_long_imm8(struct X86EMU *emu, uint8_t *imm)
1037 if (emu->cur_mod != 3) {
1038 emu->cur_offset = decode_rl_address(emu);
1039 *imm = fetch_byte_imm(emu);
1040 return fetch_data_long(emu, emu->cur_offset);
1041 } else {
1042 *imm = fetch_byte_imm(emu);
1043 return *decode_rl_long_register(emu);
1047 static void
1048 write_back_byte(struct X86EMU *emu, uint8_t val)
1050 if (emu->cur_mod != 3)
1051 store_data_byte(emu, emu->cur_offset, val);
1052 else
1053 *decode_rl_byte_register(emu) = val;
1056 static void
1057 write_back_word(struct X86EMU *emu, uint16_t val)
1059 if (emu->cur_mod != 3)
1060 store_data_word(emu, emu->cur_offset, val);
1061 else
1062 *decode_rl_word_register(emu) = val;
1065 static void
1066 write_back_long(struct X86EMU *emu, uint32_t val)
1068 if (emu->cur_mod != 3)
1069 store_data_long(emu, emu->cur_offset, val);
1070 else
1071 *decode_rl_long_register(emu) = val;
1074 static void
1075 common_inc_word_long(struct X86EMU *emu, union X86EMU_register *reg)
1077 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1078 reg->I32_reg.e_reg = inc_long(emu, reg->I32_reg.e_reg);
1079 else
1080 reg->I16_reg.x_reg = inc_word(emu, reg->I16_reg.x_reg);
1083 static void
1084 common_dec_word_long(struct X86EMU *emu, union X86EMU_register *reg)
1086 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1087 reg->I32_reg.e_reg = dec_long(emu, reg->I32_reg.e_reg);
1088 else
1089 reg->I16_reg.x_reg = dec_word(emu, reg->I16_reg.x_reg);
1092 static void
1093 common_binop_byte_rm_r(struct X86EMU *emu, uint8_t (*binop)(struct X86EMU *, uint8_t, uint8_t))
1095 uint32_t destoffset;
1096 uint8_t *destreg, srcval;
1097 uint8_t destval;
1099 fetch_decode_modrm(emu);
1100 srcval = *decode_rh_byte_register(emu);
1101 if (emu->cur_mod != 3) {
1102 destoffset = decode_rl_address(emu);
1103 destval = fetch_data_byte(emu, destoffset);
1104 destval = (*binop)(emu, destval, srcval);
1105 store_data_byte(emu, destoffset, destval);
1106 } else {
1107 destreg = decode_rl_byte_register(emu);
1108 *destreg = (*binop)(emu, *destreg, srcval);
1112 static void
1113 common_binop_ns_byte_rm_r(struct X86EMU *emu, void (*binop)(struct X86EMU *, uint8_t, uint8_t))
1115 uint32_t destoffset;
1116 uint8_t destval, srcval;
1118 fetch_decode_modrm(emu);
1119 srcval = *decode_rh_byte_register(emu);
1120 if (emu->cur_mod != 3) {
1121 destoffset = decode_rl_address(emu);
1122 destval = fetch_data_byte(emu, destoffset);
1123 } else {
1124 destval = *decode_rl_byte_register(emu);
1126 (*binop)(emu, destval, srcval);
1129 static void
1130 common_binop_word_rm_r(struct X86EMU *emu, uint16_t (*binop)(struct X86EMU *, uint16_t, uint16_t))
1132 uint32_t destoffset;
1133 uint16_t destval, *destreg, srcval;
1135 fetch_decode_modrm(emu);
1136 srcval = *decode_rh_word_register(emu);
1137 if (emu->cur_mod != 3) {
1138 destoffset = decode_rl_address(emu);
1139 destval = fetch_data_word(emu, destoffset);
1140 destval = (*binop)(emu, destval, srcval);
1141 store_data_word(emu, destoffset, destval);
1142 } else {
1143 destreg = decode_rl_word_register(emu);
1144 *destreg = (*binop)(emu, *destreg, srcval);
1148 static void
1149 common_binop_byte_r_rm(struct X86EMU *emu, uint8_t (*binop)(struct X86EMU *, uint8_t, uint8_t))
1151 uint8_t *destreg, srcval;
1152 uint32_t srcoffset;
1154 fetch_decode_modrm(emu);
1155 destreg = decode_rh_byte_register(emu);
1156 if (emu->cur_mod != 3) {
1157 srcoffset = decode_rl_address(emu);
1158 srcval = fetch_data_byte(emu, srcoffset);
1159 } else {
1160 srcval = *decode_rl_byte_register(emu);
1162 *destreg = (*binop)(emu, *destreg, srcval);
1165 static void
1166 common_binop_long_rm_r(struct X86EMU *emu, uint32_t (*binop)(struct X86EMU *, uint32_t, uint32_t))
1168 uint32_t destoffset;
1169 uint32_t destval, *destreg, srcval;
1171 fetch_decode_modrm(emu);
1172 srcval = *decode_rh_long_register(emu);
1173 if (emu->cur_mod != 3) {
1174 destoffset = decode_rl_address(emu);
1175 destval = fetch_data_long(emu, destoffset);
1176 destval = (*binop)(emu, destval, srcval);
1177 store_data_long(emu, destoffset, destval);
1178 } else {
1179 destreg = decode_rl_long_register(emu);
1180 *destreg = (*binop)(emu, *destreg, srcval);
1184 static void
1185 common_binop_word_long_rm_r(struct X86EMU *emu,
1186 uint16_t (*binop16)(struct X86EMU *, uint16_t, uint16_t), uint32_t (*binop32)(struct X86EMU *, uint32_t, uint32_t))
1188 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1189 common_binop_long_rm_r(emu, binop32);
1190 else
1191 common_binop_word_rm_r(emu, binop16);
1194 static void
1195 common_binop_ns_word_rm_r(struct X86EMU *emu, void (*binop)(struct X86EMU *, uint16_t, uint16_t))
1197 uint32_t destoffset;
1198 uint16_t destval, srcval;
1200 fetch_decode_modrm(emu);
1201 srcval = *decode_rh_word_register(emu);
1202 if (emu->cur_mod != 3) {
1203 destoffset = decode_rl_address(emu);
1204 destval = fetch_data_word(emu, destoffset);
1205 } else {
1206 destval = *decode_rl_word_register(emu);
1208 (*binop)(emu, destval, srcval);
1212 static void
1213 common_binop_ns_long_rm_r(struct X86EMU *emu, void (*binop)(struct X86EMU *, uint32_t, uint32_t))
1215 uint32_t destoffset;
1216 uint32_t destval, srcval;
1218 fetch_decode_modrm(emu);
1219 srcval = *decode_rh_long_register(emu);
1220 if (emu->cur_mod != 3) {
1221 destoffset = decode_rl_address(emu);
1222 destval = fetch_data_long(emu, destoffset);
1223 } else {
1224 destval = *decode_rl_long_register(emu);
1226 (*binop)(emu, destval, srcval);
1229 static void
1230 common_binop_ns_word_long_rm_r(struct X86EMU *emu,
1231 void (*binop16)(struct X86EMU *, uint16_t, uint16_t), void (*binop32)(struct X86EMU *, uint32_t, uint32_t))
1233 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1234 common_binop_ns_long_rm_r(emu, binop32);
1235 else
1236 common_binop_ns_word_rm_r(emu, binop16);
1239 static void
1240 common_binop_long_r_rm(struct X86EMU *emu, uint32_t (*binop)(struct X86EMU *, uint32_t, uint32_t))
1242 uint32_t srcoffset;
1243 uint32_t *destreg, srcval;
1245 fetch_decode_modrm(emu);
1246 destreg = decode_rh_long_register(emu);
1247 if (emu->cur_mod != 3) {
1248 srcoffset = decode_rl_address(emu);
1249 srcval = fetch_data_long(emu, srcoffset);
1250 } else {
1251 srcval = *decode_rl_long_register(emu);
1253 *destreg = (*binop)(emu, *destreg, srcval);
1256 static void
1257 common_binop_word_r_rm(struct X86EMU *emu, uint16_t (*binop)(struct X86EMU *, uint16_t, uint16_t))
1259 uint32_t srcoffset;
1260 uint16_t *destreg, srcval;
1262 fetch_decode_modrm(emu);
1263 destreg = decode_rh_word_register(emu);
1264 if (emu->cur_mod != 3) {
1265 srcoffset = decode_rl_address(emu);
1266 srcval = fetch_data_word(emu, srcoffset);
1267 } else {
1268 srcval = *decode_rl_word_register(emu);
1270 *destreg = (*binop)(emu, *destreg, srcval);
1273 static void
1274 common_binop_word_long_r_rm(struct X86EMU *emu,
1275 uint16_t (*binop16)(struct X86EMU *, uint16_t, uint16_t), uint32_t (*binop32)(struct X86EMU *, uint32_t, uint32_t))
1277 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1278 common_binop_long_r_rm(emu, binop32);
1279 else
1280 common_binop_word_r_rm(emu, binop16);
1283 static void
1284 common_binop_byte_imm(struct X86EMU *emu, uint8_t (*binop)(struct X86EMU *, uint8_t, uint8_t))
1286 uint8_t srcval;
1288 srcval = fetch_byte_imm(emu);
1289 emu->x86.R_AL = (*binop)(emu, emu->x86.R_AL, srcval);
1292 static void
1293 common_binop_word_long_imm(struct X86EMU *emu,
1294 uint16_t (*binop16)(struct X86EMU *, uint16_t, uint16_t), uint32_t (*binop32)(struct X86EMU *, uint32_t, uint32_t))
1296 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1297 uint32_t srcval;
1299 srcval = fetch_long_imm(emu);
1300 emu->x86.R_EAX = (*binop32)(emu, emu->x86.R_EAX, srcval);
1301 } else {
1302 uint16_t srcval;
1304 srcval = fetch_word_imm(emu);
1305 emu->x86.R_AX = (*binop16)(emu, emu->x86.R_AX, srcval);
1309 static void
1310 common_push_word_long(struct X86EMU *emu, union X86EMU_register *reg)
1312 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1313 push_long(emu, reg->I32_reg.e_reg);
1314 else
1315 push_word(emu, reg->I16_reg.x_reg);
1318 static void
1319 common_pop_word_long(struct X86EMU *emu, union X86EMU_register *reg)
1321 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1322 reg->I32_reg.e_reg = pop_long(emu);
1323 else
1324 reg->I16_reg.x_reg = pop_word(emu);
1327 static void
1328 common_imul_long_IMM(struct X86EMU *emu, bool byte_imm)
1330 uint32_t srcoffset;
1331 uint32_t *destreg, srcval;
1332 int32_t imm;
1333 uint64_t res;
1335 fetch_decode_modrm(emu);
1336 destreg = decode_rh_long_register(emu);
1337 if (emu->cur_mod != 3) {
1338 srcoffset = decode_rl_address(emu);
1339 srcval = fetch_data_long(emu, srcoffset);
1340 } else {
1341 srcval = *decode_rl_long_register(emu);
1344 if (byte_imm)
1345 imm = (int8_t)fetch_byte_imm(emu);
1346 else
1347 imm = fetch_long_imm(emu);
1348 res = (int32_t)srcval * imm;
1350 if (res > 0xffffffff) {
1351 SET_FLAG(F_CF);
1352 SET_FLAG(F_OF);
1353 } else {
1354 CLEAR_FLAG(F_CF);
1355 CLEAR_FLAG(F_OF);
1357 *destreg = (uint32_t)res;
1360 static void
1361 common_imul_word_IMM(struct X86EMU *emu, bool byte_imm)
1363 uint32_t srcoffset;
1364 uint16_t *destreg, srcval;
1365 int16_t imm;
1366 uint32_t res;
1368 fetch_decode_modrm(emu);
1369 destreg = decode_rh_word_register(emu);
1370 if (emu->cur_mod != 3) {
1371 srcoffset = decode_rl_address(emu);
1372 srcval = fetch_data_word(emu, srcoffset);
1373 } else {
1374 srcval = *decode_rl_word_register(emu);
1377 if (byte_imm)
1378 imm = (int8_t)fetch_byte_imm(emu);
1379 else
1380 imm = fetch_word_imm(emu);
1381 res = (int16_t)srcval * imm;
1383 if (res > 0xffff) {
1384 SET_FLAG(F_CF);
1385 SET_FLAG(F_OF);
1386 } else {
1387 CLEAR_FLAG(F_CF);
1388 CLEAR_FLAG(F_OF);
1390 *destreg = (uint16_t) res;
1393 static void
1394 common_imul_imm(struct X86EMU *emu, bool byte_imm)
1396 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1397 common_imul_long_IMM(emu, byte_imm);
1398 else
1399 common_imul_word_IMM(emu, byte_imm);
1402 static void
1403 common_jmp_near(struct X86EMU *emu, bool cond)
1405 int8_t offset;
1406 uint16_t target;
1408 offset = (int8_t) fetch_byte_imm(emu);
1409 target = (uint16_t) (emu->x86.R_IP + (int16_t) offset);
1410 if (cond)
1411 emu->x86.R_IP = target;
1414 static void
1415 common_load_far_pointer(struct X86EMU *emu, uint16_t *seg)
1417 uint16_t *dstreg;
1418 uint32_t srcoffset;
1420 fetch_decode_modrm(emu);
1421 if (emu->cur_mod == 3)
1422 X86EMU_halt_sys(emu);
1424 dstreg = decode_rh_word_register(emu);
1425 srcoffset = decode_rl_address(emu);
1426 *dstreg = fetch_data_word(emu, srcoffset);
1427 *seg = fetch_data_word(emu, srcoffset + 2);
1430 /*----------------------------- Implementation ----------------------------*/
1431 /****************************************************************************
1432 REMARKS:
1433 Handles opcode 0x3a
1434 ****************************************************************************/
1435 static void
1436 x86emuOp_cmp_byte_R_RM(struct X86EMU *emu)
1438 uint8_t *destreg, srcval;
1440 fetch_decode_modrm(emu);
1441 destreg = decode_rh_byte_register(emu);
1442 srcval = decode_and_fetch_byte(emu);
1443 cmp_byte(emu, *destreg, srcval);
1445 /****************************************************************************
1446 REMARKS:
1447 Handles opcode 0x3b
1448 ****************************************************************************/
1449 static void
1450 x86emuOp32_cmp_word_R_RM(struct X86EMU *emu)
1452 uint32_t srcval, *destreg;
1454 fetch_decode_modrm(emu);
1455 destreg = decode_rh_long_register(emu);
1456 srcval = decode_and_fetch_long(emu);
1457 cmp_long(emu, *destreg, srcval);
1460 static void
1461 x86emuOp16_cmp_word_R_RM(struct X86EMU *emu)
1463 uint16_t srcval, *destreg;
1465 fetch_decode_modrm(emu);
1466 destreg = decode_rh_word_register(emu);
1467 srcval = decode_and_fetch_word(emu);
1468 cmp_word(emu, *destreg, srcval);
1471 static void
1472 x86emuOp_cmp_word_R_RM(struct X86EMU *emu)
1474 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1475 x86emuOp32_cmp_word_R_RM(emu);
1476 else
1477 x86emuOp16_cmp_word_R_RM(emu);
1479 /****************************************************************************
1480 REMARKS:
1481 Handles opcode 0x3c
1482 ****************************************************************************/
1483 static void
1484 x86emuOp_cmp_byte_AL_IMM(struct X86EMU *emu)
1486 uint8_t srcval;
1488 srcval = fetch_byte_imm(emu);
1489 cmp_byte(emu, emu->x86.R_AL, srcval);
1491 /****************************************************************************
1492 REMARKS:
1493 Handles opcode 0x3d
1494 ****************************************************************************/
1495 static void
1496 x86emuOp32_cmp_word_AX_IMM(struct X86EMU *emu)
1498 uint32_t srcval;
1500 srcval = fetch_long_imm(emu);
1501 cmp_long(emu, emu->x86.R_EAX, srcval);
1504 static void
1505 x86emuOp16_cmp_word_AX_IMM(struct X86EMU *emu)
1507 uint16_t srcval;
1509 srcval = fetch_word_imm(emu);
1510 cmp_word(emu, emu->x86.R_AX, srcval);
1513 static void
1514 x86emuOp_cmp_word_AX_IMM(struct X86EMU *emu)
1516 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1517 x86emuOp32_cmp_word_AX_IMM(emu);
1518 else
1519 x86emuOp16_cmp_word_AX_IMM(emu);
1521 /****************************************************************************
1522 REMARKS:
1523 Handles opcode 0x60
1524 ****************************************************************************/
1525 static void
1526 x86emuOp_push_all(struct X86EMU *emu)
1528 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1529 uint32_t old_sp = emu->x86.R_ESP;
1531 push_long(emu, emu->x86.R_EAX);
1532 push_long(emu, emu->x86.R_ECX);
1533 push_long(emu, emu->x86.R_EDX);
1534 push_long(emu, emu->x86.R_EBX);
1535 push_long(emu, old_sp);
1536 push_long(emu, emu->x86.R_EBP);
1537 push_long(emu, emu->x86.R_ESI);
1538 push_long(emu, emu->x86.R_EDI);
1539 } else {
1540 uint16_t old_sp = emu->x86.R_SP;
1542 push_word(emu, emu->x86.R_AX);
1543 push_word(emu, emu->x86.R_CX);
1544 push_word(emu, emu->x86.R_DX);
1545 push_word(emu, emu->x86.R_BX);
1546 push_word(emu, old_sp);
1547 push_word(emu, emu->x86.R_BP);
1548 push_word(emu, emu->x86.R_SI);
1549 push_word(emu, emu->x86.R_DI);
1552 /****************************************************************************
1553 REMARKS:
1554 Handles opcode 0x61
1555 ****************************************************************************/
1556 static void
1557 x86emuOp_pop_all(struct X86EMU *emu)
1559 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1560 emu->x86.R_EDI = pop_long(emu);
1561 emu->x86.R_ESI = pop_long(emu);
1562 emu->x86.R_EBP = pop_long(emu);
1563 emu->x86.R_ESP += 4; /* skip ESP */
1564 emu->x86.R_EBX = pop_long(emu);
1565 emu->x86.R_EDX = pop_long(emu);
1566 emu->x86.R_ECX = pop_long(emu);
1567 emu->x86.R_EAX = pop_long(emu);
1568 } else {
1569 emu->x86.R_DI = pop_word(emu);
1570 emu->x86.R_SI = pop_word(emu);
1571 emu->x86.R_BP = pop_word(emu);
1572 emu->x86.R_SP += 2;/* skip SP */
1573 emu->x86.R_BX = pop_word(emu);
1574 emu->x86.R_DX = pop_word(emu);
1575 emu->x86.R_CX = pop_word(emu);
1576 emu->x86.R_AX = pop_word(emu);
1579 /*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */
1580 /*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */
1582 /****************************************************************************
1583 REMARKS:
1584 Handles opcode 0x68
1585 ****************************************************************************/
1586 static void
1587 x86emuOp_push_word_IMM(struct X86EMU *emu)
1589 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1590 uint32_t imm;
1592 imm = fetch_long_imm(emu);
1593 push_long(emu, imm);
1594 } else {
1595 uint16_t imm;
1597 imm = fetch_word_imm(emu);
1598 push_word(emu, imm);
1601 /****************************************************************************
1602 REMARKS:
1603 Handles opcode 0x6a
1604 ****************************************************************************/
1605 static void
1606 x86emuOp_push_byte_IMM(struct X86EMU *emu)
1608 int16_t imm;
1610 imm = (int8_t) fetch_byte_imm(emu);
1611 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1612 push_long(emu, (int32_t) imm);
1613 } else {
1614 push_word(emu, imm);
1617 /****************************************************************************
1618 REMARKS:
1619 Handles opcode 0x6c
1620 ****************************************************************************/
1621 /****************************************************************************
1622 REMARKS:
1623 Handles opcode 0x6d
1624 ****************************************************************************/
1625 static void
1626 x86emuOp_ins_word(struct X86EMU *emu)
1628 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1629 ins(emu, 4);
1630 } else {
1631 ins(emu, 2);
1634 /****************************************************************************
1635 REMARKS:
1636 Handles opcode 0x6f
1637 ****************************************************************************/
1638 static void
1639 x86emuOp_outs_word(struct X86EMU *emu)
1641 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1642 outs(emu, 4);
1643 } else {
1644 outs(emu, 2);
1647 /****************************************************************************
1648 REMARKS:
1649 Handles opcode 0x7c
1650 ****************************************************************************/
1651 static void
1652 x86emuOp_jump_near_L(struct X86EMU *emu)
1654 bool sf, of;
1656 sf = ACCESS_FLAG(F_SF) != 0;
1657 of = ACCESS_FLAG(F_OF) != 0;
1659 common_jmp_near(emu, sf != of);
1661 /****************************************************************************
1662 REMARKS:
1663 Handles opcode 0x7d
1664 ****************************************************************************/
1665 static void
1666 x86emuOp_jump_near_NL(struct X86EMU *emu)
1668 bool sf, of;
1670 sf = ACCESS_FLAG(F_SF) != 0;
1671 of = ACCESS_FLAG(F_OF) != 0;
1673 common_jmp_near(emu, sf == of);
1675 /****************************************************************************
1676 REMARKS:
1677 Handles opcode 0x7e
1678 ****************************************************************************/
1679 static void
1680 x86emuOp_jump_near_LE(struct X86EMU *emu)
1682 bool sf, of;
1684 sf = ACCESS_FLAG(F_SF) != 0;
1685 of = ACCESS_FLAG(F_OF) != 0;
1687 common_jmp_near(emu, sf != of || ACCESS_FLAG(F_ZF));
1689 /****************************************************************************
1690 REMARKS:
1691 Handles opcode 0x7f
1692 ****************************************************************************/
1693 static void
1694 x86emuOp_jump_near_NLE(struct X86EMU *emu)
1696 bool sf, of;
1698 sf = ACCESS_FLAG(F_SF) != 0;
1699 of = ACCESS_FLAG(F_OF) != 0;
1701 common_jmp_near(emu, sf == of && !ACCESS_FLAG(F_ZF));
1704 static
1705 uint8_t(*const opc80_byte_operation[]) (struct X86EMU *, uint8_t d, uint8_t s) =
1707 add_byte, /* 00 */
1708 or_byte, /* 01 */
1709 adc_byte, /* 02 */
1710 sbb_byte, /* 03 */
1711 and_byte, /* 04 */
1712 sub_byte, /* 05 */
1713 xor_byte, /* 06 */
1714 cmp_byte, /* 07 */
1716 /****************************************************************************
1717 REMARKS:
1718 Handles opcode 0x80
1719 ****************************************************************************/
1720 static void
1721 x86emuOp_opc80_byte_RM_IMM(struct X86EMU *emu)
1723 uint8_t imm, destval;
1726 * Weirdo special case instruction format. Part of the opcode
1727 * held below in "RH". Doubly nested case would result, except
1728 * that the decoded instruction
1730 fetch_decode_modrm(emu);
1731 destval = decode_and_fetch_byte(emu);
1732 imm = fetch_byte_imm(emu);
1733 destval = (*opc80_byte_operation[emu->cur_rh]) (emu, destval, imm);
1734 if (emu->cur_rh != 7)
1735 write_back_byte(emu, destval);
1738 static
1739 uint16_t(* const opc81_word_operation[]) (struct X86EMU *, uint16_t d, uint16_t s) =
1741 add_word, /* 00 */
1742 or_word, /* 01 */
1743 adc_word, /* 02 */
1744 sbb_word, /* 03 */
1745 and_word, /* 04 */
1746 sub_word, /* 05 */
1747 xor_word, /* 06 */
1748 cmp_word, /* 07 */
1751 static
1752 uint32_t(* const opc81_long_operation[]) (struct X86EMU *, uint32_t d, uint32_t s) =
1754 add_long, /* 00 */
1755 or_long, /* 01 */
1756 adc_long, /* 02 */
1757 sbb_long, /* 03 */
1758 and_long, /* 04 */
1759 sub_long, /* 05 */
1760 xor_long, /* 06 */
1761 cmp_long, /* 07 */
1763 /****************************************************************************
1764 REMARKS:
1765 Handles opcode 0x81
1766 ****************************************************************************/
1767 static void
1768 x86emuOp32_opc81_word_RM_IMM(struct X86EMU *emu)
1770 uint32_t destval, imm;
1773 * Weirdo special case instruction format. Part of the opcode
1774 * held below in "RH". Doubly nested case would result, except
1775 * that the decoded instruction
1777 fetch_decode_modrm(emu);
1778 destval = decode_and_fetch_long(emu);
1779 imm = fetch_long_imm(emu);
1780 destval = (*opc81_long_operation[emu->cur_rh]) (emu, destval, imm);
1781 if (emu->cur_rh != 7)
1782 write_back_long(emu, destval);
1785 static void
1786 x86emuOp16_opc81_word_RM_IMM(struct X86EMU *emu)
1788 uint16_t destval, imm;
1791 * Weirdo special case instruction format. Part of the opcode
1792 * held below in "RH". Doubly nested case would result, except
1793 * that the decoded instruction
1795 fetch_decode_modrm(emu);
1796 destval = decode_and_fetch_word(emu);
1797 imm = fetch_word_imm(emu);
1798 destval = (*opc81_word_operation[emu->cur_rh]) (emu, destval, imm);
1799 if (emu->cur_rh != 7)
1800 write_back_word(emu, destval);
1803 static void
1804 x86emuOp_opc81_word_RM_IMM(struct X86EMU *emu)
1806 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1807 x86emuOp32_opc81_word_RM_IMM(emu);
1808 else
1809 x86emuOp16_opc81_word_RM_IMM(emu);
1812 static
1813 uint8_t(* const opc82_byte_operation[]) (struct X86EMU *, uint8_t s, uint8_t d) =
1815 add_byte, /* 00 */
1816 or_byte, /* 01 *//* YYY UNUSED ???? */
1817 adc_byte, /* 02 */
1818 sbb_byte, /* 03 */
1819 and_byte, /* 04 *//* YYY UNUSED ???? */
1820 sub_byte, /* 05 */
1821 xor_byte, /* 06 *//* YYY UNUSED ???? */
1822 cmp_byte, /* 07 */
1824 /****************************************************************************
1825 REMARKS:
1826 Handles opcode 0x82
1827 ****************************************************************************/
1828 static void
1829 x86emuOp_opc82_byte_RM_IMM(struct X86EMU *emu)
1831 uint8_t imm, destval;
1834 * Weirdo special case instruction format. Part of the opcode
1835 * held below in "RH". Doubly nested case would result, except
1836 * that the decoded instruction Similar to opcode 81, except that
1837 * the immediate byte is sign extended to a word length.
1839 fetch_decode_modrm(emu);
1840 destval = decode_and_fetch_byte(emu);
1841 imm = fetch_byte_imm(emu);
1842 destval = (*opc82_byte_operation[emu->cur_rh]) (emu, destval, imm);
1843 if (emu->cur_rh != 7)
1844 write_back_byte(emu, destval);
1847 static
1848 uint16_t(* const opc83_word_operation[]) (struct X86EMU *, uint16_t s, uint16_t d) =
1850 add_word, /* 00 */
1851 or_word, /* 01 *//* YYY UNUSED ???? */
1852 adc_word, /* 02 */
1853 sbb_word, /* 03 */
1854 and_word, /* 04 *//* YYY UNUSED ???? */
1855 sub_word, /* 05 */
1856 xor_word, /* 06 *//* YYY UNUSED ???? */
1857 cmp_word, /* 07 */
1860 static
1861 uint32_t(* const opc83_long_operation[]) (struct X86EMU *, uint32_t s, uint32_t d) =
1863 add_long, /* 00 */
1864 or_long, /* 01 *//* YYY UNUSED ???? */
1865 adc_long, /* 02 */
1866 sbb_long, /* 03 */
1867 and_long, /* 04 *//* YYY UNUSED ???? */
1868 sub_long, /* 05 */
1869 xor_long, /* 06 *//* YYY UNUSED ???? */
1870 cmp_long, /* 07 */
1872 /****************************************************************************
1873 REMARKS:
1874 Handles opcode 0x83
1875 ****************************************************************************/
1876 static void
1877 x86emuOp32_opc83_word_RM_IMM(struct X86EMU *emu)
1879 uint32_t destval, imm;
1881 fetch_decode_modrm(emu);
1882 destval = decode_and_fetch_long(emu);
1883 imm = (int8_t) fetch_byte_imm(emu);
1884 destval = (*opc83_long_operation[emu->cur_rh]) (emu, destval, imm);
1885 if (emu->cur_rh != 7)
1886 write_back_long(emu, destval);
1889 static void
1890 x86emuOp16_opc83_word_RM_IMM(struct X86EMU *emu)
1892 uint16_t destval, imm;
1894 fetch_decode_modrm(emu);
1895 destval = decode_and_fetch_word(emu);
1896 imm = (int8_t) fetch_byte_imm(emu);
1897 destval = (*opc83_word_operation[emu->cur_rh]) (emu, destval, imm);
1898 if (emu->cur_rh != 7)
1899 write_back_word(emu, destval);
1902 static void
1903 x86emuOp_opc83_word_RM_IMM(struct X86EMU *emu)
1905 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1906 x86emuOp32_opc83_word_RM_IMM(emu);
1907 else
1908 x86emuOp16_opc83_word_RM_IMM(emu);
1910 /****************************************************************************
1911 REMARKS:
1912 Handles opcode 0x86
1913 ****************************************************************************/
1914 static void
1915 x86emuOp_xchg_byte_RM_R(struct X86EMU *emu)
1917 uint8_t *srcreg, destval, tmp;
1919 fetch_decode_modrm(emu);
1920 destval = decode_and_fetch_byte(emu);
1921 srcreg = decode_rh_byte_register(emu);
1922 tmp = destval;
1923 destval = *srcreg;
1924 *srcreg = tmp;
1925 write_back_byte(emu, destval);
1927 /****************************************************************************
1928 REMARKS:
1929 Handles opcode 0x87
1930 ****************************************************************************/
1931 static void
1932 x86emuOp32_xchg_word_RM_R(struct X86EMU *emu)
1934 uint32_t *srcreg, destval, tmp;
1936 fetch_decode_modrm(emu);
1937 destval = decode_and_fetch_long(emu);
1938 srcreg = decode_rh_long_register(emu);
1939 tmp = destval;
1940 destval = *srcreg;
1941 *srcreg = tmp;
1942 write_back_long(emu, destval);
1945 static void
1946 x86emuOp16_xchg_word_RM_R(struct X86EMU *emu)
1948 uint16_t *srcreg, destval, tmp;
1950 fetch_decode_modrm(emu);
1951 destval = decode_and_fetch_word(emu);
1952 srcreg = decode_rh_word_register(emu);
1953 tmp = destval;
1954 destval = *srcreg;
1955 *srcreg = tmp;
1956 write_back_word(emu, destval);
1959 static void
1960 x86emuOp_xchg_word_RM_R(struct X86EMU *emu)
1962 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1963 x86emuOp32_xchg_word_RM_R(emu);
1964 else
1965 x86emuOp16_xchg_word_RM_R(emu);
1967 /****************************************************************************
1968 REMARKS:
1969 Handles opcode 0x88
1970 ****************************************************************************/
1971 static void
1972 x86emuOp_mov_byte_RM_R(struct X86EMU *emu)
1974 uint8_t *destreg, *srcreg;
1975 uint32_t destoffset;
1977 fetch_decode_modrm(emu);
1978 srcreg = decode_rh_byte_register(emu);
1979 if (emu->cur_mod != 3) {
1980 destoffset = decode_rl_address(emu);
1981 store_data_byte(emu, destoffset, *srcreg);
1982 } else {
1983 destreg = decode_rl_byte_register(emu);
1984 *destreg = *srcreg;
1987 /****************************************************************************
1988 REMARKS:
1989 Handles opcode 0x89
1990 ****************************************************************************/
1991 static void
1992 x86emuOp32_mov_word_RM_R(struct X86EMU *emu)
1994 uint32_t destoffset;
1995 uint32_t *destreg, srcval;
1997 fetch_decode_modrm(emu);
1998 srcval = *decode_rh_long_register(emu);
1999 if (emu->cur_mod != 3) {
2000 destoffset = decode_rl_address(emu);
2001 store_data_long(emu, destoffset, srcval);
2002 } else {
2003 destreg = decode_rl_long_register(emu);
2004 *destreg = srcval;
2008 static void
2009 x86emuOp16_mov_word_RM_R(struct X86EMU *emu)
2011 uint32_t destoffset;
2012 uint16_t *destreg, srcval;
2014 fetch_decode_modrm(emu);
2015 srcval = *decode_rh_word_register(emu);
2016 if (emu->cur_mod != 3) {
2017 destoffset = decode_rl_address(emu);
2018 store_data_word(emu, destoffset, srcval);
2019 } else {
2020 destreg = decode_rl_word_register(emu);
2021 *destreg = srcval;
2025 static void
2026 x86emuOp_mov_word_RM_R(struct X86EMU *emu)
2028 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2029 x86emuOp32_mov_word_RM_R(emu);
2030 else
2031 x86emuOp16_mov_word_RM_R(emu);
2033 /****************************************************************************
2034 REMARKS:
2035 Handles opcode 0x8a
2036 ****************************************************************************/
2037 static void
2038 x86emuOp_mov_byte_R_RM(struct X86EMU *emu)
2040 uint8_t *destreg;
2042 fetch_decode_modrm(emu);
2043 destreg = decode_rh_byte_register(emu);
2044 *destreg = decode_and_fetch_byte(emu);
2046 /****************************************************************************
2047 REMARKS:
2048 Handles opcode 0x8b
2049 ****************************************************************************/
2050 static void
2051 x86emuOp_mov_word_R_RM(struct X86EMU *emu)
2053 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2054 uint32_t *destreg;
2056 fetch_decode_modrm(emu);
2057 destreg = decode_rh_long_register(emu);
2058 *destreg = decode_and_fetch_long(emu);
2059 } else {
2060 uint16_t *destreg;
2062 fetch_decode_modrm(emu);
2063 destreg = decode_rh_word_register(emu);
2064 *destreg = decode_and_fetch_word(emu);
2067 /****************************************************************************
2068 REMARKS:
2069 Handles opcode 0x8c
2070 ****************************************************************************/
2071 static void
2072 x86emuOp_mov_word_RM_SR(struct X86EMU *emu)
2074 uint16_t *destreg, srcval;
2075 uint32_t destoffset;
2077 fetch_decode_modrm(emu);
2078 srcval = *decode_rh_seg_register(emu);
2079 if (emu->cur_mod != 3) {
2080 destoffset = decode_rl_address(emu);
2081 store_data_word(emu, destoffset, srcval);
2082 } else {
2083 destreg = decode_rl_word_register(emu);
2084 *destreg = srcval;
2087 /****************************************************************************
2088 REMARKS:
2089 Handles opcode 0x8d
2090 ****************************************************************************/
2091 static void
2092 x86emuOp_lea_word_R_M(struct X86EMU *emu)
2094 uint16_t *srcreg;
2095 uint32_t destoffset;
2098 * TODO: Need to handle address size prefix!
2100 * lea eax,[eax+ebx*2] ??
2102 fetch_decode_modrm(emu);
2103 if (emu->cur_mod == 3)
2104 X86EMU_halt_sys(emu);
2106 srcreg = decode_rh_word_register(emu);
2107 destoffset = decode_rl_address(emu);
2108 *srcreg = (uint16_t) destoffset;
2110 /****************************************************************************
2111 REMARKS:
2112 Handles opcode 0x8e
2113 ****************************************************************************/
2114 static void
2115 x86emuOp_mov_word_SR_RM(struct X86EMU *emu)
2117 uint16_t *destreg;
2119 fetch_decode_modrm(emu);
2120 destreg = decode_rh_seg_register(emu);
2121 *destreg = decode_and_fetch_word(emu);
2123 * Clean up, and reset all the R_xSP pointers to the correct
2124 * locations. This is about 3x too much overhead (doing all the
2125 * segreg ptrs when only one is needed, but this instruction
2126 * *cannot* be that common, and this isn't too much work anyway.
2129 /****************************************************************************
2130 REMARKS:
2131 Handles opcode 0x8f
2132 ****************************************************************************/
2133 static void
2134 x86emuOp32_pop_RM(struct X86EMU *emu)
2136 uint32_t destoffset;
2137 uint32_t destval, *destreg;
2139 fetch_decode_modrm(emu);
2140 if (emu->cur_mod != 3) {
2141 destoffset = decode_rl_address(emu);
2142 destval = pop_long(emu);
2143 store_data_long(emu, destoffset, destval);
2144 } else {
2145 destreg = decode_rl_long_register(emu);
2146 *destreg = pop_long(emu);
2150 static void
2151 x86emuOp16_pop_RM(struct X86EMU *emu)
2153 uint32_t destoffset;
2154 uint16_t destval, *destreg;
2156 fetch_decode_modrm(emu);
2157 if (emu->cur_mod != 3) {
2158 destoffset = decode_rl_address(emu);
2159 destval = pop_word(emu);
2160 store_data_word(emu, destoffset, destval);
2161 } else {
2162 destreg = decode_rl_word_register(emu);
2163 *destreg = pop_word(emu);
2167 static void
2168 x86emuOp_pop_RM(struct X86EMU *emu)
2170 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2171 x86emuOp32_pop_RM(emu);
2172 else
2173 x86emuOp16_pop_RM(emu);
2175 /****************************************************************************
2176 REMARKS:
2177 Handles opcode 0x91
2178 ****************************************************************************/
2179 static void
2180 x86emuOp_xchg_word_AX_CX(struct X86EMU *emu)
2182 uint32_t tmp;
2184 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2185 tmp = emu->x86.R_EAX;
2186 emu->x86.R_EAX = emu->x86.R_ECX;
2187 emu->x86.R_ECX = tmp;
2188 } else {
2189 tmp = emu->x86.R_AX;
2190 emu->x86.R_AX = emu->x86.R_CX;
2191 emu->x86.R_CX = (uint16_t) tmp;
2194 /****************************************************************************
2195 REMARKS:
2196 Handles opcode 0x92
2197 ****************************************************************************/
2198 static void
2199 x86emuOp_xchg_word_AX_DX(struct X86EMU *emu)
2201 uint32_t tmp;
2203 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2204 tmp = emu->x86.R_EAX;
2205 emu->x86.R_EAX = emu->x86.R_EDX;
2206 emu->x86.R_EDX = tmp;
2207 } else {
2208 tmp = emu->x86.R_AX;
2209 emu->x86.R_AX = emu->x86.R_DX;
2210 emu->x86.R_DX = (uint16_t) tmp;
2213 /****************************************************************************
2214 REMARKS:
2215 Handles opcode 0x93
2216 ****************************************************************************/
2217 static void
2218 x86emuOp_xchg_word_AX_BX(struct X86EMU *emu)
2220 uint32_t tmp;
2222 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2223 tmp = emu->x86.R_EAX;
2224 emu->x86.R_EAX = emu->x86.R_EBX;
2225 emu->x86.R_EBX = tmp;
2226 } else {
2227 tmp = emu->x86.R_AX;
2228 emu->x86.R_AX = emu->x86.R_BX;
2229 emu->x86.R_BX = (uint16_t) tmp;
2232 /****************************************************************************
2233 REMARKS:
2234 Handles opcode 0x94
2235 ****************************************************************************/
2236 static void
2237 x86emuOp_xchg_word_AX_SP(struct X86EMU *emu)
2239 uint32_t tmp;
2241 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2242 tmp = emu->x86.R_EAX;
2243 emu->x86.R_EAX = emu->x86.R_ESP;
2244 emu->x86.R_ESP = tmp;
2245 } else {
2246 tmp = emu->x86.R_AX;
2247 emu->x86.R_AX = emu->x86.R_SP;
2248 emu->x86.R_SP = (uint16_t) tmp;
2251 /****************************************************************************
2252 REMARKS:
2253 Handles opcode 0x95
2254 ****************************************************************************/
2255 static void
2256 x86emuOp_xchg_word_AX_BP(struct X86EMU *emu)
2258 uint32_t tmp;
2260 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2261 tmp = emu->x86.R_EAX;
2262 emu->x86.R_EAX = emu->x86.R_EBP;
2263 emu->x86.R_EBP = tmp;
2264 } else {
2265 tmp = emu->x86.R_AX;
2266 emu->x86.R_AX = emu->x86.R_BP;
2267 emu->x86.R_BP = (uint16_t) tmp;
2270 /****************************************************************************
2271 REMARKS:
2272 Handles opcode 0x96
2273 ****************************************************************************/
2274 static void
2275 x86emuOp_xchg_word_AX_SI(struct X86EMU *emu)
2277 uint32_t tmp;
2279 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2280 tmp = emu->x86.R_EAX;
2281 emu->x86.R_EAX = emu->x86.R_ESI;
2282 emu->x86.R_ESI = tmp;
2283 } else {
2284 tmp = emu->x86.R_AX;
2285 emu->x86.R_AX = emu->x86.R_SI;
2286 emu->x86.R_SI = (uint16_t) tmp;
2289 /****************************************************************************
2290 REMARKS:
2291 Handles opcode 0x97
2292 ****************************************************************************/
2293 static void
2294 x86emuOp_xchg_word_AX_DI(struct X86EMU *emu)
2296 uint32_t tmp;
2298 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2299 tmp = emu->x86.R_EAX;
2300 emu->x86.R_EAX = emu->x86.R_EDI;
2301 emu->x86.R_EDI = tmp;
2302 } else {
2303 tmp = emu->x86.R_AX;
2304 emu->x86.R_AX = emu->x86.R_DI;
2305 emu->x86.R_DI = (uint16_t) tmp;
2308 /****************************************************************************
2309 REMARKS:
2310 Handles opcode 0x98
2311 ****************************************************************************/
2312 static void
2313 x86emuOp_cbw(struct X86EMU *emu)
2315 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2316 if (emu->x86.R_AX & 0x8000) {
2317 emu->x86.R_EAX |= 0xffff0000;
2318 } else {
2319 emu->x86.R_EAX &= 0x0000ffff;
2321 } else {
2322 if (emu->x86.R_AL & 0x80) {
2323 emu->x86.R_AH = 0xff;
2324 } else {
2325 emu->x86.R_AH = 0x0;
2329 /****************************************************************************
2330 REMARKS:
2331 Handles opcode 0x99
2332 ****************************************************************************/
2333 static void
2334 x86emuOp_cwd(struct X86EMU *emu)
2336 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2337 if (emu->x86.R_EAX & 0x80000000) {
2338 emu->x86.R_EDX = 0xffffffff;
2339 } else {
2340 emu->x86.R_EDX = 0x0;
2342 } else {
2343 if (emu->x86.R_AX & 0x8000) {
2344 emu->x86.R_DX = 0xffff;
2345 } else {
2346 emu->x86.R_DX = 0x0;
2350 /****************************************************************************
2351 REMARKS:
2352 Handles opcode 0x9a
2353 ****************************************************************************/
2354 static void
2355 x86emuOp_call_far_IMM(struct X86EMU *emu)
2357 uint16_t farseg, faroff;
2359 faroff = fetch_word_imm(emu);
2360 farseg = fetch_word_imm(emu);
2361 /* XXX
2363 * Hooked interrupt vectors calling into our "BIOS" will cause problems
2364 * unless all intersegment stuff is checked for BIOS access. Check
2365 * needed here. For moment, let it alone. */
2366 push_word(emu, emu->x86.R_CS);
2367 emu->x86.R_CS = farseg;
2368 push_word(emu, emu->x86.R_IP);
2369 emu->x86.R_IP = faroff;
2371 /****************************************************************************
2372 REMARKS:
2373 Handles opcode 0x9c
2374 ****************************************************************************/
2375 static void
2376 x86emuOp_pushf_word(struct X86EMU *emu)
2378 uint32_t flags;
2380 /* clear out *all* bits not representing flags, and turn on real bits */
2381 flags = (emu->x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
2382 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2383 push_long(emu, flags);
2384 } else {
2385 push_word(emu, (uint16_t) flags);
2388 /****************************************************************************
2389 REMARKS:
2390 Handles opcode 0x9d
2391 ****************************************************************************/
2392 static void
2393 x86emuOp_popf_word(struct X86EMU *emu)
2395 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2396 emu->x86.R_EFLG = pop_long(emu);
2397 } else {
2398 emu->x86.R_FLG = pop_word(emu);
2401 /****************************************************************************
2402 REMARKS:
2403 Handles opcode 0x9e
2404 ****************************************************************************/
2405 static void
2406 x86emuOp_sahf(struct X86EMU *emu)
2408 /* clear the lower bits of the flag register */
2409 emu->x86.R_FLG &= 0xffffff00;
2410 /* or in the AH register into the flags register */
2411 emu->x86.R_FLG |= emu->x86.R_AH;
2413 /****************************************************************************
2414 REMARKS:
2415 Handles opcode 0x9f
2416 ****************************************************************************/
2417 static void
2418 x86emuOp_lahf(struct X86EMU *emu)
2420 emu->x86.R_AH = (uint8_t) (emu->x86.R_FLG & 0xff);
2421 /* undocumented TC++ behavior??? Nope. It's documented, but you have
2422 * too look real hard to notice it. */
2423 emu->x86.R_AH |= 0x2;
2425 /****************************************************************************
2426 REMARKS:
2427 Handles opcode 0xa0
2428 ****************************************************************************/
2429 static void
2430 x86emuOp_mov_AL_M_IMM(struct X86EMU *emu)
2432 uint16_t offset;
2434 offset = fetch_word_imm(emu);
2435 emu->x86.R_AL = fetch_data_byte(emu, offset);
2437 /****************************************************************************
2438 REMARKS:
2439 Handles opcode 0xa1
2440 ****************************************************************************/
2441 static void
2442 x86emuOp_mov_AX_M_IMM(struct X86EMU *emu)
2444 uint16_t offset;
2446 offset = fetch_word_imm(emu);
2447 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2448 emu->x86.R_EAX = fetch_data_long(emu, offset);
2449 } else {
2450 emu->x86.R_AX = fetch_data_word(emu, offset);
2453 /****************************************************************************
2454 REMARKS:
2455 Handles opcode 0xa2
2456 ****************************************************************************/
2457 static void
2458 x86emuOp_mov_M_AL_IMM(struct X86EMU *emu)
2460 uint16_t offset;
2462 offset = fetch_word_imm(emu);
2463 store_data_byte(emu, offset, emu->x86.R_AL);
2465 /****************************************************************************
2466 REMARKS:
2467 Handles opcode 0xa3
2468 ****************************************************************************/
2469 static void
2470 x86emuOp_mov_M_AX_IMM(struct X86EMU *emu)
2472 uint16_t offset;
2474 offset = fetch_word_imm(emu);
2475 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2476 store_data_long(emu, offset, emu->x86.R_EAX);
2477 } else {
2478 store_data_word(emu, offset, emu->x86.R_AX);
2481 /****************************************************************************
2482 REMARKS:
2483 Handles opcode 0xa4
2484 ****************************************************************************/
2485 static void
2486 x86emuOp_movs_byte(struct X86EMU *emu)
2488 uint8_t val;
2489 uint32_t count;
2490 int inc;
2492 if (ACCESS_FLAG(F_DF)) /* down */
2493 inc = -1;
2494 else
2495 inc = 1;
2496 count = 1;
2497 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2498 /* dont care whether REPE or REPNE */
2499 /* move them until CX is ZERO. */
2500 count = emu->x86.R_CX;
2501 emu->x86.R_CX = 0;
2502 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2504 while (count--) {
2505 val = fetch_data_byte(emu, emu->x86.R_SI);
2506 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, val);
2507 emu->x86.R_SI += inc;
2508 emu->x86.R_DI += inc;
2511 /****************************************************************************
2512 REMARKS:
2513 Handles opcode 0xa5
2514 ****************************************************************************/
2515 static void
2516 x86emuOp_movs_word(struct X86EMU *emu)
2518 uint32_t val;
2519 int inc;
2520 uint32_t count;
2522 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2523 inc = 4;
2524 else
2525 inc = 2;
2527 if (ACCESS_FLAG(F_DF)) /* down */
2528 inc = -inc;
2530 count = 1;
2531 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2532 /* dont care whether REPE or REPNE */
2533 /* move them until CX is ZERO. */
2534 count = emu->x86.R_CX;
2535 emu->x86.R_CX = 0;
2536 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2538 while (count--) {
2539 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2540 val = fetch_data_long(emu, emu->x86.R_SI);
2541 store_long(emu, emu->x86.R_ES, emu->x86.R_DI, val);
2542 } else {
2543 val = fetch_data_word(emu, emu->x86.R_SI);
2544 store_word(emu, emu->x86.R_ES, emu->x86.R_DI, (uint16_t) val);
2546 emu->x86.R_SI += inc;
2547 emu->x86.R_DI += inc;
2550 /****************************************************************************
2551 REMARKS:
2552 Handles opcode 0xa6
2553 ****************************************************************************/
2554 static void
2555 x86emuOp_cmps_byte(struct X86EMU *emu)
2557 int8_t val1, val2;
2558 int inc;
2560 if (ACCESS_FLAG(F_DF)) /* down */
2561 inc = -1;
2562 else
2563 inc = 1;
2565 if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2566 /* REPE */
2567 /* move them until CX is ZERO. */
2568 while (emu->x86.R_CX != 0) {
2569 val1 = fetch_data_byte(emu, emu->x86.R_SI);
2570 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2571 cmp_byte(emu, val1, val2);
2572 emu->x86.R_CX -= 1;
2573 emu->x86.R_SI += inc;
2574 emu->x86.R_DI += inc;
2575 if (ACCESS_FLAG(F_ZF) == 0)
2576 break;
2578 emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2579 } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2580 /* REPNE */
2581 /* move them until CX is ZERO. */
2582 while (emu->x86.R_CX != 0) {
2583 val1 = fetch_data_byte(emu, emu->x86.R_SI);
2584 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2585 cmp_byte(emu, val1, val2);
2586 emu->x86.R_CX -= 1;
2587 emu->x86.R_SI += inc;
2588 emu->x86.R_DI += inc;
2589 if (ACCESS_FLAG(F_ZF))
2590 break; /* zero flag set means equal */
2592 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2593 } else {
2594 val1 = fetch_data_byte(emu, emu->x86.R_SI);
2595 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2596 cmp_byte(emu, val1, val2);
2597 emu->x86.R_SI += inc;
2598 emu->x86.R_DI += inc;
2601 /****************************************************************************
2602 REMARKS:
2603 Handles opcode 0xa7
2604 ****************************************************************************/
2605 static void
2606 x86emuOp_cmps_word(struct X86EMU *emu)
2608 uint32_t val1, val2;
2609 int inc;
2611 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2612 if (ACCESS_FLAG(F_DF)) /* down */
2613 inc = -4;
2614 else
2615 inc = 4;
2616 } else {
2617 if (ACCESS_FLAG(F_DF)) /* down */
2618 inc = -2;
2619 else
2620 inc = 2;
2622 if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2623 /* REPE */
2624 /* move them until CX is ZERO. */
2625 while (emu->x86.R_CX != 0) {
2626 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2627 val1 = fetch_data_long(emu, emu->x86.R_SI);
2628 val2 = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
2629 cmp_long(emu, val1, val2);
2630 } else {
2631 val1 = fetch_data_word(emu, emu->x86.R_SI);
2632 val2 = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
2633 cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
2635 emu->x86.R_CX -= 1;
2636 emu->x86.R_SI += inc;
2637 emu->x86.R_DI += inc;
2638 if (ACCESS_FLAG(F_ZF) == 0)
2639 break;
2641 emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2642 } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2643 /* REPNE */
2644 /* move them until CX is ZERO. */
2645 while (emu->x86.R_CX != 0) {
2646 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2647 val1 = fetch_data_long(emu, emu->x86.R_SI);
2648 val2 = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
2649 cmp_long(emu, val1, val2);
2650 } else {
2651 val1 = fetch_data_word(emu, emu->x86.R_SI);
2652 val2 = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
2653 cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
2655 emu->x86.R_CX -= 1;
2656 emu->x86.R_SI += inc;
2657 emu->x86.R_DI += inc;
2658 if (ACCESS_FLAG(F_ZF))
2659 break; /* zero flag set means equal */
2661 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2662 } else {
2663 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2664 val1 = fetch_data_long(emu, emu->x86.R_SI);
2665 val2 = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
2666 cmp_long(emu, val1, val2);
2667 } else {
2668 val1 = fetch_data_word(emu, emu->x86.R_SI);
2669 val2 = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
2670 cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
2672 emu->x86.R_SI += inc;
2673 emu->x86.R_DI += inc;
2676 /****************************************************************************
2677 REMARKS:
2678 Handles opcode 0xa9
2679 ****************************************************************************/
2680 static void
2681 x86emuOp_test_AX_IMM(struct X86EMU *emu)
2683 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2684 test_long(emu, emu->x86.R_EAX, fetch_long_imm(emu));
2685 } else {
2686 test_word(emu, emu->x86.R_AX, fetch_word_imm(emu));
2689 /****************************************************************************
2690 REMARKS:
2691 Handles opcode 0xaa
2692 ****************************************************************************/
2693 static void
2694 x86emuOp_stos_byte(struct X86EMU *emu)
2696 int inc;
2698 if (ACCESS_FLAG(F_DF)) /* down */
2699 inc = -1;
2700 else
2701 inc = 1;
2702 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2703 /* dont care whether REPE or REPNE */
2704 /* move them until CX is ZERO. */
2705 while (emu->x86.R_CX != 0) {
2706 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_AL);
2707 emu->x86.R_CX -= 1;
2708 emu->x86.R_DI += inc;
2710 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2711 } else {
2712 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_AL);
2713 emu->x86.R_DI += inc;
2716 /****************************************************************************
2717 REMARKS:
2718 Handles opcode 0xab
2719 ****************************************************************************/
2720 static void
2721 x86emuOp_stos_word(struct X86EMU *emu)
2723 int inc;
2724 uint32_t count;
2726 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2727 inc = 4;
2728 else
2729 inc = 2;
2731 if (ACCESS_FLAG(F_DF)) /* down */
2732 inc = -inc;
2734 count = 1;
2735 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2736 /* dont care whether REPE or REPNE */
2737 /* move them until CX is ZERO. */
2738 count = emu->x86.R_CX;
2739 emu->x86.R_CX = 0;
2740 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2742 while (count--) {
2743 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2744 store_long(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_EAX);
2745 } else {
2746 store_word(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_AX);
2748 emu->x86.R_DI += inc;
2751 /****************************************************************************
2752 REMARKS:
2753 Handles opcode 0xac
2754 ****************************************************************************/
2755 static void
2756 x86emuOp_lods_byte(struct X86EMU *emu)
2758 int inc;
2760 if (ACCESS_FLAG(F_DF)) /* down */
2761 inc = -1;
2762 else
2763 inc = 1;
2764 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2765 /* dont care whether REPE or REPNE */
2766 /* move them until CX is ZERO. */
2767 while (emu->x86.R_CX != 0) {
2768 emu->x86.R_AL = fetch_data_byte(emu, emu->x86.R_SI);
2769 emu->x86.R_CX -= 1;
2770 emu->x86.R_SI += inc;
2772 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2773 } else {
2774 emu->x86.R_AL = fetch_data_byte(emu, emu->x86.R_SI);
2775 emu->x86.R_SI += inc;
2778 /****************************************************************************
2779 REMARKS:
2780 Handles opcode 0xad
2781 ****************************************************************************/
2782 static void
2783 x86emuOp_lods_word(struct X86EMU *emu)
2785 int inc;
2786 uint32_t count;
2788 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2789 inc = 4;
2790 else
2791 inc = 2;
2793 if (ACCESS_FLAG(F_DF)) /* down */
2794 inc = -inc;
2796 count = 1;
2797 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2798 /* dont care whether REPE or REPNE */
2799 /* move them until CX is ZERO. */
2800 count = emu->x86.R_CX;
2801 emu->x86.R_CX = 0;
2802 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2804 while (count--) {
2805 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2806 emu->x86.R_EAX = fetch_data_long(emu, emu->x86.R_SI);
2807 } else {
2808 emu->x86.R_AX = fetch_data_word(emu, emu->x86.R_SI);
2810 emu->x86.R_SI += inc;
2813 /****************************************************************************
2814 REMARKS:
2815 Handles opcode 0xae
2816 ****************************************************************************/
2817 static void
2818 x86emuOp_scas_byte(struct X86EMU *emu)
2820 int8_t val2;
2821 int inc;
2823 if (ACCESS_FLAG(F_DF)) /* down */
2824 inc = -1;
2825 else
2826 inc = 1;
2827 if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2828 /* REPE */
2829 /* move them until CX is ZERO. */
2830 while (emu->x86.R_CX != 0) {
2831 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2832 cmp_byte(emu, emu->x86.R_AL, val2);
2833 emu->x86.R_CX -= 1;
2834 emu->x86.R_DI += inc;
2835 if (ACCESS_FLAG(F_ZF) == 0)
2836 break;
2838 emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2839 } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2840 /* REPNE */
2841 /* move them until CX is ZERO. */
2842 while (emu->x86.R_CX != 0) {
2843 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2844 cmp_byte(emu, emu->x86.R_AL, val2);
2845 emu->x86.R_CX -= 1;
2846 emu->x86.R_DI += inc;
2847 if (ACCESS_FLAG(F_ZF))
2848 break; /* zero flag set means equal */
2850 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2851 } else {
2852 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2853 cmp_byte(emu, emu->x86.R_AL, val2);
2854 emu->x86.R_DI += inc;
2857 /****************************************************************************
2858 REMARKS:
2859 Handles opcode 0xaf
2860 ****************************************************************************/
2861 static void
2862 x86emuOp_scas_word(struct X86EMU *emu)
2864 int inc;
2865 uint32_t val;
2867 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2868 inc = 4;
2869 else
2870 inc = 2;
2872 if (ACCESS_FLAG(F_DF)) /* down */
2873 inc = -inc;
2875 if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2876 /* REPE */
2877 /* move them until CX is ZERO. */
2878 while (emu->x86.R_CX != 0) {
2879 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2880 val = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
2881 cmp_long(emu, emu->x86.R_EAX, val);
2882 } else {
2883 val = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
2884 cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
2886 emu->x86.R_CX -= 1;
2887 emu->x86.R_DI += inc;
2888 if (ACCESS_FLAG(F_ZF) == 0)
2889 break;
2891 emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2892 } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2893 /* REPNE */
2894 /* move them until CX is ZERO. */
2895 while (emu->x86.R_CX != 0) {
2896 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2897 val = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
2898 cmp_long(emu, emu->x86.R_EAX, val);
2899 } else {
2900 val = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
2901 cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
2903 emu->x86.R_CX -= 1;
2904 emu->x86.R_DI += inc;
2905 if (ACCESS_FLAG(F_ZF))
2906 break; /* zero flag set means equal */
2908 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2909 } else {
2910 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2911 val = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
2912 cmp_long(emu, emu->x86.R_EAX, val);
2913 } else {
2914 val = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
2915 cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
2917 emu->x86.R_DI += inc;
2920 /****************************************************************************
2921 REMARKS:
2922 Handles opcode 0xb8
2923 ****************************************************************************/
2924 static void
2925 x86emuOp_mov_word_AX_IMM(struct X86EMU *emu)
2927 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2928 emu->x86.R_EAX = fetch_long_imm(emu);
2929 else
2930 emu->x86.R_AX = fetch_word_imm(emu);
2932 /****************************************************************************
2933 REMARKS:
2934 Handles opcode 0xb9
2935 ****************************************************************************/
2936 static void
2937 x86emuOp_mov_word_CX_IMM(struct X86EMU *emu)
2939 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2940 emu->x86.R_ECX = fetch_long_imm(emu);
2941 else
2942 emu->x86.R_CX = fetch_word_imm(emu);
2944 /****************************************************************************
2945 REMARKS:
2946 Handles opcode 0xba
2947 ****************************************************************************/
2948 static void
2949 x86emuOp_mov_word_DX_IMM(struct X86EMU *emu)
2951 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2952 emu->x86.R_EDX = fetch_long_imm(emu);
2953 else
2954 emu->x86.R_DX = fetch_word_imm(emu);
2956 /****************************************************************************
2957 REMARKS:
2958 Handles opcode 0xbb
2959 ****************************************************************************/
2960 static void
2961 x86emuOp_mov_word_BX_IMM(struct X86EMU *emu)
2963 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2964 emu->x86.R_EBX = fetch_long_imm(emu);
2965 else
2966 emu->x86.R_BX = fetch_word_imm(emu);
2968 /****************************************************************************
2969 REMARKS:
2970 Handles opcode 0xbc
2971 ****************************************************************************/
2972 static void
2973 x86emuOp_mov_word_SP_IMM(struct X86EMU *emu)
2975 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2976 emu->x86.R_ESP = fetch_long_imm(emu);
2977 else
2978 emu->x86.R_SP = fetch_word_imm(emu);
2980 /****************************************************************************
2981 REMARKS:
2982 Handles opcode 0xbd
2983 ****************************************************************************/
2984 static void
2985 x86emuOp_mov_word_BP_IMM(struct X86EMU *emu)
2987 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2988 emu->x86.R_EBP = fetch_long_imm(emu);
2989 else
2990 emu->x86.R_BP = fetch_word_imm(emu);
2992 /****************************************************************************
2993 REMARKS:
2994 Handles opcode 0xbe
2995 ****************************************************************************/
2996 static void
2997 x86emuOp_mov_word_SI_IMM(struct X86EMU *emu)
2999 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3000 emu->x86.R_ESI = fetch_long_imm(emu);
3001 else
3002 emu->x86.R_SI = fetch_word_imm(emu);
3004 /****************************************************************************
3005 REMARKS:
3006 Handles opcode 0xbf
3007 ****************************************************************************/
3008 static void
3009 x86emuOp_mov_word_DI_IMM(struct X86EMU *emu)
3011 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3012 emu->x86.R_EDI = fetch_long_imm(emu);
3013 else
3014 emu->x86.R_DI = fetch_word_imm(emu);
3016 /* used by opcodes c0, d0, and d2. */
3017 static
3018 uint8_t(* const opcD0_byte_operation[]) (struct X86EMU *, uint8_t d, uint8_t s) =
3020 rol_byte,
3021 ror_byte,
3022 rcl_byte,
3023 rcr_byte,
3024 shl_byte,
3025 shr_byte,
3026 shl_byte, /* sal_byte === shl_byte by definition */
3027 sar_byte,
3029 /****************************************************************************
3030 REMARKS:
3031 Handles opcode 0xc0
3032 ****************************************************************************/
3033 static void
3034 x86emuOp_opcC0_byte_RM_MEM(struct X86EMU *emu)
3036 uint8_t destval, amt;
3039 * Yet another weirdo special case instruction format. Part of
3040 * the opcode held below in "RH". Doubly nested case would
3041 * result, except that the decoded instruction
3043 fetch_decode_modrm(emu);
3044 /* know operation, decode the mod byte to find the addressing mode. */
3045 destval = decode_and_fetch_byte_imm8(emu, &amt);
3046 destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, amt);
3047 write_back_byte(emu, destval);
3049 /* used by opcodes c1, d1, and d3. */
3050 static
3051 uint16_t(* const opcD1_word_operation[]) (struct X86EMU *, uint16_t s, uint8_t d) =
3053 rol_word,
3054 ror_word,
3055 rcl_word,
3056 rcr_word,
3057 shl_word,
3058 shr_word,
3059 shl_word, /* sal_byte === shl_byte by definition */
3060 sar_word,
3062 /* used by opcodes c1, d1, and d3. */
3063 static
3064 uint32_t(* const opcD1_long_operation[]) (struct X86EMU *, uint32_t s, uint8_t d) =
3066 rol_long,
3067 ror_long,
3068 rcl_long,
3069 rcr_long,
3070 shl_long,
3071 shr_long,
3072 shl_long, /* sal_byte === shl_byte by definition */
3073 sar_long,
3075 /****************************************************************************
3076 REMARKS:
3077 Handles opcode 0xc1
3078 ****************************************************************************/
3079 static void
3080 x86emuOp_opcC1_word_RM_MEM(struct X86EMU *emu)
3082 uint8_t amt;
3085 * Yet another weirdo special case instruction format. Part of
3086 * the opcode held below in "RH". Doubly nested case would
3087 * result, except that the decoded instruction
3089 fetch_decode_modrm(emu);
3090 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3091 uint32_t destval;
3093 destval = decode_and_fetch_long_imm8(emu, &amt);
3094 destval = (*opcD1_long_operation[emu->cur_rh]) (emu, destval, amt);
3095 write_back_long(emu, destval);
3096 } else {
3097 uint16_t destval;
3099 destval = decode_and_fetch_word_imm8(emu, &amt);
3100 destval = (*opcD1_word_operation[emu->cur_rh]) (emu, destval, amt);
3101 write_back_word(emu, destval);
3104 /****************************************************************************
3105 REMARKS:
3106 Handles opcode 0xc2
3107 ****************************************************************************/
3108 static void
3109 x86emuOp_ret_near_IMM(struct X86EMU *emu)
3111 uint16_t imm;
3113 imm = fetch_word_imm(emu);
3114 emu->x86.R_IP = pop_word(emu);
3115 emu->x86.R_SP += imm;
3117 /****************************************************************************
3118 REMARKS:
3119 Handles opcode 0xc6
3120 ****************************************************************************/
3121 static void
3122 x86emuOp_mov_byte_RM_IMM(struct X86EMU *emu)
3124 uint8_t *destreg;
3125 uint32_t destoffset;
3126 uint8_t imm;
3128 fetch_decode_modrm(emu);
3129 if (emu->cur_rh != 0)
3130 X86EMU_halt_sys(emu);
3131 if (emu->cur_mod != 3) {
3132 destoffset = decode_rl_address(emu);
3133 imm = fetch_byte_imm(emu);
3134 store_data_byte(emu, destoffset, imm);
3135 } else {
3136 destreg = decode_rl_byte_register(emu);
3137 imm = fetch_byte_imm(emu);
3138 *destreg = imm;
3141 /****************************************************************************
3142 REMARKS:
3143 Handles opcode 0xc7
3144 ****************************************************************************/
3145 static void
3146 x86emuOp32_mov_word_RM_IMM(struct X86EMU *emu)
3148 uint32_t destoffset;
3149 uint32_t imm, *destreg;
3151 fetch_decode_modrm(emu);
3152 if (emu->cur_rh != 0)
3153 X86EMU_halt_sys(emu);
3155 if (emu->cur_mod != 3) {
3156 destoffset = decode_rl_address(emu);
3157 imm = fetch_long_imm(emu);
3158 store_data_long(emu, destoffset, imm);
3159 } else {
3160 destreg = decode_rl_long_register(emu);
3161 imm = fetch_long_imm(emu);
3162 *destreg = imm;
3166 static void
3167 x86emuOp16_mov_word_RM_IMM(struct X86EMU *emu)
3169 uint32_t destoffset;
3170 uint16_t imm, *destreg;
3172 fetch_decode_modrm(emu);
3173 if (emu->cur_rh != 0)
3174 X86EMU_halt_sys(emu);
3176 if (emu->cur_mod != 3) {
3177 destoffset = decode_rl_address(emu);
3178 imm = fetch_word_imm(emu);
3179 store_data_word(emu, destoffset, imm);
3180 } else {
3181 destreg = decode_rl_word_register(emu);
3182 imm = fetch_word_imm(emu);
3183 *destreg = imm;
3187 static void
3188 x86emuOp_mov_word_RM_IMM(struct X86EMU *emu)
3190 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3191 x86emuOp32_mov_word_RM_IMM(emu);
3192 else
3193 x86emuOp16_mov_word_RM_IMM(emu);
3195 /****************************************************************************
3196 REMARKS:
3197 Handles opcode 0xc8
3198 ****************************************************************************/
3199 static void
3200 x86emuOp_enter(struct X86EMU *emu)
3202 uint16_t local, frame_pointer;
3203 uint8_t nesting;
3204 int i;
3206 local = fetch_word_imm(emu);
3207 nesting = fetch_byte_imm(emu);
3208 push_word(emu, emu->x86.R_BP);
3209 frame_pointer = emu->x86.R_SP;
3210 if (nesting > 0) {
3211 for (i = 1; i < nesting; i++) {
3212 emu->x86.R_BP -= 2;
3213 push_word(emu, fetch_word(emu, emu->x86.R_SS, emu->x86.R_BP));
3215 push_word(emu, frame_pointer);
3217 emu->x86.R_BP = frame_pointer;
3218 emu->x86.R_SP = (uint16_t) (emu->x86.R_SP - local);
3220 /****************************************************************************
3221 REMARKS:
3222 Handles opcode 0xc9
3223 ****************************************************************************/
3224 static void
3225 x86emuOp_leave(struct X86EMU *emu)
3227 emu->x86.R_SP = emu->x86.R_BP;
3228 emu->x86.R_BP = pop_word(emu);
3230 /****************************************************************************
3231 REMARKS:
3232 Handles opcode 0xca
3233 ****************************************************************************/
3234 static void
3235 x86emuOp_ret_far_IMM(struct X86EMU *emu)
3237 uint16_t imm;
3239 imm = fetch_word_imm(emu);
3240 emu->x86.R_IP = pop_word(emu);
3241 emu->x86.R_CS = pop_word(emu);
3242 emu->x86.R_SP += imm;
3244 /****************************************************************************
3245 REMARKS:
3246 Handles opcode 0xcb
3247 ****************************************************************************/
3248 static void
3249 x86emuOp_ret_far(struct X86EMU *emu)
3251 emu->x86.R_IP = pop_word(emu);
3252 emu->x86.R_CS = pop_word(emu);
3254 /****************************************************************************
3255 REMARKS:
3256 Handles opcode 0xcc
3257 ****************************************************************************/
3258 static void
3259 x86emuOp_int3(struct X86EMU *emu)
3261 x86emu_intr_dispatch(emu, 3);
3263 /****************************************************************************
3264 REMARKS:
3265 Handles opcode 0xcd
3266 ****************************************************************************/
3267 static void
3268 x86emuOp_int_IMM(struct X86EMU *emu)
3270 uint8_t intnum;
3272 intnum = fetch_byte_imm(emu);
3273 x86emu_intr_dispatch(emu, intnum);
3275 /****************************************************************************
3276 REMARKS:
3277 Handles opcode 0xce
3278 ****************************************************************************/
3279 static void
3280 x86emuOp_into(struct X86EMU *emu)
3282 if (ACCESS_FLAG(F_OF))
3283 x86emu_intr_dispatch(emu, 4);
3285 /****************************************************************************
3286 REMARKS:
3287 Handles opcode 0xcf
3288 ****************************************************************************/
3289 static void
3290 x86emuOp_iret(struct X86EMU *emu)
3292 emu->x86.R_IP = pop_word(emu);
3293 emu->x86.R_CS = pop_word(emu);
3294 emu->x86.R_FLG = pop_word(emu);
3296 /****************************************************************************
3297 REMARKS:
3298 Handles opcode 0xd0
3299 ****************************************************************************/
3300 static void
3301 x86emuOp_opcD0_byte_RM_1(struct X86EMU *emu)
3303 uint8_t destval;
3305 fetch_decode_modrm(emu);
3306 destval = decode_and_fetch_byte(emu);
3307 destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, 1);
3308 write_back_byte(emu, destval);
3310 /****************************************************************************
3311 REMARKS:
3312 Handles opcode 0xd1
3313 ****************************************************************************/
3314 static void
3315 x86emuOp_opcD1_word_RM_1(struct X86EMU *emu)
3317 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3318 uint32_t destval;
3320 fetch_decode_modrm(emu);
3321 destval = decode_and_fetch_long(emu);
3322 destval = (*opcD1_long_operation[emu->cur_rh]) (emu, destval, 1);
3323 write_back_long(emu, destval);
3324 } else {
3325 uint16_t destval;
3327 fetch_decode_modrm(emu);
3328 destval = decode_and_fetch_word(emu);
3329 destval = (*opcD1_word_operation[emu->cur_rh]) (emu, destval, 1);
3330 write_back_word(emu, destval);
3333 /****************************************************************************
3334 REMARKS:
3335 Handles opcode 0xd2
3336 ****************************************************************************/
3337 static void
3338 x86emuOp_opcD2_byte_RM_CL(struct X86EMU *emu)
3340 uint8_t destval;
3342 fetch_decode_modrm(emu);
3343 destval = decode_and_fetch_byte(emu);
3344 destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, emu->x86.R_CL);
3345 write_back_byte(emu, destval);
3347 /****************************************************************************
3348 REMARKS:
3349 Handles opcode 0xd3
3350 ****************************************************************************/
3351 static void
3352 x86emuOp_opcD3_word_RM_CL(struct X86EMU *emu)
3354 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3355 uint32_t destval;
3357 fetch_decode_modrm(emu);
3358 destval = decode_and_fetch_long(emu);
3359 destval = (*opcD1_long_operation[emu->cur_rh]) (emu, destval, emu->x86.R_CL);
3360 write_back_long(emu, destval);
3361 } else {
3362 uint16_t destval;
3364 fetch_decode_modrm(emu);
3365 destval = decode_and_fetch_word(emu);
3366 destval = (*opcD1_word_operation[emu->cur_rh]) (emu, destval, emu->x86.R_CL);
3367 write_back_word(emu, destval);
3370 /****************************************************************************
3371 REMARKS:
3372 Handles opcode 0xd4
3373 ****************************************************************************/
3374 static void
3375 x86emuOp_aam(struct X86EMU *emu)
3377 uint8_t a;
3379 a = fetch_byte_imm(emu); /* this is a stupid encoding. */
3380 if (a != 10) {
3381 /* fix: add base decoding aam_word(uint8_t val, int base a) */
3382 X86EMU_halt_sys(emu);
3384 /* note the type change here --- returning AL and AH in AX. */
3385 emu->x86.R_AX = aam_word(emu, emu->x86.R_AL);
3387 /****************************************************************************
3388 REMARKS:
3389 Handles opcode 0xd5
3390 ****************************************************************************/
3391 static void
3392 x86emuOp_aad(struct X86EMU *emu)
3394 uint8_t a;
3396 a = fetch_byte_imm(emu);
3397 if (a != 10) {
3398 /* fix: add base decoding aad_word(uint16_t val, int base a) */
3399 X86EMU_halt_sys(emu);
3401 emu->x86.R_AX = aad_word(emu, emu->x86.R_AX);
3403 /* opcode 0xd6 ILLEGAL OPCODE */
3405 /****************************************************************************
3406 REMARKS:
3407 Handles opcode 0xd7
3408 ****************************************************************************/
3409 static void
3410 x86emuOp_xlat(struct X86EMU *emu)
3412 uint16_t addr;
3414 addr = (uint16_t) (emu->x86.R_BX + (uint8_t) emu->x86.R_AL);
3415 emu->x86.R_AL = fetch_data_byte(emu, addr);
3418 /* opcode=0xd8 */
3419 static void
3420 x86emuOp_esc_coprocess_d8(struct X86EMU *emu)
3423 /* opcode=0xd9 */
3424 static void
3425 x86emuOp_esc_coprocess_d9(struct X86EMU *emu)
3427 fetch_decode_modrm(emu);
3428 if (emu->cur_mod != 3)
3429 decode_rl_address(emu);
3431 /* opcode=0xda */
3432 static void
3433 x86emuOp_esc_coprocess_da(struct X86EMU *emu)
3435 fetch_decode_modrm(emu);
3436 if (emu->cur_mod != 3)
3437 decode_rl_address(emu);
3439 /* opcode=0xdb */
3440 static void
3441 x86emuOp_esc_coprocess_db(struct X86EMU *emu)
3443 fetch_decode_modrm(emu);
3444 if (emu->cur_mod != 3)
3445 decode_rl_address(emu);
3447 /* opcode=0xdc */
3448 static void
3449 x86emuOp_esc_coprocess_dc(struct X86EMU *emu)
3451 fetch_decode_modrm(emu);
3452 if (emu->cur_mod != 3)
3453 decode_rl_address(emu);
3455 /* opcode=0xdd */
3456 static void
3457 x86emuOp_esc_coprocess_dd(struct X86EMU *emu)
3459 fetch_decode_modrm(emu);
3460 if (emu->cur_mod != 3)
3461 decode_rl_address(emu);
3463 /* opcode=0xde */
3464 static void
3465 x86emuOp_esc_coprocess_de(struct X86EMU *emu)
3467 fetch_decode_modrm(emu);
3468 if (emu->cur_mod != 3)
3469 decode_rl_address(emu);
3471 /* opcode=0xdf */
3472 static void
3473 x86emuOp_esc_coprocess_df(struct X86EMU *emu)
3475 fetch_decode_modrm(emu);
3476 if (emu->cur_mod != 3)
3477 decode_rl_address(emu);
3480 /****************************************************************************
3481 REMARKS:
3482 Handles opcode 0xe0
3483 ****************************************************************************/
3484 static void
3485 x86emuOp_loopne(struct X86EMU *emu)
3487 int16_t ip;
3489 ip = (int8_t) fetch_byte_imm(emu);
3490 ip += (int16_t) emu->x86.R_IP;
3491 emu->x86.R_CX -= 1;
3492 if (emu->x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */
3493 emu->x86.R_IP = ip;
3495 /****************************************************************************
3496 REMARKS:
3497 Handles opcode 0xe1
3498 ****************************************************************************/
3499 static void
3500 x86emuOp_loope(struct X86EMU *emu)
3502 int16_t ip;
3504 ip = (int8_t) fetch_byte_imm(emu);
3505 ip += (int16_t) emu->x86.R_IP;
3506 emu->x86.R_CX -= 1;
3507 if (emu->x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */
3508 emu->x86.R_IP = ip;
3510 /****************************************************************************
3511 REMARKS:
3512 Handles opcode 0xe2
3513 ****************************************************************************/
3514 static void
3515 x86emuOp_loop(struct X86EMU *emu)
3517 int16_t ip;
3519 ip = (int8_t) fetch_byte_imm(emu);
3520 ip += (int16_t) emu->x86.R_IP;
3521 emu->x86.R_CX -= 1;
3522 if (emu->x86.R_CX != 0)
3523 emu->x86.R_IP = ip;
3525 /****************************************************************************
3526 REMARKS:
3527 Handles opcode 0xe3
3528 ****************************************************************************/
3529 static void
3530 x86emuOp_jcxz(struct X86EMU *emu)
3532 uint16_t target;
3533 int8_t offset;
3535 /* jump to byte offset if overflow flag is set */
3536 offset = (int8_t) fetch_byte_imm(emu);
3537 target = (uint16_t) (emu->x86.R_IP + offset);
3538 if (emu->x86.R_CX == 0)
3539 emu->x86.R_IP = target;
3541 /****************************************************************************
3542 REMARKS:
3543 Handles opcode 0xe4
3544 ****************************************************************************/
3545 static void
3546 x86emuOp_in_byte_AL_IMM(struct X86EMU *emu)
3548 uint8_t port;
3550 port = (uint8_t) fetch_byte_imm(emu);
3551 emu->x86.R_AL = (*emu->emu_inb) (emu, port);
3553 /****************************************************************************
3554 REMARKS:
3555 Handles opcode 0xe5
3556 ****************************************************************************/
3557 static void
3558 x86emuOp_in_word_AX_IMM(struct X86EMU *emu)
3560 uint8_t port;
3562 port = (uint8_t) fetch_byte_imm(emu);
3563 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3564 emu->x86.R_EAX = (*emu->emu_inl) (emu, port);
3565 } else {
3566 emu->x86.R_AX = (*emu->emu_inw) (emu, port);
3569 /****************************************************************************
3570 REMARKS:
3571 Handles opcode 0xe6
3572 ****************************************************************************/
3573 static void
3574 x86emuOp_out_byte_IMM_AL(struct X86EMU *emu)
3576 uint8_t port;
3578 port = (uint8_t) fetch_byte_imm(emu);
3579 (*emu->emu_outb) (emu, port, emu->x86.R_AL);
3581 /****************************************************************************
3582 REMARKS:
3583 Handles opcode 0xe7
3584 ****************************************************************************/
3585 static void
3586 x86emuOp_out_word_IMM_AX(struct X86EMU *emu)
3588 uint8_t port;
3590 port = (uint8_t) fetch_byte_imm(emu);
3591 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3592 (*emu->emu_outl) (emu, port, emu->x86.R_EAX);
3593 } else {
3594 (*emu->emu_outw) (emu, port, emu->x86.R_AX);
3597 /****************************************************************************
3598 REMARKS:
3599 Handles opcode 0xe8
3600 ****************************************************************************/
3601 static void
3602 x86emuOp_call_near_IMM(struct X86EMU *emu)
3604 int16_t ip;
3606 ip = (int16_t) fetch_word_imm(emu);
3607 ip += (int16_t) emu->x86.R_IP; /* CHECK SIGN */
3608 push_word(emu, emu->x86.R_IP);
3609 emu->x86.R_IP = ip;
3611 /****************************************************************************
3612 REMARKS:
3613 Handles opcode 0xe9
3614 ****************************************************************************/
3615 static void
3616 x86emuOp_jump_near_IMM(struct X86EMU *emu)
3618 int ip;
3620 ip = (int16_t) fetch_word_imm(emu);
3621 ip += (int16_t) emu->x86.R_IP;
3622 emu->x86.R_IP = (uint16_t) ip;
3624 /****************************************************************************
3625 REMARKS:
3626 Handles opcode 0xea
3627 ****************************************************************************/
3628 static void
3629 x86emuOp_jump_far_IMM(struct X86EMU *emu)
3631 uint16_t cs, ip;
3633 ip = fetch_word_imm(emu);
3634 cs = fetch_word_imm(emu);
3635 emu->x86.R_IP = ip;
3636 emu->x86.R_CS = cs;
3638 /****************************************************************************
3639 REMARKS:
3640 Handles opcode 0xeb
3641 ****************************************************************************/
3642 static void
3643 x86emuOp_jump_byte_IMM(struct X86EMU *emu)
3645 uint16_t target;
3646 int8_t offset;
3648 offset = (int8_t) fetch_byte_imm(emu);
3649 target = (uint16_t) (emu->x86.R_IP + offset);
3650 emu->x86.R_IP = target;
3652 /****************************************************************************
3653 REMARKS:
3654 Handles opcode 0xec
3655 ****************************************************************************/
3656 static void
3657 x86emuOp_in_byte_AL_DX(struct X86EMU *emu)
3659 emu->x86.R_AL = (*emu->emu_inb) (emu, emu->x86.R_DX);
3661 /****************************************************************************
3662 REMARKS:
3663 Handles opcode 0xed
3664 ****************************************************************************/
3665 static void
3666 x86emuOp_in_word_AX_DX(struct X86EMU *emu)
3668 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3669 emu->x86.R_EAX = (*emu->emu_inl) (emu, emu->x86.R_DX);
3670 } else {
3671 emu->x86.R_AX = (*emu->emu_inw) (emu, emu->x86.R_DX);
3674 /****************************************************************************
3675 REMARKS:
3676 Handles opcode 0xee
3677 ****************************************************************************/
3678 static void
3679 x86emuOp_out_byte_DX_AL(struct X86EMU *emu)
3681 (*emu->emu_outb) (emu, emu->x86.R_DX, emu->x86.R_AL);
3683 /****************************************************************************
3684 REMARKS:
3685 Handles opcode 0xef
3686 ****************************************************************************/
3687 static void
3688 x86emuOp_out_word_DX_AX(struct X86EMU *emu)
3690 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3691 (*emu->emu_outl) (emu, emu->x86.R_DX, emu->x86.R_EAX);
3692 } else {
3693 (*emu->emu_outw) (emu, emu->x86.R_DX, emu->x86.R_AX);
3696 /****************************************************************************
3697 REMARKS:
3698 Handles opcode 0xf0
3699 ****************************************************************************/
3700 static void
3701 x86emuOp_lock(struct X86EMU *emu)
3704 /*opcode 0xf1 ILLEGAL OPERATION */
3706 /****************************************************************************
3707 REMARKS:
3708 Handles opcode 0xf5
3709 ****************************************************************************/
3710 static void
3711 x86emuOp_cmc(struct X86EMU *emu)
3713 if (ACCESS_FLAG(F_CF))
3714 CLEAR_FLAG(F_CF);
3715 else
3716 SET_FLAG(F_CF);
3718 /****************************************************************************
3719 REMARKS:
3720 Handles opcode 0xf6
3721 ****************************************************************************/
3722 static void
3723 x86emuOp_opcF6_byte_RM(struct X86EMU *emu)
3725 uint8_t destval, srcval;
3727 /* long, drawn out code follows. Double switch for a total of 32
3728 * cases. */
3729 fetch_decode_modrm(emu);
3730 if (emu->cur_rh == 1)
3731 X86EMU_halt_sys(emu);
3733 if (emu->cur_rh == 0) {
3734 destval = decode_and_fetch_byte_imm8(emu, &srcval);
3735 test_byte(emu, destval, srcval);
3736 return;
3738 destval = decode_and_fetch_byte(emu);
3739 switch (emu->cur_rh) {
3740 case 2:
3741 destval = ~destval;
3742 write_back_byte(emu, destval);
3743 break;
3744 case 3:
3745 destval = neg_byte(emu, destval);
3746 write_back_byte(emu, destval);
3747 break;
3748 case 4:
3749 mul_byte(emu, destval);
3750 break;
3751 case 5:
3752 imul_byte(emu, destval);
3753 break;
3754 case 6:
3755 div_byte(emu, destval);
3756 break;
3757 case 7:
3758 idiv_byte(emu, destval);
3759 break;
3762 /****************************************************************************
3763 REMARKS:
3764 Handles opcode 0xf7
3765 ****************************************************************************/
3766 static void
3767 x86emuOp32_opcF7_word_RM(struct X86EMU *emu)
3769 uint32_t destval, srcval;
3771 /* long, drawn out code follows. Double switch for a total of 32
3772 * cases. */
3773 fetch_decode_modrm(emu);
3774 if (emu->cur_rh == 1)
3775 X86EMU_halt_sys(emu);
3777 if (emu->cur_rh == 0) {
3778 if (emu->cur_mod != 3) {
3779 uint32_t destoffset;
3781 destoffset = decode_rl_address(emu);
3782 srcval = fetch_long_imm(emu);
3783 destval = fetch_data_long(emu, destoffset);
3784 } else {
3785 srcval = fetch_long_imm(emu);
3786 destval = *decode_rl_long_register(emu);
3788 test_long(emu, destval, srcval);
3789 return;
3791 destval = decode_and_fetch_long(emu);
3792 switch (emu->cur_rh) {
3793 case 2:
3794 destval = ~destval;
3795 write_back_long(emu, destval);
3796 break;
3797 case 3:
3798 destval = neg_long(emu, destval);
3799 write_back_long(emu, destval);
3800 break;
3801 case 4:
3802 mul_long(emu, destval);
3803 break;
3804 case 5:
3805 imul_long(emu, destval);
3806 break;
3807 case 6:
3808 div_long(emu, destval);
3809 break;
3810 case 7:
3811 idiv_long(emu, destval);
3812 break;
3815 static void
3816 x86emuOp16_opcF7_word_RM(struct X86EMU *emu)
3818 uint16_t destval, srcval;
3820 /* long, drawn out code follows. Double switch for a total of 32
3821 * cases. */
3822 fetch_decode_modrm(emu);
3823 if (emu->cur_rh == 1)
3824 X86EMU_halt_sys(emu);
3826 if (emu->cur_rh == 0) {
3827 if (emu->cur_mod != 3) {
3828 uint32_t destoffset;
3830 destoffset = decode_rl_address(emu);
3831 srcval = fetch_word_imm(emu);
3832 destval = fetch_data_word(emu, destoffset);
3833 } else {
3834 srcval = fetch_word_imm(emu);
3835 destval = *decode_rl_word_register(emu);
3837 test_word(emu, destval, srcval);
3838 return;
3840 destval = decode_and_fetch_word(emu);
3841 switch (emu->cur_rh) {
3842 case 2:
3843 destval = ~destval;
3844 write_back_word(emu, destval);
3845 break;
3846 case 3:
3847 destval = neg_word(emu, destval);
3848 write_back_word(emu, destval);
3849 break;
3850 case 4:
3851 mul_word(emu, destval);
3852 break;
3853 case 5:
3854 imul_word(emu, destval);
3855 break;
3856 case 6:
3857 div_word(emu, destval);
3858 break;
3859 case 7:
3860 idiv_word(emu, destval);
3861 break;
3864 static void
3865 x86emuOp_opcF7_word_RM(struct X86EMU *emu)
3867 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3868 x86emuOp32_opcF7_word_RM(emu);
3869 else
3870 x86emuOp16_opcF7_word_RM(emu);
3872 /****************************************************************************
3873 REMARKS:
3874 Handles opcode 0xfe
3875 ****************************************************************************/
3876 static void
3877 x86emuOp_opcFE_byte_RM(struct X86EMU *emu)
3879 uint8_t destval;
3880 uint32_t destoffset;
3881 uint8_t *destreg;
3883 /* Yet another special case instruction. */
3884 fetch_decode_modrm(emu);
3885 if (emu->cur_mod != 3) {
3886 destoffset = decode_rl_address(emu);
3887 switch (emu->cur_rh) {
3888 case 0: /* inc word ptr ... */
3889 destval = fetch_data_byte(emu, destoffset);
3890 destval = inc_byte(emu, destval);
3891 store_data_byte(emu, destoffset, destval);
3892 break;
3893 case 1: /* dec word ptr ... */
3894 destval = fetch_data_byte(emu, destoffset);
3895 destval = dec_byte(emu, destval);
3896 store_data_byte(emu, destoffset, destval);
3897 break;
3899 } else {
3900 destreg = decode_rl_byte_register(emu);
3901 switch (emu->cur_rh) {
3902 case 0:
3903 *destreg = inc_byte(emu, *destreg);
3904 break;
3905 case 1:
3906 *destreg = dec_byte(emu, *destreg);
3907 break;
3911 /****************************************************************************
3912 REMARKS:
3913 Handles opcode 0xff
3914 ****************************************************************************/
3915 static void
3916 x86emuOp32_opcFF_word_RM(struct X86EMU *emu)
3918 uint32_t destoffset = 0;
3919 uint32_t destval, *destreg;
3921 if (emu->cur_mod != 3) {
3922 destoffset = decode_rl_address(emu);
3923 destval = fetch_data_long(emu, destoffset);
3924 switch (emu->cur_rh) {
3925 case 0: /* inc word ptr ... */
3926 destval = inc_long(emu, destval);
3927 store_data_long(emu, destoffset, destval);
3928 break;
3929 case 1: /* dec word ptr ... */
3930 destval = dec_long(emu, destval);
3931 store_data_long(emu, destoffset, destval);
3932 break;
3933 case 6: /* push word ptr ... */
3934 push_long(emu, destval);
3935 break;
3937 } else {
3938 destreg = decode_rl_long_register(emu);
3939 switch (emu->cur_rh) {
3940 case 0:
3941 *destreg = inc_long(emu, *destreg);
3942 break;
3943 case 1:
3944 *destreg = dec_long(emu, *destreg);
3945 break;
3946 case 6:
3947 push_long(emu, *destreg);
3948 break;
3953 static void
3954 x86emuOp16_opcFF_word_RM(struct X86EMU *emu)
3956 uint32_t destoffset = 0;
3957 uint16_t *destreg;
3958 uint16_t destval;
3960 if (emu->cur_mod != 3) {
3961 destoffset = decode_rl_address(emu);
3962 destval = fetch_data_word(emu, destoffset);
3963 switch (emu->cur_rh) {
3964 case 0:
3965 destval = inc_word(emu, destval);
3966 store_data_word(emu, destoffset, destval);
3967 break;
3968 case 1: /* dec word ptr ... */
3969 destval = dec_word(emu, destval);
3970 store_data_word(emu, destoffset, destval);
3971 break;
3972 case 6: /* push word ptr ... */
3973 push_word(emu, destval);
3974 break;
3976 } else {
3977 destreg = decode_rl_word_register(emu);
3978 switch (emu->cur_rh) {
3979 case 0:
3980 *destreg = inc_word(emu, *destreg);
3981 break;
3982 case 1:
3983 *destreg = dec_word(emu, *destreg);
3984 break;
3985 case 6:
3986 push_word(emu, *destreg);
3987 break;
3992 static void
3993 x86emuOp_opcFF_word_RM(struct X86EMU *emu)
3995 uint32_t destoffset = 0;
3996 uint16_t destval, destval2;
3998 /* Yet another special case instruction. */
3999 fetch_decode_modrm(emu);
4000 if ((emu->cur_mod == 3 && (emu->cur_rh == 3 || emu->cur_rh == 5)) || emu->cur_rh == 7)
4001 X86EMU_halt_sys(emu);
4002 if (emu->cur_rh == 0 || emu->cur_rh == 1 || emu->cur_rh == 6) {
4003 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
4004 x86emuOp32_opcFF_word_RM(emu);
4005 else
4006 x86emuOp16_opcFF_word_RM(emu);
4007 return;
4010 if (emu->cur_mod != 3) {
4011 destoffset = decode_rl_address(emu);
4012 destval = fetch_data_word(emu, destoffset);
4013 switch (emu->cur_rh) {
4014 case 3: /* call far ptr ... */
4015 destval2 = fetch_data_word(emu, destoffset + 2);
4016 push_word(emu, emu->x86.R_CS);
4017 emu->x86.R_CS = destval2;
4018 push_word(emu, emu->x86.R_IP);
4019 emu->x86.R_IP = destval;
4020 break;
4021 case 5: /* jmp far ptr ... */
4022 destval2 = fetch_data_word(emu, destoffset + 2);
4023 emu->x86.R_IP = destval;
4024 emu->x86.R_CS = destval2;
4025 break;
4027 } else {
4028 destval = *decode_rl_word_register(emu);
4031 switch (emu->cur_rh) {
4032 case 2: /* call word ptr */
4033 push_word(emu, emu->x86.R_IP);
4034 emu->x86.R_IP = destval;
4035 break;
4036 case 4: /* jmp */
4037 emu->x86.R_IP = destval;
4038 break;
4041 /***************************************************************************
4042 * Single byte operation code table:
4043 **************************************************************************/
4044 static void
4045 X86EMU_exec_one_byte(struct X86EMU * emu)
4047 uint8_t op1;
4049 op1 = fetch_byte_imm(emu);
4051 switch (op1) {
4052 case 0x00:
4053 common_binop_byte_rm_r(emu, add_byte);
4054 break;
4055 case 0x01:
4056 common_binop_word_long_rm_r(emu, add_word, add_long);
4057 break;
4058 case 0x02:
4059 common_binop_byte_r_rm(emu, add_byte);
4060 break;
4061 case 0x03:
4062 common_binop_word_long_r_rm(emu, add_word, add_long);
4063 break;
4064 case 0x04:
4065 common_binop_byte_imm(emu, add_byte);
4066 break;
4067 case 0x05:
4068 common_binop_word_long_imm(emu, add_word, add_long);
4069 break;
4070 case 0x06:
4071 push_word(emu, emu->x86.R_ES);
4072 break;
4073 case 0x07:
4074 emu->x86.R_ES = pop_word(emu);
4075 break;
4077 case 0x08:
4078 common_binop_byte_rm_r(emu, or_byte);
4079 break;
4080 case 0x09:
4081 common_binop_word_long_rm_r(emu, or_word, or_long);
4082 break;
4083 case 0x0a:
4084 common_binop_byte_r_rm(emu, or_byte);
4085 break;
4086 case 0x0b:
4087 common_binop_word_long_r_rm(emu, or_word, or_long);
4088 break;
4089 case 0x0c:
4090 common_binop_byte_imm(emu, or_byte);
4091 break;
4092 case 0x0d:
4093 common_binop_word_long_imm(emu, or_word, or_long);
4094 break;
4095 case 0x0e:
4096 push_word(emu, emu->x86.R_CS);
4097 break;
4098 case 0x0f:
4099 X86EMU_exec_two_byte(emu);
4100 break;
4102 case 0x10:
4103 common_binop_byte_rm_r(emu, adc_byte);
4104 break;
4105 case 0x11:
4106 common_binop_word_long_rm_r(emu, adc_word, adc_long);
4107 break;
4108 case 0x12:
4109 common_binop_byte_r_rm(emu, adc_byte);
4110 break;
4111 case 0x13:
4112 common_binop_word_long_r_rm(emu, adc_word, adc_long);
4113 break;
4114 case 0x14:
4115 common_binop_byte_imm(emu, adc_byte);
4116 break;
4117 case 0x15:
4118 common_binop_word_long_imm(emu, adc_word, adc_long);
4119 break;
4120 case 0x16:
4121 push_word(emu, emu->x86.R_SS);
4122 break;
4123 case 0x17:
4124 emu->x86.R_SS = pop_word(emu);
4125 break;
4127 case 0x18:
4128 common_binop_byte_rm_r(emu, sbb_byte);
4129 break;
4130 case 0x19:
4131 common_binop_word_long_rm_r(emu, sbb_word, sbb_long);
4132 break;
4133 case 0x1a:
4134 common_binop_byte_r_rm(emu, sbb_byte);
4135 break;
4136 case 0x1b:
4137 common_binop_word_long_r_rm(emu, sbb_word, sbb_long);
4138 break;
4139 case 0x1c:
4140 common_binop_byte_imm(emu, sbb_byte);
4141 break;
4142 case 0x1d:
4143 common_binop_word_long_imm(emu, sbb_word, sbb_long);
4144 break;
4145 case 0x1e:
4146 push_word(emu, emu->x86.R_DS);
4147 break;
4148 case 0x1f:
4149 emu->x86.R_DS = pop_word(emu);
4150 break;
4152 case 0x20:
4153 common_binop_byte_rm_r(emu, and_byte);
4154 break;
4155 case 0x21:
4156 common_binop_word_long_rm_r(emu, and_word, and_long);
4157 break;
4158 case 0x22:
4159 common_binop_byte_r_rm(emu, and_byte);
4160 break;
4161 case 0x23:
4162 common_binop_word_long_r_rm(emu, and_word, and_long);
4163 break;
4164 case 0x24:
4165 common_binop_byte_imm(emu, and_byte);
4166 break;
4167 case 0x25:
4168 common_binop_word_long_imm(emu, and_word, and_long);
4169 break;
4170 case 0x26:
4171 emu->x86.mode |= SYSMODE_SEGOVR_ES;
4172 break;
4173 case 0x27:
4174 emu->x86.R_AL = daa_byte(emu, emu->x86.R_AL);
4175 break;
4177 case 0x28:
4178 common_binop_byte_rm_r(emu, sub_byte);
4179 break;
4180 case 0x29:
4181 common_binop_word_long_rm_r(emu, sub_word, sub_long);
4182 break;
4183 case 0x2a:
4184 common_binop_byte_r_rm(emu, sub_byte);
4185 break;
4186 case 0x2b:
4187 common_binop_word_long_r_rm(emu, sub_word, sub_long);
4188 break;
4189 case 0x2c:
4190 common_binop_byte_imm(emu, sub_byte);
4191 break;
4192 case 0x2d:
4193 common_binop_word_long_imm(emu, sub_word, sub_long);
4194 break;
4195 case 0x2e:
4196 emu->x86.mode |= SYSMODE_SEGOVR_CS;
4197 break;
4198 case 0x2f:
4199 emu->x86.R_AL = das_byte(emu, emu->x86.R_AL);
4200 break;
4202 case 0x30:
4203 common_binop_byte_rm_r(emu, xor_byte);
4204 break;
4205 case 0x31:
4206 common_binop_word_long_rm_r(emu, xor_word, xor_long);
4207 break;
4208 case 0x32:
4209 common_binop_byte_r_rm(emu, xor_byte);
4210 break;
4211 case 0x33:
4212 common_binop_word_long_r_rm(emu, xor_word, xor_long);
4213 break;
4214 case 0x34:
4215 common_binop_byte_imm(emu, xor_byte);
4216 break;
4217 case 0x35:
4218 common_binop_word_long_imm(emu, xor_word, xor_long);
4219 break;
4220 case 0x36:
4221 emu->x86.mode |= SYSMODE_SEGOVR_SS;
4222 break;
4223 case 0x37:
4224 emu->x86.R_AX = aaa_word(emu, emu->x86.R_AX);
4225 break;
4227 case 0x38:
4228 common_binop_ns_byte_rm_r(emu, cmp_byte_no_return);
4229 break;
4230 case 0x39:
4231 common_binop_ns_word_long_rm_r(emu, cmp_word_no_return,
4232 cmp_long_no_return);
4233 break;
4234 case 0x3a:
4235 x86emuOp_cmp_byte_R_RM(emu);
4236 break;
4237 case 0x3b:
4238 x86emuOp_cmp_word_R_RM(emu);
4239 break;
4240 case 0x3c:
4241 x86emuOp_cmp_byte_AL_IMM(emu);
4242 break;
4243 case 0x3d:
4244 x86emuOp_cmp_word_AX_IMM(emu);
4245 break;
4246 case 0x3e:
4247 emu->x86.mode |= SYSMODE_SEGOVR_DS;
4248 break;
4249 case 0x3f:
4250 emu->x86.R_AX = aas_word(emu, emu->x86.R_AX);
4251 break;
4253 case 0x40:
4254 common_inc_word_long(emu, &emu->x86.register_a);
4255 break;
4256 case 0x41:
4257 common_inc_word_long(emu, &emu->x86.register_c);
4258 break;
4259 case 0x42:
4260 common_inc_word_long(emu, &emu->x86.register_d);
4261 break;
4262 case 0x43:
4263 common_inc_word_long(emu, &emu->x86.register_b);
4264 break;
4265 case 0x44:
4266 common_inc_word_long(emu, &emu->x86.register_sp);
4267 break;
4268 case 0x45:
4269 common_inc_word_long(emu, &emu->x86.register_bp);
4270 break;
4271 case 0x46:
4272 common_inc_word_long(emu, &emu->x86.register_si);
4273 break;
4274 case 0x47:
4275 common_inc_word_long(emu, &emu->x86.register_di);
4276 break;
4278 case 0x48:
4279 common_dec_word_long(emu, &emu->x86.register_a);
4280 break;
4281 case 0x49:
4282 common_dec_word_long(emu, &emu->x86.register_c);
4283 break;
4284 case 0x4a:
4285 common_dec_word_long(emu, &emu->x86.register_d);
4286 break;
4287 case 0x4b:
4288 common_dec_word_long(emu, &emu->x86.register_b);
4289 break;
4290 case 0x4c:
4291 common_dec_word_long(emu, &emu->x86.register_sp);
4292 break;
4293 case 0x4d:
4294 common_dec_word_long(emu, &emu->x86.register_bp);
4295 break;
4296 case 0x4e:
4297 common_dec_word_long(emu, &emu->x86.register_si);
4298 break;
4299 case 0x4f:
4300 common_dec_word_long(emu, &emu->x86.register_di);
4301 break;
4303 case 0x50:
4304 common_push_word_long(emu, &emu->x86.register_a);
4305 break;
4306 case 0x51:
4307 common_push_word_long(emu, &emu->x86.register_c);
4308 break;
4309 case 0x52:
4310 common_push_word_long(emu, &emu->x86.register_d);
4311 break;
4312 case 0x53:
4313 common_push_word_long(emu, &emu->x86.register_b);
4314 break;
4315 case 0x54:
4316 common_push_word_long(emu, &emu->x86.register_sp);
4317 break;
4318 case 0x55:
4319 common_push_word_long(emu, &emu->x86.register_bp);
4320 break;
4321 case 0x56:
4322 common_push_word_long(emu, &emu->x86.register_si);
4323 break;
4324 case 0x57:
4325 common_push_word_long(emu, &emu->x86.register_di);
4326 break;
4328 case 0x58:
4329 common_pop_word_long(emu, &emu->x86.register_a);
4330 break;
4331 case 0x59:
4332 common_pop_word_long(emu, &emu->x86.register_c);
4333 break;
4334 case 0x5a:
4335 common_pop_word_long(emu, &emu->x86.register_d);
4336 break;
4337 case 0x5b:
4338 common_pop_word_long(emu, &emu->x86.register_b);
4339 break;
4340 case 0x5c:
4341 common_pop_word_long(emu, &emu->x86.register_sp);
4342 break;
4343 case 0x5d:
4344 common_pop_word_long(emu, &emu->x86.register_bp);
4345 break;
4346 case 0x5e:
4347 common_pop_word_long(emu, &emu->x86.register_si);
4348 break;
4349 case 0x5f:
4350 common_pop_word_long(emu, &emu->x86.register_di);
4351 break;
4353 case 0x60:
4354 x86emuOp_push_all(emu);
4355 break;
4356 case 0x61:
4357 x86emuOp_pop_all(emu);
4358 break;
4359 /* 0x62 bound */
4360 /* 0x63 arpl */
4361 case 0x64:
4362 emu->x86.mode |= SYSMODE_SEGOVR_FS;
4363 break;
4364 case 0x65:
4365 emu->x86.mode |= SYSMODE_SEGOVR_GS;
4366 break;
4367 case 0x66:
4368 emu->x86.mode |= SYSMODE_PREFIX_DATA;
4369 break;
4370 case 0x67:
4371 emu->x86.mode |= SYSMODE_PREFIX_ADDR;
4372 break;
4374 case 0x68:
4375 x86emuOp_push_word_IMM(emu);
4376 break;
4377 case 0x69:
4378 common_imul_imm(emu, false);
4379 break;
4380 case 0x6a:
4381 x86emuOp_push_byte_IMM(emu);
4382 break;
4383 case 0x6b:
4384 common_imul_imm(emu, true);
4385 break;
4386 case 0x6c:
4387 ins(emu, 1);
4388 break;
4389 case 0x6d:
4390 x86emuOp_ins_word(emu);
4391 break;
4392 case 0x6e:
4393 outs(emu, 1);
4394 break;
4395 case 0x6f:
4396 x86emuOp_outs_word(emu);
4397 break;
4399 case 0x70:
4400 common_jmp_near(emu, ACCESS_FLAG(F_OF));
4401 break;
4402 case 0x71:
4403 common_jmp_near(emu, !ACCESS_FLAG(F_OF));
4404 break;
4405 case 0x72:
4406 common_jmp_near(emu, ACCESS_FLAG(F_CF));
4407 break;
4408 case 0x73:
4409 common_jmp_near(emu, !ACCESS_FLAG(F_CF));
4410 break;
4411 case 0x74:
4412 common_jmp_near(emu, ACCESS_FLAG(F_ZF));
4413 break;
4414 case 0x75:
4415 common_jmp_near(emu, !ACCESS_FLAG(F_ZF));
4416 break;
4417 case 0x76:
4418 common_jmp_near(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
4419 break;
4420 case 0x77:
4421 common_jmp_near(emu, !ACCESS_FLAG(F_CF) && !ACCESS_FLAG(F_ZF));
4422 break;
4424 case 0x78:
4425 common_jmp_near(emu, ACCESS_FLAG(F_SF));
4426 break;
4427 case 0x79:
4428 common_jmp_near(emu, !ACCESS_FLAG(F_SF));
4429 break;
4430 case 0x7a:
4431 common_jmp_near(emu, ACCESS_FLAG(F_PF));
4432 break;
4433 case 0x7b:
4434 common_jmp_near(emu, !ACCESS_FLAG(F_PF));
4435 break;
4436 case 0x7c:
4437 x86emuOp_jump_near_L(emu);
4438 break;
4439 case 0x7d:
4440 x86emuOp_jump_near_NL(emu);
4441 break;
4442 case 0x7e:
4443 x86emuOp_jump_near_LE(emu);
4444 break;
4445 case 0x7f:
4446 x86emuOp_jump_near_NLE(emu);
4447 break;
4449 case 0x80:
4450 x86emuOp_opc80_byte_RM_IMM(emu);
4451 break;
4452 case 0x81:
4453 x86emuOp_opc81_word_RM_IMM(emu);
4454 break;
4455 case 0x82:
4456 x86emuOp_opc82_byte_RM_IMM(emu);
4457 break;
4458 case 0x83:
4459 x86emuOp_opc83_word_RM_IMM(emu);
4460 break;
4461 case 0x84:
4462 common_binop_ns_byte_rm_r(emu, test_byte);
4463 break;
4464 case 0x85:
4465 common_binop_ns_word_long_rm_r(emu, test_word, test_long);
4466 break;
4467 case 0x86:
4468 x86emuOp_xchg_byte_RM_R(emu);
4469 break;
4470 case 0x87:
4471 x86emuOp_xchg_word_RM_R(emu);
4472 break;
4474 case 0x88:
4475 x86emuOp_mov_byte_RM_R(emu);
4476 break;
4477 case 0x89:
4478 x86emuOp_mov_word_RM_R(emu);
4479 break;
4480 case 0x8a:
4481 x86emuOp_mov_byte_R_RM(emu);
4482 break;
4483 case 0x8b:
4484 x86emuOp_mov_word_R_RM(emu);
4485 break;
4486 case 0x8c:
4487 x86emuOp_mov_word_RM_SR(emu);
4488 break;
4489 case 0x8d:
4490 x86emuOp_lea_word_R_M(emu);
4491 break;
4492 case 0x8e:
4493 x86emuOp_mov_word_SR_RM(emu);
4494 break;
4495 case 0x8f:
4496 x86emuOp_pop_RM(emu);
4497 break;
4499 case 0x90:
4500 /* nop */
4501 break;
4502 case 0x91:
4503 x86emuOp_xchg_word_AX_CX(emu);
4504 break;
4505 case 0x92:
4506 x86emuOp_xchg_word_AX_DX(emu);
4507 break;
4508 case 0x93:
4509 x86emuOp_xchg_word_AX_BX(emu);
4510 break;
4511 case 0x94:
4512 x86emuOp_xchg_word_AX_SP(emu);
4513 break;
4514 case 0x95:
4515 x86emuOp_xchg_word_AX_BP(emu);
4516 break;
4517 case 0x96:
4518 x86emuOp_xchg_word_AX_SI(emu);
4519 break;
4520 case 0x97:
4521 x86emuOp_xchg_word_AX_DI(emu);
4522 break;
4524 case 0x98:
4525 x86emuOp_cbw(emu);
4526 break;
4527 case 0x99:
4528 x86emuOp_cwd(emu);
4529 break;
4530 case 0x9a:
4531 x86emuOp_call_far_IMM(emu);
4532 break;
4533 case 0x9b:
4534 /* wait */
4535 break;
4536 case 0x9c:
4537 x86emuOp_pushf_word(emu);
4538 break;
4539 case 0x9d:
4540 x86emuOp_popf_word(emu);
4541 break;
4542 case 0x9e:
4543 x86emuOp_sahf(emu);
4544 break;
4545 case 0x9f:
4546 x86emuOp_lahf(emu);
4547 break;
4549 case 0xa0:
4550 x86emuOp_mov_AL_M_IMM(emu);
4551 break;
4552 case 0xa1:
4553 x86emuOp_mov_AX_M_IMM(emu);
4554 break;
4555 case 0xa2:
4556 x86emuOp_mov_M_AL_IMM(emu);
4557 break;
4558 case 0xa3:
4559 x86emuOp_mov_M_AX_IMM(emu);
4560 break;
4561 case 0xa4:
4562 x86emuOp_movs_byte(emu);
4563 break;
4564 case 0xa5:
4565 x86emuOp_movs_word(emu);
4566 break;
4567 case 0xa6:
4568 x86emuOp_cmps_byte(emu);
4569 break;
4570 case 0xa7:
4571 x86emuOp_cmps_word(emu);
4572 break;
4574 case 0xa8:
4575 test_byte(emu, emu->x86.R_AL, fetch_byte_imm(emu));
4576 break;
4577 case 0xa9:
4578 x86emuOp_test_AX_IMM(emu);
4579 break;
4580 case 0xaa:
4581 x86emuOp_stos_byte(emu);
4582 break;
4583 case 0xab:
4584 x86emuOp_stos_word(emu);
4585 break;
4586 case 0xac:
4587 x86emuOp_lods_byte(emu);
4588 break;
4589 case 0xad:
4590 x86emuOp_lods_word(emu);
4591 break;
4592 case 0xae:
4593 x86emuOp_scas_byte(emu);
4594 break;
4595 case 0xaf:
4596 x86emuOp_scas_word(emu);
4597 break;
4599 case 0xb0:
4600 emu->x86.R_AL = fetch_byte_imm(emu);
4601 break;
4602 case 0xb1:
4603 emu->x86.R_CL = fetch_byte_imm(emu);
4604 break;
4605 case 0xb2:
4606 emu->x86.R_DL = fetch_byte_imm(emu);
4607 break;
4608 case 0xb3:
4609 emu->x86.R_BL = fetch_byte_imm(emu);
4610 break;
4611 case 0xb4:
4612 emu->x86.R_AH = fetch_byte_imm(emu);
4613 break;
4614 case 0xb5:
4615 emu->x86.R_CH = fetch_byte_imm(emu);
4616 break;
4617 case 0xb6:
4618 emu->x86.R_DH = fetch_byte_imm(emu);
4619 break;
4620 case 0xb7:
4621 emu->x86.R_BH = fetch_byte_imm(emu);
4622 break;
4624 case 0xb8:
4625 x86emuOp_mov_word_AX_IMM(emu);
4626 break;
4627 case 0xb9:
4628 x86emuOp_mov_word_CX_IMM(emu);
4629 break;
4630 case 0xba:
4631 x86emuOp_mov_word_DX_IMM(emu);
4632 break;
4633 case 0xbb:
4634 x86emuOp_mov_word_BX_IMM(emu);
4635 break;
4636 case 0xbc:
4637 x86emuOp_mov_word_SP_IMM(emu);
4638 break;
4639 case 0xbd:
4640 x86emuOp_mov_word_BP_IMM(emu);
4641 break;
4642 case 0xbe:
4643 x86emuOp_mov_word_SI_IMM(emu);
4644 break;
4645 case 0xbf:
4646 x86emuOp_mov_word_DI_IMM(emu);
4647 break;
4649 case 0xc0:
4650 x86emuOp_opcC0_byte_RM_MEM(emu);
4651 break;
4652 case 0xc1:
4653 x86emuOp_opcC1_word_RM_MEM(emu);
4654 break;
4655 case 0xc2:
4656 x86emuOp_ret_near_IMM(emu);
4657 break;
4658 case 0xc3:
4659 emu->x86.R_IP = pop_word(emu);
4660 break;
4661 case 0xc4:
4662 common_load_far_pointer(emu, &emu->x86.R_ES);
4663 break;
4664 case 0xc5:
4665 common_load_far_pointer(emu, &emu->x86.R_DS);
4666 break;
4667 case 0xc6:
4668 x86emuOp_mov_byte_RM_IMM(emu);
4669 break;
4670 case 0xc7:
4671 x86emuOp_mov_word_RM_IMM(emu);
4672 break;
4673 case 0xc8:
4674 x86emuOp_enter(emu);
4675 break;
4676 case 0xc9:
4677 x86emuOp_leave(emu);
4678 break;
4679 case 0xca:
4680 x86emuOp_ret_far_IMM(emu);
4681 break;
4682 case 0xcb:
4683 x86emuOp_ret_far(emu);
4684 break;
4685 case 0xcc:
4686 x86emuOp_int3(emu);
4687 break;
4688 case 0xcd:
4689 x86emuOp_int_IMM(emu);
4690 break;
4691 case 0xce:
4692 x86emuOp_into(emu);
4693 break;
4694 case 0xcf:
4695 x86emuOp_iret(emu);
4696 break;
4698 case 0xd0:
4699 x86emuOp_opcD0_byte_RM_1(emu);
4700 break;
4701 case 0xd1:
4702 x86emuOp_opcD1_word_RM_1(emu);
4703 break;
4704 case 0xd2:
4705 x86emuOp_opcD2_byte_RM_CL(emu);
4706 break;
4707 case 0xd3:
4708 x86emuOp_opcD3_word_RM_CL(emu);
4709 break;
4710 case 0xd4:
4711 x86emuOp_aam(emu);
4712 break;
4713 case 0xd5:
4714 x86emuOp_aad(emu);
4715 break;
4716 /* 0xd6 Undocumented SETALC instruction */
4717 case 0xd7:
4718 x86emuOp_xlat(emu);
4719 break;
4720 case 0xd8:
4721 x86emuOp_esc_coprocess_d8(emu);
4722 break;
4723 case 0xd9:
4724 x86emuOp_esc_coprocess_d9(emu);
4725 break;
4726 case 0xda:
4727 x86emuOp_esc_coprocess_da(emu);
4728 break;
4729 case 0xdb:
4730 x86emuOp_esc_coprocess_db(emu);
4731 break;
4732 case 0xdc:
4733 x86emuOp_esc_coprocess_dc(emu);
4734 break;
4735 case 0xdd:
4736 x86emuOp_esc_coprocess_dd(emu);
4737 break;
4738 case 0xde:
4739 x86emuOp_esc_coprocess_de(emu);
4740 break;
4741 case 0xdf:
4742 x86emuOp_esc_coprocess_df(emu);
4743 break;
4745 case 0xe0:
4746 x86emuOp_loopne(emu);
4747 break;
4748 case 0xe1:
4749 x86emuOp_loope(emu);
4750 break;
4751 case 0xe2:
4752 x86emuOp_loop(emu);
4753 break;
4754 case 0xe3:
4755 x86emuOp_jcxz(emu);
4756 break;
4757 case 0xe4:
4758 x86emuOp_in_byte_AL_IMM(emu);
4759 break;
4760 case 0xe5:
4761 x86emuOp_in_word_AX_IMM(emu);
4762 break;
4763 case 0xe6:
4764 x86emuOp_out_byte_IMM_AL(emu);
4765 break;
4766 case 0xe7:
4767 x86emuOp_out_word_IMM_AX(emu);
4768 break;
4770 case 0xe8:
4771 x86emuOp_call_near_IMM(emu);
4772 break;
4773 case 0xe9:
4774 x86emuOp_jump_near_IMM(emu);
4775 break;
4776 case 0xea:
4777 x86emuOp_jump_far_IMM(emu);
4778 break;
4779 case 0xeb:
4780 x86emuOp_jump_byte_IMM(emu);
4781 break;
4782 case 0xec:
4783 x86emuOp_in_byte_AL_DX(emu);
4784 break;
4785 case 0xed:
4786 x86emuOp_in_word_AX_DX(emu);
4787 break;
4788 case 0xee:
4789 x86emuOp_out_byte_DX_AL(emu);
4790 break;
4791 case 0xef:
4792 x86emuOp_out_word_DX_AX(emu);
4793 break;
4795 case 0xf0:
4796 x86emuOp_lock(emu);
4797 break;
4798 case 0xf2:
4799 emu->x86.mode |= SYSMODE_PREFIX_REPNE;
4800 break;
4801 case 0xf3:
4802 emu->x86.mode |= SYSMODE_PREFIX_REPE;
4803 break;
4804 case 0xf4:
4805 X86EMU_halt_sys(emu);
4806 break;
4807 case 0xf5:
4808 x86emuOp_cmc(emu);
4809 break;
4810 case 0xf6:
4811 x86emuOp_opcF6_byte_RM(emu);
4812 break;
4813 case 0xf7:
4814 x86emuOp_opcF7_word_RM(emu);
4815 break;
4817 case 0xf8:
4818 CLEAR_FLAG(F_CF);
4819 break;
4820 case 0xf9:
4821 SET_FLAG(F_CF);
4822 break;
4823 case 0xfa:
4824 CLEAR_FLAG(F_IF);
4825 break;
4826 case 0xfb:
4827 SET_FLAG(F_IF);
4828 break;
4829 case 0xfc:
4830 CLEAR_FLAG(F_DF);
4831 break;
4832 case 0xfd:
4833 SET_FLAG(F_DF);
4834 break;
4835 case 0xfe:
4836 x86emuOp_opcFE_byte_RM(emu);
4837 break;
4838 case 0xff:
4839 x86emuOp_opcFF_word_RM(emu);
4840 break;
4841 default:
4842 X86EMU_halt_sys(emu);
4843 break;
4845 if (op1 != 0x26 && op1 != 0x2e && op1 != 0x36 && op1 != 0x3e &&
4846 (op1 | 3) != 0x67)
4847 emu->x86.mode &= ~SYSMODE_CLRMASK;
4850 static void
4851 common_jmp_long(struct X86EMU *emu, bool cond)
4853 int16_t target;
4855 target = (int16_t) fetch_word_imm(emu);
4856 target += (int16_t) emu->x86.R_IP;
4857 if (cond)
4858 emu->x86.R_IP = (uint16_t) target;
4861 static void
4862 common_set_byte(struct X86EMU *emu, bool cond)
4864 uint32_t destoffset;
4865 uint8_t *destreg, destval;
4867 fetch_decode_modrm(emu);
4868 destval = cond ? 0x01 : 0x00;
4869 if (emu->cur_mod != 3) {
4870 destoffset = decode_rl_address(emu);
4871 store_data_byte(emu, destoffset, destval);
4872 } else {
4873 destreg = decode_rl_byte_register(emu);
4874 *destreg = destval;
4878 static void
4879 common_bitstring32(struct X86EMU *emu, int op)
4881 int bit;
4882 uint32_t srcval, *shiftreg, mask;
4884 fetch_decode_modrm(emu);
4885 shiftreg = decode_rh_long_register(emu);
4886 srcval = decode_and_fetch_long_disp(emu, (int16_t) *shiftreg >> 5);
4887 bit = *shiftreg & 0x1F;
4888 mask = 0x1 << bit;
4889 CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
4891 switch (op) {
4892 case 0:
4893 break;
4894 case 1:
4895 write_back_long(emu, srcval | mask);
4896 break;
4897 case 2:
4898 write_back_long(emu, srcval & ~mask);
4899 break;
4900 case 3:
4901 write_back_long(emu, srcval ^ mask);
4902 break;
4906 static void
4907 common_bitstring16(struct X86EMU *emu, int op)
4909 int bit;
4910 uint16_t srcval, *shiftreg, mask;
4912 fetch_decode_modrm(emu);
4913 shiftreg = decode_rh_word_register(emu);
4914 srcval = decode_and_fetch_word_disp(emu, (int16_t) *shiftreg >> 4);
4915 bit = *shiftreg & 0xF;
4916 mask = 0x1 << bit;
4917 CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
4919 switch (op) {
4920 case 0:
4921 break;
4922 case 1:
4923 write_back_word(emu, srcval | mask);
4924 break;
4925 case 2:
4926 write_back_word(emu, srcval & ~mask);
4927 break;
4928 case 3:
4929 write_back_word(emu, srcval ^ mask);
4930 break;
4934 static void
4935 common_bitstring(struct X86EMU *emu, int op)
4937 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
4938 common_bitstring32(emu, op);
4939 else
4940 common_bitstring16(emu, op);
4943 static void
4944 common_bitsearch32(struct X86EMU *emu, int diff)
4946 uint32_t srcval, *dstreg;
4948 fetch_decode_modrm(emu);
4949 dstreg = decode_rh_long_register(emu);
4950 srcval = decode_and_fetch_long(emu);
4951 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
4952 for (*dstreg = 0; *dstreg < 32; *dstreg += diff) {
4953 if ((srcval >> *dstreg) & 1)
4954 break;
4958 static void
4959 common_bitsearch16(struct X86EMU *emu, int diff)
4961 uint16_t srcval, *dstreg;
4963 fetch_decode_modrm(emu);
4964 dstreg = decode_rh_word_register(emu);
4965 srcval = decode_and_fetch_word(emu);
4966 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
4967 for (*dstreg = 0; *dstreg < 16; *dstreg += diff) {
4968 if ((srcval >> *dstreg) & 1)
4969 break;
4973 static void
4974 common_bitsearch(struct X86EMU *emu, int diff)
4976 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
4977 common_bitsearch32(emu, diff);
4978 else
4979 common_bitsearch16(emu, diff);
4982 static void
4983 common_shift32(struct X86EMU *emu, bool shift_left, bool use_cl)
4985 uint8_t shift;
4986 uint32_t destval, *shiftreg;
4988 fetch_decode_modrm(emu);
4989 shiftreg = decode_rh_long_register(emu);
4990 if (use_cl) {
4991 destval = decode_and_fetch_long(emu);
4992 shift = emu->x86.R_CL;
4993 } else {
4994 destval = decode_and_fetch_long_imm8(emu, &shift);
4996 if (shift_left)
4997 destval = shld_long(emu, destval, *shiftreg, shift);
4998 else
4999 destval = shrd_long(emu, destval, *shiftreg, shift);
5000 write_back_long(emu, destval);
5003 static void
5004 common_shift16(struct X86EMU *emu, bool shift_left, bool use_cl)
5006 uint8_t shift;
5007 uint16_t destval, *shiftreg;
5009 fetch_decode_modrm(emu);
5010 shiftreg = decode_rh_word_register(emu);
5011 if (use_cl) {
5012 destval = decode_and_fetch_word(emu);
5013 shift = emu->x86.R_CL;
5014 } else {
5015 destval = decode_and_fetch_word_imm8(emu, &shift);
5017 if (shift_left)
5018 destval = shld_word(emu, destval, *shiftreg, shift);
5019 else
5020 destval = shrd_word(emu, destval, *shiftreg, shift);
5021 write_back_word(emu, destval);
5024 static void
5025 common_shift(struct X86EMU *emu, bool shift_left, bool use_cl)
5027 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5028 common_shift32(emu, shift_left, use_cl);
5029 else
5030 common_shift16(emu, shift_left, use_cl);
5033 /*----------------------------- Implementation ----------------------------*/
5034 #define xorl(a,b) ((a) && !(b)) || (!(a) && (b))
5036 /****************************************************************************
5037 REMARKS:
5038 Handles opcode 0x0f,0x31
5039 ****************************************************************************/
5040 static void
5041 x86emuOp2_rdtsc(struct X86EMU *emu)
5043 emu->x86.R_EAX = emu->cur_cycles & 0xffffffff;
5044 emu->x86.R_EDX = emu->cur_cycles >> 32;
5046 /****************************************************************************
5047 REMARKS:
5048 Handles opcode 0x0f,0xa0
5049 ****************************************************************************/
5050 static void
5051 x86emuOp2_push_FS(struct X86EMU *emu)
5053 push_word(emu, emu->x86.R_FS);
5055 /****************************************************************************
5056 REMARKS:
5057 Handles opcode 0x0f,0xa1
5058 ****************************************************************************/
5059 static void
5060 x86emuOp2_pop_FS(struct X86EMU *emu)
5062 emu->x86.R_FS = pop_word(emu);
5064 /****************************************************************************
5065 REMARKS:
5066 Handles opcode 0x0f,0xa1
5067 ****************************************************************************/
5068 #if defined(__i386__) || defined(__amd64__)
5069 static void
5070 hw_cpuid(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d)
5072 __asm__ __volatile__("cpuid"
5073 : "=a" (*a), "=b" (*b),
5074 "=c" (*c), "=d" (*d)
5075 : "a" (*a), "c" (*c)
5076 : "cc");
5078 #endif
5079 static void
5080 x86emuOp2_cpuid(struct X86EMU *emu)
5082 #if defined(__i386__) || defined(__amd64__)
5083 hw_cpuid(&emu->x86.R_EAX, &emu->x86.R_EBX, &emu->x86.R_ECX,
5084 &emu->x86.R_EDX);
5085 #endif
5086 switch (emu->x86.R_EAX) {
5087 case 0:
5088 emu->x86.R_EAX = 1;
5089 #if !defined(__i386__) && !defined(__amd64__)
5090 /* "GenuineIntel" */
5091 emu->x86.R_EBX = 0x756e6547;
5092 emu->x86.R_EDX = 0x49656e69;
5093 emu->x86.R_ECX = 0x6c65746e;
5094 #endif
5095 break;
5096 case 1:
5097 #if !defined(__i386__) && !defined(__amd64__)
5098 emu->x86.R_EAX = 0x00000480;
5099 emu->x86.R_EBX = emu->x86.R_ECX = 0;
5100 emu->x86.R_EDX = 0x00000002;
5101 #else
5102 emu->x86.R_EDX &= 0x00000012;
5103 #endif
5104 break;
5105 default:
5106 emu->x86.R_EAX = emu->x86.R_EBX = emu->x86.R_ECX =
5107 emu->x86.R_EDX = 0;
5108 break;
5111 /****************************************************************************
5112 REMARKS:
5113 Handles opcode 0x0f,0xa3
5114 ****************************************************************************/
5115 static void
5116 x86emuOp2_bt_R(struct X86EMU *emu)
5118 common_bitstring(emu, 0);
5120 /****************************************************************************
5121 REMARKS:
5122 Handles opcode 0x0f,0xa4
5123 ****************************************************************************/
5124 static void
5125 x86emuOp2_shld_IMM(struct X86EMU *emu)
5127 common_shift(emu, true, false);
5129 /****************************************************************************
5130 REMARKS:
5131 Handles opcode 0x0f,0xa5
5132 ****************************************************************************/
5133 static void
5134 x86emuOp2_shld_CL(struct X86EMU *emu)
5136 common_shift(emu, true, true);
5138 /****************************************************************************
5139 REMARKS:
5140 Handles opcode 0x0f,0xa8
5141 ****************************************************************************/
5142 static void
5143 x86emuOp2_push_GS(struct X86EMU *emu)
5145 push_word(emu, emu->x86.R_GS);
5147 /****************************************************************************
5148 REMARKS:
5149 Handles opcode 0x0f,0xa9
5150 ****************************************************************************/
5151 static void
5152 x86emuOp2_pop_GS(struct X86EMU *emu)
5154 emu->x86.R_GS = pop_word(emu);
5156 /****************************************************************************
5157 REMARKS:
5158 Handles opcode 0x0f,0xab
5159 ****************************************************************************/
5160 static void
5161 x86emuOp2_bts_R(struct X86EMU *emu)
5163 common_bitstring(emu, 1);
5165 /****************************************************************************
5166 REMARKS:
5167 Handles opcode 0x0f,0xac
5168 ****************************************************************************/
5169 static void
5170 x86emuOp2_shrd_IMM(struct X86EMU *emu)
5172 common_shift(emu, false, false);
5174 /****************************************************************************
5175 REMARKS:
5176 Handles opcode 0x0f,0xad
5177 ****************************************************************************/
5178 static void
5179 x86emuOp2_shrd_CL(struct X86EMU *emu)
5181 common_shift(emu, false, true);
5183 /****************************************************************************
5184 REMARKS:
5185 Handles opcode 0x0f,0xaf
5186 ****************************************************************************/
5187 static void
5188 x86emuOp2_32_imul_R_RM(struct X86EMU *emu)
5190 uint32_t *destreg, srcval;
5191 uint64_t res;
5193 fetch_decode_modrm(emu);
5194 destreg = decode_rh_long_register(emu);
5195 srcval = decode_and_fetch_long(emu);
5196 res = (int32_t) *destreg * (int32_t)srcval;
5197 if (res > 0xffffffff) {
5198 SET_FLAG(F_CF);
5199 SET_FLAG(F_OF);
5200 } else {
5201 CLEAR_FLAG(F_CF);
5202 CLEAR_FLAG(F_OF);
5204 *destreg = (uint32_t) res;
5207 static void
5208 x86emuOp2_16_imul_R_RM(struct X86EMU *emu)
5210 uint16_t *destreg, srcval;
5211 uint32_t res;
5213 fetch_decode_modrm(emu);
5214 destreg = decode_rh_word_register(emu);
5215 srcval = decode_and_fetch_word(emu);
5216 res = (int16_t) * destreg * (int16_t)srcval;
5217 if (res > 0xFFFF) {
5218 SET_FLAG(F_CF);
5219 SET_FLAG(F_OF);
5220 } else {
5221 CLEAR_FLAG(F_CF);
5222 CLEAR_FLAG(F_OF);
5224 *destreg = (uint16_t) res;
5227 static void
5228 x86emuOp2_imul_R_RM(struct X86EMU *emu)
5230 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5231 x86emuOp2_32_imul_R_RM(emu);
5232 else
5233 x86emuOp2_16_imul_R_RM(emu);
5235 /****************************************************************************
5236 REMARKS:
5237 Handles opcode 0x0f,0xb2
5238 ****************************************************************************/
5239 static void
5240 x86emuOp2_lss_R_IMM(struct X86EMU *emu)
5242 common_load_far_pointer(emu, &emu->x86.R_SS);
5244 /****************************************************************************
5245 REMARKS:
5246 Handles opcode 0x0f,0xb3
5247 ****************************************************************************/
5248 static void
5249 x86emuOp2_btr_R(struct X86EMU *emu)
5251 common_bitstring(emu, 2);
5253 /****************************************************************************
5254 REMARKS:
5255 Handles opcode 0x0f,0xb4
5256 ****************************************************************************/
5257 static void
5258 x86emuOp2_lfs_R_IMM(struct X86EMU *emu)
5260 common_load_far_pointer(emu, &emu->x86.R_FS);
5262 /****************************************************************************
5263 REMARKS:
5264 Handles opcode 0x0f,0xb5
5265 ****************************************************************************/
5266 static void
5267 x86emuOp2_lgs_R_IMM(struct X86EMU *emu)
5269 common_load_far_pointer(emu, &emu->x86.R_GS);
5271 /****************************************************************************
5272 REMARKS:
5273 Handles opcode 0x0f,0xb6
5274 ****************************************************************************/
5275 static void
5276 x86emuOp2_32_movzx_byte_R_RM(struct X86EMU *emu)
5278 uint32_t *destreg;
5280 fetch_decode_modrm(emu);
5281 destreg = decode_rh_long_register(emu);
5282 *destreg = decode_and_fetch_byte(emu);
5285 static void
5286 x86emuOp2_16_movzx_byte_R_RM(struct X86EMU *emu)
5288 uint16_t *destreg;
5290 fetch_decode_modrm(emu);
5291 destreg = decode_rh_word_register(emu);
5292 *destreg = decode_and_fetch_byte(emu);
5295 static void
5296 x86emuOp2_movzx_byte_R_RM(struct X86EMU *emu)
5298 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5299 x86emuOp2_32_movzx_byte_R_RM(emu);
5300 else
5301 x86emuOp2_16_movzx_byte_R_RM(emu);
5303 /****************************************************************************
5304 REMARKS:
5305 Handles opcode 0x0f,0xb7
5306 ****************************************************************************/
5307 static void
5308 x86emuOp2_movzx_word_R_RM(struct X86EMU *emu)
5310 uint32_t *destreg;
5312 fetch_decode_modrm(emu);
5313 destreg = decode_rh_long_register(emu);
5314 *destreg = decode_and_fetch_word(emu);
5316 /****************************************************************************
5317 REMARKS:
5318 Handles opcode 0x0f,0xba
5319 ****************************************************************************/
5320 static void
5321 x86emuOp2_32_btX_I(struct X86EMU *emu)
5323 int bit;
5324 uint32_t srcval, mask;
5325 uint8_t shift;
5327 fetch_decode_modrm(emu);
5328 if (emu->cur_rh < 4)
5329 X86EMU_halt_sys(emu);
5331 srcval = decode_and_fetch_long_imm8(emu, &shift);
5332 bit = shift & 0x1F;
5333 mask = (0x1 << bit);
5335 switch (emu->cur_rh) {
5336 case 5:
5337 write_back_long(emu, srcval | mask);
5338 break;
5339 case 6:
5340 write_back_long(emu, srcval & ~mask);
5341 break;
5342 case 7:
5343 write_back_long(emu, srcval ^ mask);
5344 break;
5346 CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5349 static void
5350 x86emuOp2_16_btX_I(struct X86EMU *emu)
5352 int bit;
5354 uint16_t srcval, mask;
5355 uint8_t shift;
5357 fetch_decode_modrm(emu);
5358 if (emu->cur_rh < 4)
5359 X86EMU_halt_sys(emu);
5361 srcval = decode_and_fetch_word_imm8(emu, &shift);
5362 bit = shift & 0xF;
5363 mask = (0x1 << bit);
5364 switch (emu->cur_rh) {
5365 case 5:
5366 write_back_word(emu, srcval | mask);
5367 break;
5368 case 6:
5369 write_back_word(emu, srcval & ~mask);
5370 break;
5371 case 7:
5372 write_back_word(emu, srcval ^ mask);
5373 break;
5375 CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5378 static void
5379 x86emuOp2_btX_I(struct X86EMU *emu)
5381 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5382 x86emuOp2_32_btX_I(emu);
5383 else
5384 x86emuOp2_16_btX_I(emu);
5386 /****************************************************************************
5387 REMARKS:
5388 Handles opcode 0x0f,0xbb
5389 ****************************************************************************/
5390 static void
5391 x86emuOp2_btc_R(struct X86EMU *emu)
5393 common_bitstring(emu, 3);
5395 /****************************************************************************
5396 REMARKS:
5397 Handles opcode 0x0f,0xbc
5398 ****************************************************************************/
5399 static void
5400 x86emuOp2_bsf(struct X86EMU *emu)
5402 common_bitsearch(emu, +1);
5404 /****************************************************************************
5405 REMARKS:
5406 Handles opcode 0x0f,0xbd
5407 ****************************************************************************/
5408 static void
5409 x86emuOp2_bsr(struct X86EMU *emu)
5411 common_bitsearch(emu, -1);
5413 /****************************************************************************
5414 REMARKS:
5415 Handles opcode 0x0f,0xbe
5416 ****************************************************************************/
5417 static void
5418 x86emuOp2_32_movsx_byte_R_RM(struct X86EMU *emu)
5420 uint32_t *destreg;
5422 destreg = decode_rh_long_register(emu);
5423 *destreg = (int32_t)(int8_t)decode_and_fetch_byte(emu);
5426 static void
5427 x86emuOp2_16_movsx_byte_R_RM(struct X86EMU *emu)
5429 uint16_t *destreg;
5431 fetch_decode_modrm(emu);
5432 destreg = decode_rh_word_register(emu);
5433 *destreg = (int16_t)(int8_t)decode_and_fetch_byte(emu);
5436 static void
5437 x86emuOp2_movsx_byte_R_RM(struct X86EMU *emu)
5439 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5440 x86emuOp2_32_movsx_byte_R_RM(emu);
5441 else
5442 x86emuOp2_16_movsx_byte_R_RM(emu);
5444 /****************************************************************************
5445 REMARKS:
5446 Handles opcode 0x0f,0xbf
5447 ****************************************************************************/
5448 static void
5449 x86emuOp2_movsx_word_R_RM(struct X86EMU *emu)
5451 uint32_t *destreg;
5453 fetch_decode_modrm(emu);
5454 destreg = decode_rh_long_register(emu);
5455 *destreg = (int32_t)(int16_t)decode_and_fetch_word(emu);
5458 static void
5459 X86EMU_exec_two_byte(struct X86EMU * emu)
5461 uint8_t op2;
5463 op2 = fetch_byte_imm(emu);
5465 switch (op2) {
5466 /* 0x00 Group F (ring 0 PM) */
5467 /* 0x01 Group G (ring 0 PM) */
5468 /* 0x02 lar (ring 0 PM) */
5469 /* 0x03 lsl (ring 0 PM) */
5470 /* 0x05 loadall (undocumented) */
5471 /* 0x06 clts (ring 0 PM) */
5472 /* 0x07 loadall (undocumented) */
5473 /* 0x08 invd (ring 0 PM) */
5474 /* 0x09 wbinvd (ring 0 PM) */
5476 /* 0x20 mov reg32(op2); break;creg (ring 0 PM) */
5477 /* 0x21 mov reg32(op2); break;dreg (ring 0 PM) */
5478 /* 0x22 mov creg(op2); break;reg32 (ring 0 PM) */
5479 /* 0x23 mov dreg(op2); break;reg32 (ring 0 PM) */
5480 /* 0x24 mov reg32(op2); break;treg (ring 0 PM) */
5481 /* 0x26 mov treg(op2); break;reg32 (ring 0 PM) */
5483 case 0x31:
5484 x86emuOp2_rdtsc(emu);
5485 break;
5487 case 0x80:
5488 common_jmp_long(emu, ACCESS_FLAG(F_OF));
5489 break;
5490 case 0x81:
5491 common_jmp_long(emu, !ACCESS_FLAG(F_OF));
5492 break;
5493 case 0x82:
5494 common_jmp_long(emu, ACCESS_FLAG(F_CF));
5495 break;
5496 case 0x83:
5497 common_jmp_long(emu, !ACCESS_FLAG(F_CF));
5498 break;
5499 case 0x84:
5500 common_jmp_long(emu, ACCESS_FLAG(F_ZF));
5501 break;
5502 case 0x85:
5503 common_jmp_long(emu, !ACCESS_FLAG(F_ZF));
5504 break;
5505 case 0x86:
5506 common_jmp_long(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
5507 break;
5508 case 0x87:
5509 common_jmp_long(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)));
5510 break;
5511 case 0x88:
5512 common_jmp_long(emu, ACCESS_FLAG(F_SF));
5513 break;
5514 case 0x89:
5515 common_jmp_long(emu, !ACCESS_FLAG(F_SF));
5516 break;
5517 case 0x8a:
5518 common_jmp_long(emu, ACCESS_FLAG(F_PF));
5519 break;
5520 case 0x8b:
5521 common_jmp_long(emu, !ACCESS_FLAG(F_PF));
5522 break;
5523 case 0x8c:
5524 common_jmp_long(emu, xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)));
5525 break;
5526 case 0x8d:
5527 common_jmp_long(emu, !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF))));
5528 break;
5529 case 0x8e:
5530 common_jmp_long(emu,
5531 (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || ACCESS_FLAG(F_ZF)));
5532 break;
5533 case 0x8f:
5534 common_jmp_long(emu,
5535 !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || ACCESS_FLAG(F_ZF)));
5536 break;
5538 case 0x90:
5539 common_set_byte(emu, ACCESS_FLAG(F_OF));
5540 break;
5541 case 0x91:
5542 common_set_byte(emu, !ACCESS_FLAG(F_OF));
5543 break;
5544 case 0x92:
5545 common_set_byte(emu, ACCESS_FLAG(F_CF));
5546 break;
5547 case 0x93:
5548 common_set_byte(emu, !ACCESS_FLAG(F_CF));
5549 break;
5550 case 0x94:
5551 common_set_byte(emu, ACCESS_FLAG(F_ZF));
5552 break;
5553 case 0x95:
5554 common_set_byte(emu, !ACCESS_FLAG(F_ZF));
5555 break;
5556 case 0x96:
5557 common_set_byte(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
5558 break;
5559 case 0x97:
5560 common_set_byte(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)));
5561 break;
5562 case 0x98:
5563 common_set_byte(emu, ACCESS_FLAG(F_SF));
5564 break;
5565 case 0x99:
5566 common_set_byte(emu, !ACCESS_FLAG(F_SF));
5567 break;
5568 case 0x9a:
5569 common_set_byte(emu, ACCESS_FLAG(F_PF));
5570 break;
5571 case 0x9b:
5572 common_set_byte(emu, !ACCESS_FLAG(F_PF));
5573 break;
5574 case 0x9c:
5575 common_set_byte(emu, xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)));
5576 break;
5577 case 0x9d:
5578 common_set_byte(emu, xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)));
5579 break;
5580 case 0x9e:
5581 common_set_byte(emu,
5582 (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
5583 ACCESS_FLAG(F_ZF)));
5584 break;
5585 case 0x9f:
5586 common_set_byte(emu,
5587 !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
5588 ACCESS_FLAG(F_ZF)));
5589 break;
5591 case 0xa0:
5592 x86emuOp2_push_FS(emu);
5593 break;
5594 case 0xa1:
5595 x86emuOp2_pop_FS(emu);
5596 break;
5597 case 0xa2:
5598 x86emuOp2_cpuid(emu);
5599 break;
5600 case 0xa3:
5601 x86emuOp2_bt_R(emu);
5602 break;
5603 case 0xa4:
5604 x86emuOp2_shld_IMM(emu);
5605 break;
5606 case 0xa5:
5607 x86emuOp2_shld_CL(emu);
5608 break;
5609 case 0xa8:
5610 x86emuOp2_push_GS(emu);
5611 break;
5612 case 0xa9:
5613 x86emuOp2_pop_GS(emu);
5614 break;
5615 case 0xab:
5616 x86emuOp2_bts_R(emu);
5617 break;
5618 case 0xac:
5619 x86emuOp2_shrd_IMM(emu);
5620 break;
5621 case 0xad:
5622 x86emuOp2_shrd_CL(emu);
5623 break;
5624 case 0xaf:
5625 x86emuOp2_imul_R_RM(emu);
5626 break;
5628 /* 0xb0 TODO: cmpxchg */
5629 /* 0xb1 TODO: cmpxchg */
5630 case 0xb2:
5631 x86emuOp2_lss_R_IMM(emu);
5632 break;
5633 case 0xb3:
5634 x86emuOp2_btr_R(emu);
5635 break;
5636 case 0xb4:
5637 x86emuOp2_lfs_R_IMM(emu);
5638 break;
5639 case 0xb5:
5640 x86emuOp2_lgs_R_IMM(emu);
5641 break;
5642 case 0xb6:
5643 x86emuOp2_movzx_byte_R_RM(emu);
5644 break;
5645 case 0xb7:
5646 x86emuOp2_movzx_word_R_RM(emu);
5647 break;
5648 case 0xba:
5649 x86emuOp2_btX_I(emu);
5650 break;
5651 case 0xbb:
5652 x86emuOp2_btc_R(emu);
5653 break;
5654 case 0xbc:
5655 x86emuOp2_bsf(emu);
5656 break;
5657 case 0xbd:
5658 x86emuOp2_bsr(emu);
5659 break;
5660 case 0xbe:
5661 x86emuOp2_movsx_byte_R_RM(emu);
5662 break;
5663 case 0xbf:
5664 x86emuOp2_movsx_word_R_RM(emu);
5665 break;
5667 /* 0xc0 TODO: xadd */
5668 /* 0xc1 TODO: xadd */
5669 /* 0xc8 TODO: bswap */
5670 /* 0xc9 TODO: bswap */
5671 /* 0xca TODO: bswap */
5672 /* 0xcb TODO: bswap */
5673 /* 0xcc TODO: bswap */
5674 /* 0xcd TODO: bswap */
5675 /* 0xce TODO: bswap */
5676 /* 0xcf TODO: bswap */
5678 default:
5679 X86EMU_halt_sys(emu);
5680 break;
5685 * Carry Chain Calculation
5687 * This represents a somewhat expensive calculation which is
5688 * apparently required to emulate the setting of the OF and AF flag.
5689 * The latter is not so important, but the former is. The overflow
5690 * flag is the XOR of the top two bits of the carry chain for an
5691 * addition (similar for subtraction). Since we do not want to
5692 * simulate the addition in a bitwise manner, we try to calculate the
5693 * carry chain given the two operands and the result.
5695 * So, given the following table, which represents the addition of two
5696 * bits, we can derive a formula for the carry chain.
5698 * a b cin r cout
5699 * 0 0 0 0 0
5700 * 0 0 1 1 0
5701 * 0 1 0 1 0
5702 * 0 1 1 0 1
5703 * 1 0 0 1 0
5704 * 1 0 1 0 1
5705 * 1 1 0 0 1
5706 * 1 1 1 1 1
5708 * Construction of table for cout:
5710 * ab
5711 * r \ 00 01 11 10
5712 * |------------------
5713 * 0 | 0 1 1 1
5714 * 1 | 0 0 1 0
5716 * By inspection, one gets: cc = ab + r'(a + b)
5718 * That represents alot of operations, but NO CHOICE....
5720 * Borrow Chain Calculation.
5722 * The following table represents the subtraction of two bits, from
5723 * which we can derive a formula for the borrow chain.
5725 * a b bin r bout
5726 * 0 0 0 0 0
5727 * 0 0 1 1 1
5728 * 0 1 0 1 1
5729 * 0 1 1 0 1
5730 * 1 0 0 1 0
5731 * 1 0 1 0 0
5732 * 1 1 0 0 0
5733 * 1 1 1 1 1
5735 * Construction of table for cout:
5737 * ab
5738 * r \ 00 01 11 10
5739 * |------------------
5740 * 0 | 0 1 0 0
5741 * 1 | 1 1 1 0
5743 * By inspection, one gets: bc = a'b + r(a' + b)
5745 ****************************************************************************/
5747 /*------------------------- Global Variables ------------------------------*/
5749 static uint32_t x86emu_parity_tab[8] =
5751 0x96696996,
5752 0x69969669,
5753 0x69969669,
5754 0x96696996,
5755 0x69969669,
5756 0x96696996,
5757 0x96696996,
5758 0x69969669,
5760 #define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
5761 #define XOR2(x) (((x) ^ ((x)>>1)) & 0x1)
5763 /****************************************************************************
5764 REMARKS:
5765 Implements the AAA instruction and side effects.
5766 ****************************************************************************/
5767 static uint16_t
5768 aaa_word(struct X86EMU *emu, uint16_t d)
5770 uint16_t res;
5771 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
5772 d += 0x6;
5773 d += 0x100;
5774 SET_FLAG(F_AF);
5775 SET_FLAG(F_CF);
5776 } else {
5777 CLEAR_FLAG(F_CF);
5778 CLEAR_FLAG(F_AF);
5780 res = (uint16_t) (d & 0xFF0F);
5781 CLEAR_FLAG(F_SF);
5782 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
5783 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
5784 return res;
5786 /****************************************************************************
5787 REMARKS:
5788 Implements the AAA instruction and side effects.
5789 ****************************************************************************/
5790 static uint16_t
5791 aas_word(struct X86EMU *emu, uint16_t d)
5793 uint16_t res;
5794 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
5795 d -= 0x6;
5796 d -= 0x100;
5797 SET_FLAG(F_AF);
5798 SET_FLAG(F_CF);
5799 } else {
5800 CLEAR_FLAG(F_CF);
5801 CLEAR_FLAG(F_AF);
5803 res = (uint16_t) (d & 0xFF0F);
5804 CLEAR_FLAG(F_SF);
5805 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
5806 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
5807 return res;
5809 /****************************************************************************
5810 REMARKS:
5811 Implements the AAD instruction and side effects.
5812 ****************************************************************************/
5813 static uint16_t
5814 aad_word(struct X86EMU *emu, uint16_t d)
5816 uint16_t l;
5817 uint8_t hb, lb;
5819 hb = (uint8_t) ((d >> 8) & 0xff);
5820 lb = (uint8_t) ((d & 0xff));
5821 l = (uint16_t) ((lb + 10 * hb) & 0xFF);
5823 CLEAR_FLAG(F_CF);
5824 CLEAR_FLAG(F_AF);
5825 CLEAR_FLAG(F_OF);
5826 CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
5827 CONDITIONAL_SET_FLAG(l == 0, F_ZF);
5828 CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
5829 return l;
5831 /****************************************************************************
5832 REMARKS:
5833 Implements the AAM instruction and side effects.
5834 ****************************************************************************/
5835 static uint16_t
5836 aam_word(struct X86EMU *emu, uint8_t d)
5838 uint16_t h, l;
5840 h = (uint16_t) (d / 10);
5841 l = (uint16_t) (d % 10);
5842 l |= (uint16_t) (h << 8);
5844 CLEAR_FLAG(F_CF);
5845 CLEAR_FLAG(F_AF);
5846 CLEAR_FLAG(F_OF);
5847 CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
5848 CONDITIONAL_SET_FLAG(l == 0, F_ZF);
5849 CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
5850 return l;
5852 /****************************************************************************
5853 REMARKS:
5854 Implements the ADC instruction and side effects.
5855 ****************************************************************************/
5856 static uint8_t
5857 adc_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
5859 uint32_t res; /* all operands in native machine order */
5860 uint32_t cc;
5862 if (ACCESS_FLAG(F_CF))
5863 res = 1 + d + s;
5864 else
5865 res = d + s;
5867 CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
5868 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
5869 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
5870 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
5872 /* calculate the carry chain SEE NOTE AT TOP. */
5873 cc = (s & d) | ((~res) & (s | d));
5874 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
5875 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
5876 return (uint8_t) res;
5878 /****************************************************************************
5879 REMARKS:
5880 Implements the ADC instruction and side effects.
5881 ****************************************************************************/
5882 static uint16_t
5883 adc_word(struct X86EMU *emu, uint16_t d, uint16_t s)
5885 uint32_t res; /* all operands in native machine order */
5886 uint32_t cc;
5888 if (ACCESS_FLAG(F_CF))
5889 res = 1 + d + s;
5890 else
5891 res = d + s;
5893 CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
5894 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
5895 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
5896 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
5898 /* calculate the carry chain SEE NOTE AT TOP. */
5899 cc = (s & d) | ((~res) & (s | d));
5900 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
5901 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
5902 return (uint16_t) res;
5904 /****************************************************************************
5905 REMARKS:
5906 Implements the ADC instruction and side effects.
5907 ****************************************************************************/
5908 static uint32_t
5909 adc_long(struct X86EMU *emu, uint32_t d, uint32_t s)
5911 uint32_t lo; /* all operands in native machine order */
5912 uint32_t hi;
5913 uint32_t res;
5914 uint32_t cc;
5916 if (ACCESS_FLAG(F_CF)) {
5917 lo = 1 + (d & 0xFFFF) + (s & 0xFFFF);
5918 res = 1 + d + s;
5919 } else {
5920 lo = (d & 0xFFFF) + (s & 0xFFFF);
5921 res = d + s;
5923 hi = (lo >> 16) + (d >> 16) + (s >> 16);
5925 CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
5926 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
5927 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
5928 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
5930 /* calculate the carry chain SEE NOTE AT TOP. */
5931 cc = (s & d) | ((~res) & (s | d));
5932 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
5933 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
5934 return res;
5936 /****************************************************************************
5937 REMARKS:
5938 Implements the ADD instruction and side effects.
5939 ****************************************************************************/
5940 static uint8_t
5941 add_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
5943 uint32_t res; /* all operands in native machine order */
5944 uint32_t cc;
5946 res = d + s;
5947 CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
5948 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
5949 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
5950 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
5952 /* calculate the carry chain SEE NOTE AT TOP. */
5953 cc = (s & d) | ((~res) & (s | d));
5954 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
5955 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
5956 return (uint8_t) res;
5958 /****************************************************************************
5959 REMARKS:
5960 Implements the ADD instruction and side effects.
5961 ****************************************************************************/
5962 static uint16_t
5963 add_word(struct X86EMU *emu, uint16_t d, uint16_t s)
5965 uint32_t res; /* all operands in native machine order */
5966 uint32_t cc;
5968 res = d + s;
5969 CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
5970 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
5971 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
5972 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
5974 /* calculate the carry chain SEE NOTE AT TOP. */
5975 cc = (s & d) | ((~res) & (s | d));
5976 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
5977 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
5978 return (uint16_t) res;
5980 /****************************************************************************
5981 REMARKS:
5982 Implements the ADD instruction and side effects.
5983 ****************************************************************************/
5984 static uint32_t
5985 add_long(struct X86EMU *emu, uint32_t d, uint32_t s)
5987 uint32_t lo; /* all operands in native machine order */
5988 uint32_t hi;
5989 uint32_t res;
5990 uint32_t cc;
5992 lo = (d & 0xFFFF) + (s & 0xFFFF);
5993 res = d + s;
5994 hi = (lo >> 16) + (d >> 16) + (s >> 16);
5996 CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
5997 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
5998 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
5999 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6001 /* calculate the carry chain SEE NOTE AT TOP. */
6002 cc = (s & d) | ((~res) & (s | d));
6003 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
6004 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6006 return res;
6008 /****************************************************************************
6009 REMARKS:
6010 Implements the AND instruction and side effects.
6011 ****************************************************************************/
6012 static uint8_t
6013 and_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
6015 uint8_t res; /* all operands in native machine order */
6017 res = d & s;
6019 /* set the flags */
6020 CLEAR_FLAG(F_OF);
6021 CLEAR_FLAG(F_CF);
6022 CLEAR_FLAG(F_AF);
6023 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6024 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6025 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6026 return res;
6028 /****************************************************************************
6029 REMARKS:
6030 Implements the AND instruction and side effects.
6031 ****************************************************************************/
6032 static uint16_t
6033 and_word(struct X86EMU *emu, uint16_t d, uint16_t s)
6035 uint16_t res; /* all operands in native machine order */
6037 res = d & s;
6039 /* set the flags */
6040 CLEAR_FLAG(F_OF);
6041 CLEAR_FLAG(F_CF);
6042 CLEAR_FLAG(F_AF);
6043 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6044 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6045 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6046 return res;
6048 /****************************************************************************
6049 REMARKS:
6050 Implements the AND instruction and side effects.
6051 ****************************************************************************/
6052 static uint32_t
6053 and_long(struct X86EMU *emu, uint32_t d, uint32_t s)
6055 uint32_t res; /* all operands in native machine order */
6057 res = d & s;
6059 /* set the flags */
6060 CLEAR_FLAG(F_OF);
6061 CLEAR_FLAG(F_CF);
6062 CLEAR_FLAG(F_AF);
6063 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6064 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6065 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6066 return res;
6068 /****************************************************************************
6069 REMARKS:
6070 Implements the CMP instruction and side effects.
6071 ****************************************************************************/
6072 static uint8_t
6073 cmp_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
6075 uint32_t res; /* all operands in native machine order */
6076 uint32_t bc;
6078 res = d - s;
6079 CLEAR_FLAG(F_CF);
6080 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6081 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6082 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6084 /* calculate the borrow chain. See note at top */
6085 bc = (res & (~d | s)) | (~d & s);
6086 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
6087 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6088 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6089 return d;
6092 static void
6093 cmp_byte_no_return(struct X86EMU *emu, uint8_t d, uint8_t s)
6095 cmp_byte(emu, d, s);
6097 /****************************************************************************
6098 REMARKS:
6099 Implements the CMP instruction and side effects.
6100 ****************************************************************************/
6101 static uint16_t
6102 cmp_word(struct X86EMU *emu, uint16_t d, uint16_t s)
6104 uint32_t res; /* all operands in native machine order */
6105 uint32_t bc;
6107 res = d - s;
6108 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6109 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6110 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6112 /* calculate the borrow chain. See note at top */
6113 bc = (res & (~d | s)) | (~d & s);
6114 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
6115 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6116 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6117 return d;
6120 static void
6121 cmp_word_no_return(struct X86EMU *emu, uint16_t d, uint16_t s)
6123 cmp_word(emu, d, s);
6125 /****************************************************************************
6126 REMARKS:
6127 Implements the CMP instruction and side effects.
6128 ****************************************************************************/
6129 static uint32_t
6130 cmp_long(struct X86EMU *emu, uint32_t d, uint32_t s)
6132 uint32_t res; /* all operands in native machine order */
6133 uint32_t bc;
6135 res = d - s;
6136 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6137 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6138 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6140 /* calculate the borrow chain. See note at top */
6141 bc = (res & (~d | s)) | (~d & s);
6142 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
6143 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6144 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6145 return d;
6148 static void
6149 cmp_long_no_return(struct X86EMU *emu, uint32_t d, uint32_t s)
6151 cmp_long(emu, d, s);
6153 /****************************************************************************
6154 REMARKS:
6155 Implements the DAA instruction and side effects.
6156 ****************************************************************************/
6157 static uint8_t
6158 daa_byte(struct X86EMU *emu, uint8_t d)
6160 uint32_t res = d;
6161 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
6162 res += 6;
6163 SET_FLAG(F_AF);
6165 if (res > 0x9F || ACCESS_FLAG(F_CF)) {
6166 res += 0x60;
6167 SET_FLAG(F_CF);
6169 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6170 CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF);
6171 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6172 return (uint8_t) res;
6174 /****************************************************************************
6175 REMARKS:
6176 Implements the DAS instruction and side effects.
6177 ****************************************************************************/
6178 static uint8_t
6179 das_byte(struct X86EMU *emu, uint8_t d)
6181 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
6182 d -= 6;
6183 SET_FLAG(F_AF);
6185 if (d > 0x9F || ACCESS_FLAG(F_CF)) {
6186 d -= 0x60;
6187 SET_FLAG(F_CF);
6189 CONDITIONAL_SET_FLAG(d & 0x80, F_SF);
6190 CONDITIONAL_SET_FLAG(d == 0, F_ZF);
6191 CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF);
6192 return d;
6194 /****************************************************************************
6195 REMARKS:
6196 Implements the DEC instruction and side effects.
6197 ****************************************************************************/
6198 static uint8_t
6199 dec_byte(struct X86EMU *emu, uint8_t d)
6201 uint32_t res; /* all operands in native machine order */
6202 uint32_t bc;
6204 res = d - 1;
6205 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6206 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6207 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6209 /* calculate the borrow chain. See note at top */
6210 /* based on sub_byte, uses s==1. */
6211 bc = (res & (~d | 1)) | (~d & 1);
6212 /* carry flag unchanged */
6213 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6214 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6215 return (uint8_t) res;
6217 /****************************************************************************
6218 REMARKS:
6219 Implements the DEC instruction and side effects.
6220 ****************************************************************************/
6221 static uint16_t
6222 dec_word(struct X86EMU *emu, uint16_t d)
6224 uint32_t res; /* all operands in native machine order */
6225 uint32_t bc;
6227 res = d - 1;
6228 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6229 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6230 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6232 /* calculate the borrow chain. See note at top */
6233 /* based on the sub_byte routine, with s==1 */
6234 bc = (res & (~d | 1)) | (~d & 1);
6235 /* carry flag unchanged */
6236 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6237 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6238 return (uint16_t) res;
6240 /****************************************************************************
6241 REMARKS:
6242 Implements the DEC instruction and side effects.
6243 ****************************************************************************/
6244 static uint32_t
6245 dec_long(struct X86EMU *emu, uint32_t d)
6247 uint32_t res; /* all operands in native machine order */
6248 uint32_t bc;
6250 res = d - 1;
6252 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6253 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6254 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6256 /* calculate the borrow chain. See note at top */
6257 bc = (res & (~d | 1)) | (~d & 1);
6258 /* carry flag unchanged */
6259 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6260 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6261 return res;
6263 /****************************************************************************
6264 REMARKS:
6265 Implements the INC instruction and side effects.
6266 ****************************************************************************/
6267 static uint8_t
6268 inc_byte(struct X86EMU *emu, uint8_t d)
6270 uint32_t res; /* all operands in native machine order */
6271 uint32_t cc;
6273 res = d + 1;
6274 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6275 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6276 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6278 /* calculate the carry chain SEE NOTE AT TOP. */
6279 cc = ((1 & d) | (~res)) & (1 | d);
6280 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
6281 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6282 return (uint8_t) res;
6284 /****************************************************************************
6285 REMARKS:
6286 Implements the INC instruction and side effects.
6287 ****************************************************************************/
6288 static uint16_t
6289 inc_word(struct X86EMU *emu, uint16_t d)
6291 uint32_t res; /* all operands in native machine order */
6292 uint32_t cc;
6294 res = d + 1;
6295 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6296 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6297 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6299 /* calculate the carry chain SEE NOTE AT TOP. */
6300 cc = (1 & d) | ((~res) & (1 | d));
6301 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
6302 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6303 return (uint16_t) res;
6305 /****************************************************************************
6306 REMARKS:
6307 Implements the INC instruction and side effects.
6308 ****************************************************************************/
6309 static uint32_t
6310 inc_long(struct X86EMU *emu, uint32_t d)
6312 uint32_t res; /* all operands in native machine order */
6313 uint32_t cc;
6315 res = d + 1;
6316 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6317 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6318 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6320 /* calculate the carry chain SEE NOTE AT TOP. */
6321 cc = (1 & d) | ((~res) & (1 | d));
6322 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
6323 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6324 return res;
6326 /****************************************************************************
6327 REMARKS:
6328 Implements the OR instruction and side effects.
6329 ****************************************************************************/
6330 static uint8_t
6331 or_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
6333 uint8_t res; /* all operands in native machine order */
6335 res = d | s;
6336 CLEAR_FLAG(F_OF);
6337 CLEAR_FLAG(F_CF);
6338 CLEAR_FLAG(F_AF);
6339 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6340 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6341 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6342 return res;
6344 /****************************************************************************
6345 REMARKS:
6346 Implements the OR instruction and side effects.
6347 ****************************************************************************/
6348 static uint16_t
6349 or_word(struct X86EMU *emu, uint16_t d, uint16_t s)
6351 uint16_t res; /* all operands in native machine order */
6353 res = d | s;
6354 /* set the carry flag to be bit 8 */
6355 CLEAR_FLAG(F_OF);
6356 CLEAR_FLAG(F_CF);
6357 CLEAR_FLAG(F_AF);
6358 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6359 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6360 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6361 return res;
6363 /****************************************************************************
6364 REMARKS:
6365 Implements the OR instruction and side effects.
6366 ****************************************************************************/
6367 static uint32_t
6368 or_long(struct X86EMU *emu, uint32_t d, uint32_t s)
6370 uint32_t res; /* all operands in native machine order */
6372 res = d | s;
6374 /* set the carry flag to be bit 8 */
6375 CLEAR_FLAG(F_OF);
6376 CLEAR_FLAG(F_CF);
6377 CLEAR_FLAG(F_AF);
6378 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6379 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6380 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6381 return res;
6383 /****************************************************************************
6384 REMARKS:
6385 Implements the OR instruction and side effects.
6386 ****************************************************************************/
6387 static uint8_t
6388 neg_byte(struct X86EMU *emu, uint8_t s)
6390 uint8_t res;
6391 uint8_t bc;
6393 CONDITIONAL_SET_FLAG(s != 0, F_CF);
6394 res = (uint8_t) - s;
6395 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6396 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6397 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6398 /* calculate the borrow chain --- modified such that d=0.
6399 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for
6400 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6401 * res&0xfff... == res. Similarly ~d&s == s. So the simplified
6402 * result is: */
6403 bc = res | s;
6404 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6405 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6406 return res;
6408 /****************************************************************************
6409 REMARKS:
6410 Implements the OR instruction and side effects.
6411 ****************************************************************************/
6412 static uint16_t
6413 neg_word(struct X86EMU *emu, uint16_t s)
6415 uint16_t res;
6416 uint16_t bc;
6418 CONDITIONAL_SET_FLAG(s != 0, F_CF);
6419 res = (uint16_t) - s;
6420 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6421 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6422 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6424 /* calculate the borrow chain --- modified such that d=0.
6425 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for
6426 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6427 * res&0xfff... == res. Similarly ~d&s == s. So the simplified
6428 * result is: */
6429 bc = res | s;
6430 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6431 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6432 return res;
6434 /****************************************************************************
6435 REMARKS:
6436 Implements the OR instruction and side effects.
6437 ****************************************************************************/
6438 static uint32_t
6439 neg_long(struct X86EMU *emu, uint32_t s)
6441 uint32_t res;
6442 uint32_t bc;
6444 CONDITIONAL_SET_FLAG(s != 0, F_CF);
6445 res = (uint32_t) - s;
6446 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6447 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6448 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6450 /* calculate the borrow chain --- modified such that d=0.
6451 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for
6452 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6453 * res&0xfff... == res. Similarly ~d&s == s. So the simplified
6454 * result is: */
6455 bc = res | s;
6456 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6457 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6458 return res;
6460 /****************************************************************************
6461 REMARKS:
6462 Implements the RCL instruction and side effects.
6463 ****************************************************************************/
6464 static uint8_t
6465 rcl_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
6467 unsigned int res, cnt, mask, cf;
6469 /* s is the rotate distance. It varies from 0 - 8. */
6470 /* have
6472 * CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
6474 * want to rotate through the carry by "s" bits. We could loop, but
6475 * that's inefficient. So the width is 9, and we split into three
6476 * parts:
6478 * The new carry flag (was B_n) the stuff in B_n-1 .. B_0 the stuff in
6479 * B_7 .. B_n+1
6481 * The new rotate is done mod 9, and given this, for a rotation of n bits
6482 * (mod 9) the new carry flag is then located n bits from the MSB.
6483 * The low part is then shifted up cnt bits, and the high part is or'd
6484 * in. Using CAPS for new values, and lowercase for the original
6485 * values, this can be expressed as:
6487 * IF n > 0 1) CF <- b_(8-n) 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0
6488 * 3) B_(n-1) <- cf 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */
6489 res = d;
6490 if ((cnt = s % 9) != 0) {
6491 /* extract the new CARRY FLAG. */
6492 /* CF <- b_(8-n) */
6493 cf = (d >> (8 - cnt)) & 0x1;
6495 /* get the low stuff which rotated into the range B_7 .. B_cnt */
6496 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 */
6497 /* note that the right hand side done by the mask */
6498 res = (d << cnt) & 0xff;
6500 /* now the high stuff which rotated around into the positions
6501 * B_cnt-2 .. B_0 */
6502 /* B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */
6503 /* shift it downward, 7-(n-2) = 9-n positions. and mask off
6504 * the result before or'ing in. */
6505 mask = (1 << (cnt - 1)) - 1;
6506 res |= (d >> (9 - cnt)) & mask;
6508 /* if the carry flag was set, or it in. */
6509 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
6510 /* B_(n-1) <- cf */
6511 res |= 1 << (cnt - 1);
6513 /* set the new carry flag, based on the variable "cf" */
6514 CONDITIONAL_SET_FLAG(cf, F_CF);
6515 /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and
6516 * the most significant bit. Blecck. */
6517 /* parenthesized this expression since it appears to be
6518 * causing OF to be misset */
6519 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
6520 F_OF);
6523 return (uint8_t) res;
6525 /****************************************************************************
6526 REMARKS:
6527 Implements the RCL instruction and side effects.
6528 ****************************************************************************/
6529 static uint16_t
6530 rcl_word(struct X86EMU *emu, uint16_t d, uint8_t s)
6532 unsigned int res, cnt, mask, cf;
6534 res = d;
6535 if ((cnt = s % 17) != 0) {
6536 cf = (d >> (16 - cnt)) & 0x1;
6537 res = (d << cnt) & 0xffff;
6538 mask = (1 << (cnt - 1)) - 1;
6539 res |= (d >> (17 - cnt)) & mask;
6540 if (ACCESS_FLAG(F_CF)) {
6541 res |= 1 << (cnt - 1);
6543 CONDITIONAL_SET_FLAG(cf, F_CF);
6544 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
6545 F_OF);
6547 return (uint16_t) res;
6549 /****************************************************************************
6550 REMARKS:
6551 Implements the RCL instruction and side effects.
6552 ****************************************************************************/
6553 static uint32_t
6554 rcl_long(struct X86EMU *emu, uint32_t d, uint8_t s)
6556 uint32_t res, cnt, mask, cf;
6558 res = d;
6559 if ((cnt = s % 33) != 0) {
6560 cf = (d >> (32 - cnt)) & 0x1;
6561 res = (d << cnt) & 0xffffffff;
6562 mask = (1 << (cnt - 1)) - 1;
6563 res |= (d >> (33 - cnt)) & mask;
6564 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
6565 res |= 1 << (cnt - 1);
6567 CONDITIONAL_SET_FLAG(cf, F_CF);
6568 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
6569 F_OF);
6571 return res;
6573 /****************************************************************************
6574 REMARKS:
6575 Implements the RCR instruction and side effects.
6576 ****************************************************************************/
6577 static uint8_t
6578 rcr_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
6580 uint32_t res, cnt;
6581 uint32_t mask, cf, ocf = 0;
6583 /* rotate right through carry */
6584 /* s is the rotate distance. It varies from 0 - 8. d is the byte
6585 * object rotated.
6587 * have
6589 * CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
6591 * The new rotate is done mod 9, and given this, for a rotation of n bits
6592 * (mod 9) the new carry flag is then located n bits from the LSB.
6593 * The low part is then shifted up cnt bits, and the high part is or'd
6594 * in. Using CAPS for new values, and lowercase for the original
6595 * values, this can be expressed as:
6597 * IF n > 0 1) CF <- b_(n-1) 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
6598 * 3) B_(8-n) <- cf 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */
6599 res = d;
6600 if ((cnt = s % 9) != 0) {
6601 /* extract the new CARRY FLAG. */
6602 /* CF <- b_(n-1) */
6603 if (cnt == 1) {
6604 cf = d & 0x1;
6605 /* note hackery here. Access_flag(..) evaluates to
6606 * either 0 if flag not set non-zero if flag is set.
6607 * doing access_flag(..) != 0 casts that into either
6608 * 0..1 in any representation of the flags register
6609 * (i.e. packed bit array or unpacked.) */
6610 ocf = ACCESS_FLAG(F_CF) != 0;
6611 } else
6612 cf = (d >> (cnt - 1)) & 0x1;
6614 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */
6615 /* note that the right hand side done by the mask This is
6616 * effectively done by shifting the object to the right. The
6617 * result must be masked, in case the object came in and was
6618 * treated as a negative number. Needed??? */
6620 mask = (1 << (8 - cnt)) - 1;
6621 res = (d >> cnt) & mask;
6623 /* now the high stuff which rotated around into the positions
6624 * B_cnt-2 .. B_0 */
6625 /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */
6626 /* shift it downward, 7-(n-2) = 9-n positions. and mask off
6627 * the result before or'ing in. */
6628 res |= (d << (9 - cnt));
6630 /* if the carry flag was set, or it in. */
6631 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
6632 /* B_(8-n) <- cf */
6633 res |= 1 << (8 - cnt);
6635 /* set the new carry flag, based on the variable "cf" */
6636 CONDITIONAL_SET_FLAG(cf, F_CF);
6637 /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and
6638 * the most significant bit. Blecck. */
6639 /* parenthesized... */
6640 if (cnt == 1) {
6641 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
6642 F_OF);
6645 return (uint8_t) res;
6647 /****************************************************************************
6648 REMARKS:
6649 Implements the RCR instruction and side effects.
6650 ****************************************************************************/
6651 static uint16_t
6652 rcr_word(struct X86EMU *emu, uint16_t d, uint8_t s)
6654 uint32_t res, cnt;
6655 uint32_t mask, cf, ocf = 0;
6657 /* rotate right through carry */
6658 res = d;
6659 if ((cnt = s % 17) != 0) {
6660 if (cnt == 1) {
6661 cf = d & 0x1;
6662 ocf = ACCESS_FLAG(F_CF) != 0;
6663 } else
6664 cf = (d >> (cnt - 1)) & 0x1;
6665 mask = (1 << (16 - cnt)) - 1;
6666 res = (d >> cnt) & mask;
6667 res |= (d << (17 - cnt));
6668 if (ACCESS_FLAG(F_CF)) {
6669 res |= 1 << (16 - cnt);
6671 CONDITIONAL_SET_FLAG(cf, F_CF);
6672 if (cnt == 1) {
6673 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
6674 F_OF);
6677 return (uint16_t) res;
6679 /****************************************************************************
6680 REMARKS:
6681 Implements the RCR instruction and side effects.
6682 ****************************************************************************/
6683 static uint32_t
6684 rcr_long(struct X86EMU *emu, uint32_t d, uint8_t s)
6686 uint32_t res, cnt;
6687 uint32_t mask, cf, ocf = 0;
6689 /* rotate right through carry */
6690 res = d;
6691 if ((cnt = s % 33) != 0) {
6692 if (cnt == 1) {
6693 cf = d & 0x1;
6694 ocf = ACCESS_FLAG(F_CF) != 0;
6695 } else
6696 cf = (d >> (cnt - 1)) & 0x1;
6697 mask = (1 << (32 - cnt)) - 1;
6698 res = (d >> cnt) & mask;
6699 if (cnt != 1)
6700 res |= (d << (33 - cnt));
6701 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
6702 res |= 1 << (32 - cnt);
6704 CONDITIONAL_SET_FLAG(cf, F_CF);
6705 if (cnt == 1) {
6706 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
6707 F_OF);
6710 return res;
6712 /****************************************************************************
6713 REMARKS:
6714 Implements the ROL instruction and side effects.
6715 ****************************************************************************/
6716 static uint8_t
6717 rol_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
6719 unsigned int res, cnt, mask;
6721 /* rotate left */
6722 /* s is the rotate distance. It varies from 0 - 8. d is the byte
6723 * object rotated.
6725 * have
6727 * CF B_7 ... B_0
6729 * The new rotate is done mod 8. Much simpler than the "rcl" or "rcr"
6730 * operations.
6732 * IF n > 0 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) 2) B_(n-1) ..
6733 * B_(0) <- b_(7) .. b_(8-n) */
6734 res = d;
6735 if ((cnt = s % 8) != 0) {
6736 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */
6737 res = (d << cnt);
6739 /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */
6740 mask = (1 << cnt) - 1;
6741 res |= (d >> (8 - cnt)) & mask;
6743 /* set the new carry flag, Note that it is the low order bit
6744 * of the result!!! */
6745 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
6746 /* OVERFLOW is set *IFF* s==1, then it is the xor of CF and
6747 * the most significant bit. Blecck. */
6748 CONDITIONAL_SET_FLAG(s == 1 &&
6749 XOR2((res & 0x1) + ((res >> 6) & 0x2)),
6750 F_OF);
6751 } if (s != 0) {
6752 /* set the new carry flag, Note that it is the low order bit
6753 * of the result!!! */
6754 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
6756 return (uint8_t) res;
6758 /****************************************************************************
6759 REMARKS:
6760 Implements the ROL instruction and side effects.
6761 ****************************************************************************/
6762 static uint16_t
6763 rol_word(struct X86EMU *emu, uint16_t d, uint8_t s)
6765 unsigned int res, cnt, mask;
6767 res = d;
6768 if ((cnt = s % 16) != 0) {
6769 res = (d << cnt);
6770 mask = (1 << cnt) - 1;
6771 res |= (d >> (16 - cnt)) & mask;
6772 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
6773 CONDITIONAL_SET_FLAG(s == 1 &&
6774 XOR2((res & 0x1) + ((res >> 14) & 0x2)),
6775 F_OF);
6776 } if (s != 0) {
6777 /* set the new carry flag, Note that it is the low order bit
6778 * of the result!!! */
6779 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
6781 return (uint16_t) res;
6783 /****************************************************************************
6784 REMARKS:
6785 Implements the ROL instruction and side effects.
6786 ****************************************************************************/
6787 static uint32_t
6788 rol_long(struct X86EMU *emu, uint32_t d, uint8_t s)
6790 uint32_t res, cnt, mask;
6792 res = d;
6793 if ((cnt = s % 32) != 0) {
6794 res = (d << cnt);
6795 mask = (1 << cnt) - 1;
6796 res |= (d >> (32 - cnt)) & mask;
6797 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
6798 CONDITIONAL_SET_FLAG(s == 1 &&
6799 XOR2((res & 0x1) + ((res >> 30) & 0x2)),
6800 F_OF);
6801 } if (s != 0) {
6802 /* set the new carry flag, Note that it is the low order bit
6803 * of the result!!! */
6804 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
6806 return res;
6808 /****************************************************************************
6809 REMARKS:
6810 Implements the ROR instruction and side effects.
6811 ****************************************************************************/
6812 static uint8_t
6813 ror_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
6815 unsigned int res, cnt, mask;
6817 /* rotate right */
6818 /* s is the rotate distance. It varies from 0 - 8. d is the byte
6819 * object rotated.
6821 * have
6823 * B_7 ... B_0
6825 * The rotate is done mod 8.
6827 * IF n > 0 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) 2) B_(7) ..
6828 * B_(8-n) <- b_(n-1) .. b_(0) */
6829 res = d;
6830 if ((cnt = s % 8) != 0) { /* not a typo, do nada if cnt==0 */
6831 /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */
6832 res = (d << (8 - cnt));
6834 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */
6835 mask = (1 << (8 - cnt)) - 1;
6836 res |= (d >> (cnt)) & mask;
6838 /* set the new carry flag, Note that it is the low order bit
6839 * of the result!!! */
6840 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
6841 /* OVERFLOW is set *IFF* s==1, then it is the xor of the two
6842 * most significant bits. Blecck. */
6843 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
6844 } else if (s != 0) {
6845 /* set the new carry flag, Note that it is the low order bit
6846 * of the result!!! */
6847 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
6849 return (uint8_t) res;
6851 /****************************************************************************
6852 REMARKS:
6853 Implements the ROR instruction and side effects.
6854 ****************************************************************************/
6855 static uint16_t
6856 ror_word(struct X86EMU *emu, uint16_t d, uint8_t s)
6858 unsigned int res, cnt, mask;
6860 res = d;
6861 if ((cnt = s % 16) != 0) {
6862 res = (d << (16 - cnt));
6863 mask = (1 << (16 - cnt)) - 1;
6864 res |= (d >> (cnt)) & mask;
6865 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
6866 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
6867 } else if (s != 0) {
6868 /* set the new carry flag, Note that it is the low order bit
6869 * of the result!!! */
6870 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
6872 return (uint16_t) res;
6874 /****************************************************************************
6875 REMARKS:
6876 Implements the ROR instruction and side effects.
6877 ****************************************************************************/
6878 static uint32_t
6879 ror_long(struct X86EMU *emu, uint32_t d, uint8_t s)
6881 uint32_t res, cnt, mask;
6883 res = d;
6884 if ((cnt = s % 32) != 0) {
6885 res = (d << (32 - cnt));
6886 mask = (1 << (32 - cnt)) - 1;
6887 res |= (d >> (cnt)) & mask;
6888 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
6889 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
6890 } else if (s != 0) {
6891 /* set the new carry flag, Note that it is the low order bit
6892 * of the result!!! */
6893 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
6895 return res;
6897 /****************************************************************************
6898 REMARKS:
6899 Implements the SHL instruction and side effects.
6900 ****************************************************************************/
6901 static uint8_t
6902 shl_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
6904 unsigned int cnt, res, cf;
6906 if (s < 8) {
6907 cnt = s % 8;
6909 /* last bit shifted out goes into carry flag */
6910 if (cnt > 0) {
6911 res = d << cnt;
6912 cf = d & (1 << (8 - cnt));
6913 CONDITIONAL_SET_FLAG(cf, F_CF);
6914 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6915 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6916 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6917 } else {
6918 res = (uint8_t) d;
6921 if (cnt == 1) {
6922 /* Needs simplification. */
6923 CONDITIONAL_SET_FLAG(
6924 (((res & 0x80) == 0x80) ^
6925 (ACCESS_FLAG(F_CF) != 0)),
6926 /* was (emu->x86.R_FLG&F_CF)==F_CF)), */
6927 F_OF);
6928 } else {
6929 CLEAR_FLAG(F_OF);
6931 } else {
6932 res = 0;
6933 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80, F_CF);
6934 CLEAR_FLAG(F_OF);
6935 CLEAR_FLAG(F_SF);
6936 SET_FLAG(F_PF);
6937 SET_FLAG(F_ZF);
6939 return (uint8_t) res;
6941 /****************************************************************************
6942 REMARKS:
6943 Implements the SHL instruction and side effects.
6944 ****************************************************************************/
6945 static uint16_t
6946 shl_word(struct X86EMU *emu, uint16_t d, uint8_t s)
6948 unsigned int cnt, res, cf;
6950 if (s < 16) {
6951 cnt = s % 16;
6952 if (cnt > 0) {
6953 res = d << cnt;
6954 cf = d & (1 << (16 - cnt));
6955 CONDITIONAL_SET_FLAG(cf, F_CF);
6956 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6957 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6958 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6959 } else {
6960 res = (uint16_t) d;
6963 if (cnt == 1) {
6964 CONDITIONAL_SET_FLAG(
6965 (((res & 0x8000) == 0x8000) ^
6966 (ACCESS_FLAG(F_CF) != 0)),
6967 F_OF);
6968 } else {
6969 CLEAR_FLAG(F_OF);
6971 } else {
6972 res = 0;
6973 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF);
6974 CLEAR_FLAG(F_OF);
6975 CLEAR_FLAG(F_SF);
6976 SET_FLAG(F_PF);
6977 SET_FLAG(F_ZF);
6979 return (uint16_t) res;
6981 /****************************************************************************
6982 REMARKS:
6983 Implements the SHL instruction and side effects.
6984 ****************************************************************************/
6985 static uint32_t
6986 shl_long(struct X86EMU *emu, uint32_t d, uint8_t s)
6988 unsigned int cnt, res, cf;
6990 if (s < 32) {
6991 cnt = s % 32;
6992 if (cnt > 0) {
6993 res = d << cnt;
6994 cf = d & (1 << (32 - cnt));
6995 CONDITIONAL_SET_FLAG(cf, F_CF);
6996 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6997 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6998 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6999 } else {
7000 res = d;
7002 if (cnt == 1) {
7003 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
7004 (ACCESS_FLAG(F_CF) != 0)), F_OF);
7005 } else {
7006 CLEAR_FLAG(F_OF);
7008 } else {
7009 res = 0;
7010 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF);
7011 CLEAR_FLAG(F_OF);
7012 CLEAR_FLAG(F_SF);
7013 SET_FLAG(F_PF);
7014 SET_FLAG(F_ZF);
7016 return res;
7018 /****************************************************************************
7019 REMARKS:
7020 Implements the SHR instruction and side effects.
7021 ****************************************************************************/
7022 static uint8_t
7023 shr_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
7025 unsigned int cnt, res, cf;
7027 if (s < 8) {
7028 cnt = s % 8;
7029 if (cnt > 0) {
7030 cf = d & (1 << (cnt - 1));
7031 res = d >> cnt;
7032 CONDITIONAL_SET_FLAG(cf, F_CF);
7033 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7034 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7035 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7036 } else {
7037 res = (uint8_t) d;
7040 if (cnt == 1) {
7041 CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
7042 } else {
7043 CLEAR_FLAG(F_OF);
7045 } else {
7046 res = 0;
7047 CONDITIONAL_SET_FLAG((d >> (s - 1)) & 0x1, F_CF);
7048 CLEAR_FLAG(F_OF);
7049 CLEAR_FLAG(F_SF);
7050 SET_FLAG(F_PF);
7051 SET_FLAG(F_ZF);
7053 return (uint8_t) res;
7055 /****************************************************************************
7056 REMARKS:
7057 Implements the SHR instruction and side effects.
7058 ****************************************************************************/
7059 static uint16_t
7060 shr_word(struct X86EMU *emu, uint16_t d, uint8_t s)
7062 unsigned int cnt, res, cf;
7064 if (s < 16) {
7065 cnt = s % 16;
7066 if (cnt > 0) {
7067 cf = d & (1 << (cnt - 1));
7068 res = d >> cnt;
7069 CONDITIONAL_SET_FLAG(cf, F_CF);
7070 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7071 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7072 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7073 } else {
7074 res = d;
7077 if (cnt == 1) {
7078 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
7079 } else {
7080 CLEAR_FLAG(F_OF);
7082 } else {
7083 res = 0;
7084 CLEAR_FLAG(F_CF);
7085 CLEAR_FLAG(F_OF);
7086 SET_FLAG(F_ZF);
7087 CLEAR_FLAG(F_SF);
7088 CLEAR_FLAG(F_PF);
7090 return (uint16_t) res;
7092 /****************************************************************************
7093 REMARKS:
7094 Implements the SHR instruction and side effects.
7095 ****************************************************************************/
7096 static uint32_t
7097 shr_long(struct X86EMU *emu, uint32_t d, uint8_t s)
7099 unsigned int cnt, res, cf;
7101 if (s < 32) {
7102 cnt = s % 32;
7103 if (cnt > 0) {
7104 cf = d & (1 << (cnt - 1));
7105 res = d >> cnt;
7106 CONDITIONAL_SET_FLAG(cf, F_CF);
7107 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7108 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7109 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7110 } else {
7111 res = d;
7113 if (cnt == 1) {
7114 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
7115 } else {
7116 CLEAR_FLAG(F_OF);
7118 } else {
7119 res = 0;
7120 CLEAR_FLAG(F_CF);
7121 CLEAR_FLAG(F_OF);
7122 SET_FLAG(F_ZF);
7123 CLEAR_FLAG(F_SF);
7124 CLEAR_FLAG(F_PF);
7126 return res;
7128 /****************************************************************************
7129 REMARKS:
7130 Implements the SAR instruction and side effects.
7131 ****************************************************************************/
7132 static uint8_t
7133 sar_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
7135 unsigned int cnt, res, cf, mask, sf;
7137 res = d;
7138 sf = d & 0x80;
7139 cnt = s % 8;
7140 if (cnt > 0 && cnt < 8) {
7141 mask = (1 << (8 - cnt)) - 1;
7142 cf = d & (1 << (cnt - 1));
7143 res = (d >> cnt) & mask;
7144 CONDITIONAL_SET_FLAG(cf, F_CF);
7145 if (sf) {
7146 res |= ~mask;
7148 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7149 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7150 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7151 } else if (cnt >= 8) {
7152 if (sf) {
7153 res = 0xff;
7154 SET_FLAG(F_CF);
7155 CLEAR_FLAG(F_ZF);
7156 SET_FLAG(F_SF);
7157 SET_FLAG(F_PF);
7158 } else {
7159 res = 0;
7160 CLEAR_FLAG(F_CF);
7161 SET_FLAG(F_ZF);
7162 CLEAR_FLAG(F_SF);
7163 CLEAR_FLAG(F_PF);
7166 return (uint8_t) res;
7168 /****************************************************************************
7169 REMARKS:
7170 Implements the SAR instruction and side effects.
7171 ****************************************************************************/
7172 static uint16_t
7173 sar_word(struct X86EMU *emu, uint16_t d, uint8_t s)
7175 unsigned int cnt, res, cf, mask, sf;
7177 sf = d & 0x8000;
7178 cnt = s % 16;
7179 res = d;
7180 if (cnt > 0 && cnt < 16) {
7181 mask = (1 << (16 - cnt)) - 1;
7182 cf = d & (1 << (cnt - 1));
7183 res = (d >> cnt) & mask;
7184 CONDITIONAL_SET_FLAG(cf, F_CF);
7185 if (sf) {
7186 res |= ~mask;
7188 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7189 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7190 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7191 } else if (cnt >= 16) {
7192 if (sf) {
7193 res = 0xffff;
7194 SET_FLAG(F_CF);
7195 CLEAR_FLAG(F_ZF);
7196 SET_FLAG(F_SF);
7197 SET_FLAG(F_PF);
7198 } else {
7199 res = 0;
7200 CLEAR_FLAG(F_CF);
7201 SET_FLAG(F_ZF);
7202 CLEAR_FLAG(F_SF);
7203 CLEAR_FLAG(F_PF);
7206 return (uint16_t) res;
7208 /****************************************************************************
7209 REMARKS:
7210 Implements the SAR instruction and side effects.
7211 ****************************************************************************/
7212 static uint32_t
7213 sar_long(struct X86EMU *emu, uint32_t d, uint8_t s)
7215 uint32_t cnt, res, cf, mask, sf;
7217 sf = d & 0x80000000;
7218 cnt = s % 32;
7219 res = d;
7220 if (cnt > 0 && cnt < 32) {
7221 mask = (1 << (32 - cnt)) - 1;
7222 cf = d & (1 << (cnt - 1));
7223 res = (d >> cnt) & mask;
7224 CONDITIONAL_SET_FLAG(cf, F_CF);
7225 if (sf) {
7226 res |= ~mask;
7228 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7229 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7230 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7231 } else if (cnt >= 32) {
7232 if (sf) {
7233 res = 0xffffffff;
7234 SET_FLAG(F_CF);
7235 CLEAR_FLAG(F_ZF);
7236 SET_FLAG(F_SF);
7237 SET_FLAG(F_PF);
7238 } else {
7239 res = 0;
7240 CLEAR_FLAG(F_CF);
7241 SET_FLAG(F_ZF);
7242 CLEAR_FLAG(F_SF);
7243 CLEAR_FLAG(F_PF);
7246 return res;
7248 /****************************************************************************
7249 REMARKS:
7250 Implements the SHLD instruction and side effects.
7251 ****************************************************************************/
7252 static uint16_t
7253 shld_word(struct X86EMU *emu, uint16_t d, uint16_t fill, uint8_t s)
7255 unsigned int cnt, res, cf;
7257 if (s < 16) {
7258 cnt = s % 16;
7259 if (cnt > 0) {
7260 res = (d << cnt) | (fill >> (16 - cnt));
7261 cf = d & (1 << (16 - cnt));
7262 CONDITIONAL_SET_FLAG(cf, F_CF);
7263 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7264 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7265 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7266 } else {
7267 res = d;
7269 if (cnt == 1) {
7270 CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
7271 (ACCESS_FLAG(F_CF) != 0)), F_OF);
7272 } else {
7273 CLEAR_FLAG(F_OF);
7275 } else {
7276 res = 0;
7277 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF);
7278 CLEAR_FLAG(F_OF);
7279 CLEAR_FLAG(F_SF);
7280 SET_FLAG(F_PF);
7281 SET_FLAG(F_ZF);
7283 return (uint16_t) res;
7285 /****************************************************************************
7286 REMARKS:
7287 Implements the SHLD instruction and side effects.
7288 ****************************************************************************/
7289 static uint32_t
7290 shld_long(struct X86EMU *emu, uint32_t d, uint32_t fill, uint8_t s)
7292 unsigned int cnt, res, cf;
7294 if (s < 32) {
7295 cnt = s % 32;
7296 if (cnt > 0) {
7297 res = (d << cnt) | (fill >> (32 - cnt));
7298 cf = d & (1 << (32 - cnt));
7299 CONDITIONAL_SET_FLAG(cf, F_CF);
7300 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7301 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7302 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7303 } else {
7304 res = d;
7306 if (cnt == 1) {
7307 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
7308 (ACCESS_FLAG(F_CF) != 0)), F_OF);
7309 } else {
7310 CLEAR_FLAG(F_OF);
7312 } else {
7313 res = 0;
7314 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF);
7315 CLEAR_FLAG(F_OF);
7316 CLEAR_FLAG(F_SF);
7317 SET_FLAG(F_PF);
7318 SET_FLAG(F_ZF);
7320 return res;
7322 /****************************************************************************
7323 REMARKS:
7324 Implements the SHRD instruction and side effects.
7325 ****************************************************************************/
7326 static uint16_t
7327 shrd_word(struct X86EMU *emu, uint16_t d, uint16_t fill, uint8_t s)
7329 unsigned int cnt, res, cf;
7331 if (s < 16) {
7332 cnt = s % 16;
7333 if (cnt > 0) {
7334 cf = d & (1 << (cnt - 1));
7335 res = (d >> cnt) | (fill << (16 - cnt));
7336 CONDITIONAL_SET_FLAG(cf, F_CF);
7337 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7338 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7339 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7340 } else {
7341 res = d;
7344 if (cnt == 1) {
7345 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
7346 } else {
7347 CLEAR_FLAG(F_OF);
7349 } else {
7350 res = 0;
7351 CLEAR_FLAG(F_CF);
7352 CLEAR_FLAG(F_OF);
7353 SET_FLAG(F_ZF);
7354 CLEAR_FLAG(F_SF);
7355 CLEAR_FLAG(F_PF);
7357 return (uint16_t) res;
7359 /****************************************************************************
7360 REMARKS:
7361 Implements the SHRD instruction and side effects.
7362 ****************************************************************************/
7363 static uint32_t
7364 shrd_long(struct X86EMU *emu, uint32_t d, uint32_t fill, uint8_t s)
7366 unsigned int cnt, res, cf;
7368 if (s < 32) {
7369 cnt = s % 32;
7370 if (cnt > 0) {
7371 cf = d & (1 << (cnt - 1));
7372 res = (d >> cnt) | (fill << (32 - cnt));
7373 CONDITIONAL_SET_FLAG(cf, F_CF);
7374 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7375 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7376 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7377 } else {
7378 res = d;
7380 if (cnt == 1) {
7381 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
7382 } else {
7383 CLEAR_FLAG(F_OF);
7385 } else {
7386 res = 0;
7387 CLEAR_FLAG(F_CF);
7388 CLEAR_FLAG(F_OF);
7389 SET_FLAG(F_ZF);
7390 CLEAR_FLAG(F_SF);
7391 CLEAR_FLAG(F_PF);
7393 return res;
7395 /****************************************************************************
7396 REMARKS:
7397 Implements the SBB instruction and side effects.
7398 ****************************************************************************/
7399 static uint8_t
7400 sbb_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
7402 uint32_t res; /* all operands in native machine order */
7403 uint32_t bc;
7405 if (ACCESS_FLAG(F_CF))
7406 res = d - s - 1;
7407 else
7408 res = d - s;
7409 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7410 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7411 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7413 /* calculate the borrow chain. See note at top */
7414 bc = (res & (~d | s)) | (~d & s);
7415 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
7416 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
7417 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7418 return (uint8_t) res;
7420 /****************************************************************************
7421 REMARKS:
7422 Implements the SBB instruction and side effects.
7423 ****************************************************************************/
7424 static uint16_t
7425 sbb_word(struct X86EMU *emu, uint16_t d, uint16_t s)
7427 uint32_t res; /* all operands in native machine order */
7428 uint32_t bc;
7430 if (ACCESS_FLAG(F_CF))
7431 res = d - s - 1;
7432 else
7433 res = d - s;
7434 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7435 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7436 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7438 /* calculate the borrow chain. See note at top */
7439 bc = (res & (~d | s)) | (~d & s);
7440 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
7441 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
7442 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7443 return (uint16_t) res;
7445 /****************************************************************************
7446 REMARKS:
7447 Implements the SBB instruction and side effects.
7448 ****************************************************************************/
7449 static uint32_t
7450 sbb_long(struct X86EMU *emu, uint32_t d, uint32_t s)
7452 uint32_t res; /* all operands in native machine order */
7453 uint32_t bc;
7455 if (ACCESS_FLAG(F_CF))
7456 res = d - s - 1;
7457 else
7458 res = d - s;
7459 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7460 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7461 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7463 /* calculate the borrow chain. See note at top */
7464 bc = (res & (~d | s)) | (~d & s);
7465 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
7466 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
7467 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7468 return res;
7470 /****************************************************************************
7471 REMARKS:
7472 Implements the SUB instruction and side effects.
7473 ****************************************************************************/
7474 static uint8_t
7475 sub_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
7477 uint32_t res; /* all operands in native machine order */
7478 uint32_t bc;
7480 res = d - s;
7481 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7482 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7483 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7485 /* calculate the borrow chain. See note at top */
7486 bc = (res & (~d | s)) | (~d & s);
7487 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
7488 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
7489 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7490 return (uint8_t) res;
7492 /****************************************************************************
7493 REMARKS:
7494 Implements the SUB instruction and side effects.
7495 ****************************************************************************/
7496 static uint16_t
7497 sub_word(struct X86EMU *emu, uint16_t d, uint16_t s)
7499 uint32_t res; /* all operands in native machine order */
7500 uint32_t bc;
7502 res = d - s;
7503 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7504 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7505 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7507 /* calculate the borrow chain. See note at top */
7508 bc = (res & (~d | s)) | (~d & s);
7509 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
7510 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
7511 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7512 return (uint16_t) res;
7514 /****************************************************************************
7515 REMARKS:
7516 Implements the SUB instruction and side effects.
7517 ****************************************************************************/
7518 static uint32_t
7519 sub_long(struct X86EMU *emu, uint32_t d, uint32_t s)
7521 uint32_t res; /* all operands in native machine order */
7522 uint32_t bc;
7524 res = d - s;
7525 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7526 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7527 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7529 /* calculate the borrow chain. See note at top */
7530 bc = (res & (~d | s)) | (~d & s);
7531 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
7532 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
7533 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7534 return res;
7536 /****************************************************************************
7537 REMARKS:
7538 Implements the TEST instruction and side effects.
7539 ****************************************************************************/
7540 static void
7541 test_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
7543 uint32_t res; /* all operands in native machine order */
7545 res = d & s;
7547 CLEAR_FLAG(F_OF);
7548 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7549 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7550 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7551 /* AF == dont care */
7552 CLEAR_FLAG(F_CF);
7554 /****************************************************************************
7555 REMARKS:
7556 Implements the TEST instruction and side effects.
7557 ****************************************************************************/
7558 static void
7559 test_word(struct X86EMU *emu, uint16_t d, uint16_t s)
7561 uint32_t res; /* all operands in native machine order */
7563 res = d & s;
7565 CLEAR_FLAG(F_OF);
7566 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7567 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7568 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7569 /* AF == dont care */
7570 CLEAR_FLAG(F_CF);
7572 /****************************************************************************
7573 REMARKS:
7574 Implements the TEST instruction and side effects.
7575 ****************************************************************************/
7576 static void
7577 test_long(struct X86EMU *emu, uint32_t d, uint32_t s)
7579 uint32_t res; /* all operands in native machine order */
7581 res = d & s;
7583 CLEAR_FLAG(F_OF);
7584 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7585 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7586 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7587 /* AF == dont care */
7588 CLEAR_FLAG(F_CF);
7590 /****************************************************************************
7591 REMARKS:
7592 Implements the XOR instruction and side effects.
7593 ****************************************************************************/
7594 static uint8_t
7595 xor_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
7597 uint8_t res; /* all operands in native machine order */
7599 res = d ^ s;
7600 CLEAR_FLAG(F_OF);
7601 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7602 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7603 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
7604 CLEAR_FLAG(F_CF);
7605 CLEAR_FLAG(F_AF);
7606 return res;
7608 /****************************************************************************
7609 REMARKS:
7610 Implements the XOR instruction and side effects.
7611 ****************************************************************************/
7612 static uint16_t
7613 xor_word(struct X86EMU *emu, uint16_t d, uint16_t s)
7615 uint16_t res; /* all operands in native machine order */
7617 res = d ^ s;
7618 CLEAR_FLAG(F_OF);
7619 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7620 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7621 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7622 CLEAR_FLAG(F_CF);
7623 CLEAR_FLAG(F_AF);
7624 return res;
7626 /****************************************************************************
7627 REMARKS:
7628 Implements the XOR instruction and side effects.
7629 ****************************************************************************/
7630 static uint32_t
7631 xor_long(struct X86EMU *emu, uint32_t d, uint32_t s)
7633 uint32_t res; /* all operands in native machine order */
7635 res = d ^ s;
7636 CLEAR_FLAG(F_OF);
7637 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7638 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7639 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7640 CLEAR_FLAG(F_CF);
7641 CLEAR_FLAG(F_AF);
7642 return res;
7644 /****************************************************************************
7645 REMARKS:
7646 Implements the IMUL instruction and side effects.
7647 ****************************************************************************/
7648 static void
7649 imul_byte(struct X86EMU *emu, uint8_t s)
7651 int16_t res = (int16_t) ((int8_t) emu->x86.R_AL * (int8_t) s);
7653 emu->x86.R_AX = res;
7654 if (((emu->x86.R_AL & 0x80) == 0 && emu->x86.R_AH == 0x00) ||
7655 ((emu->x86.R_AL & 0x80) != 0 && emu->x86.R_AH == 0xFF)) {
7656 CLEAR_FLAG(F_CF);
7657 CLEAR_FLAG(F_OF);
7658 } else {
7659 SET_FLAG(F_CF);
7660 SET_FLAG(F_OF);
7663 /****************************************************************************
7664 REMARKS:
7665 Implements the IMUL instruction and side effects.
7666 ****************************************************************************/
7667 static void
7668 imul_word(struct X86EMU *emu, uint16_t s)
7670 int32_t res = (int16_t) emu->x86.R_AX * (int16_t) s;
7672 emu->x86.R_AX = (uint16_t) res;
7673 emu->x86.R_DX = (uint16_t) (res >> 16);
7674 if (((emu->x86.R_AX & 0x8000) == 0 && emu->x86.R_DX == 0x00) ||
7675 ((emu->x86.R_AX & 0x8000) != 0 && emu->x86.R_DX == 0xFF)) {
7676 CLEAR_FLAG(F_CF);
7677 CLEAR_FLAG(F_OF);
7678 } else {
7679 SET_FLAG(F_CF);
7680 SET_FLAG(F_OF);
7683 /****************************************************************************
7684 REMARKS:
7685 Implements the IMUL instruction and side effects.
7686 ****************************************************************************/
7687 static void
7688 imul_long(struct X86EMU *emu, uint32_t s)
7690 int64_t res;
7692 res = (int64_t)(int32_t)emu->x86.R_EAX * (int32_t)s;
7693 emu->x86.R_EAX = (uint32_t)res;
7694 emu->x86.R_EDX = ((uint64_t)res) >> 32;
7695 if (((emu->x86.R_EAX & 0x80000000) == 0 && emu->x86.R_EDX == 0x00) ||
7696 ((emu->x86.R_EAX & 0x80000000) != 0 && emu->x86.R_EDX == 0xFF)) {
7697 CLEAR_FLAG(F_CF);
7698 CLEAR_FLAG(F_OF);
7699 } else {
7700 SET_FLAG(F_CF);
7701 SET_FLAG(F_OF);
7704 /****************************************************************************
7705 REMARKS:
7706 Implements the MUL instruction and side effects.
7707 ****************************************************************************/
7708 static void
7709 mul_byte(struct X86EMU *emu, uint8_t s)
7711 uint16_t res = (uint16_t) (emu->x86.R_AL * s);
7713 emu->x86.R_AX = res;
7714 if (emu->x86.R_AH == 0) {
7715 CLEAR_FLAG(F_CF);
7716 CLEAR_FLAG(F_OF);
7717 } else {
7718 SET_FLAG(F_CF);
7719 SET_FLAG(F_OF);
7722 /****************************************************************************
7723 REMARKS:
7724 Implements the MUL instruction and side effects.
7725 ****************************************************************************/
7726 static void
7727 mul_word(struct X86EMU *emu, uint16_t s)
7729 uint32_t res = emu->x86.R_AX * s;
7731 emu->x86.R_AX = (uint16_t) res;
7732 emu->x86.R_DX = (uint16_t) (res >> 16);
7733 if (emu->x86.R_DX == 0) {
7734 CLEAR_FLAG(F_CF);
7735 CLEAR_FLAG(F_OF);
7736 } else {
7737 SET_FLAG(F_CF);
7738 SET_FLAG(F_OF);
7741 /****************************************************************************
7742 REMARKS:
7743 Implements the MUL instruction and side effects.
7744 ****************************************************************************/
7745 static void
7746 mul_long(struct X86EMU *emu, uint32_t s)
7748 uint64_t res = (uint64_t) emu->x86.R_EAX * s;
7750 emu->x86.R_EAX = (uint32_t) res;
7751 emu->x86.R_EDX = (uint32_t) (res >> 32);
7753 if (emu->x86.R_EDX == 0) {
7754 CLEAR_FLAG(F_CF);
7755 CLEAR_FLAG(F_OF);
7756 } else {
7757 SET_FLAG(F_CF);
7758 SET_FLAG(F_OF);
7761 /****************************************************************************
7762 REMARKS:
7763 Implements the IDIV instruction and side effects.
7764 ****************************************************************************/
7765 static void
7766 idiv_byte(struct X86EMU *emu, uint8_t s)
7768 int32_t dvd, div, mod;
7770 dvd = (int16_t) emu->x86.R_AX;
7771 if (s == 0) {
7772 x86emu_intr_raise(emu, 8);
7773 return;
7775 div = dvd / (int8_t) s;
7776 mod = dvd % (int8_t) s;
7777 if (div > 0x7f || div < -0x7f) {
7778 x86emu_intr_raise(emu, 8);
7779 return;
7781 emu->x86.R_AL = (int8_t) div;
7782 emu->x86.R_AH = (int8_t) mod;
7784 /****************************************************************************
7785 REMARKS:
7786 Implements the IDIV instruction and side effects.
7787 ****************************************************************************/
7788 static void
7789 idiv_word(struct X86EMU *emu, uint16_t s)
7791 int32_t dvd, div, mod;
7793 dvd = (((int32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX;
7794 if (s == 0) {
7795 x86emu_intr_raise(emu, 8);
7796 return;
7798 div = dvd / (int16_t) s;
7799 mod = dvd % (int16_t) s;
7800 if (div > 0x7fff || div < -0x7fff) {
7801 x86emu_intr_raise(emu, 8);
7802 return;
7804 CLEAR_FLAG(F_CF);
7805 CLEAR_FLAG(F_SF);
7806 CONDITIONAL_SET_FLAG(div == 0, F_ZF);
7807 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
7809 emu->x86.R_AX = (uint16_t) div;
7810 emu->x86.R_DX = (uint16_t) mod;
7812 /****************************************************************************
7813 REMARKS:
7814 Implements the IDIV instruction and side effects.
7815 ****************************************************************************/
7816 static void
7817 idiv_long(struct X86EMU *emu, uint32_t s)
7819 int64_t dvd, div, mod;
7821 dvd = (((int64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX;
7822 if (s == 0) {
7823 x86emu_intr_raise(emu, 8);
7824 return;
7826 div = dvd / (int32_t) s;
7827 mod = dvd % (int32_t) s;
7828 if (div > 0x7fffffff || div < -0x7fffffff) {
7829 x86emu_intr_raise(emu, 8);
7830 return;
7832 CLEAR_FLAG(F_CF);
7833 CLEAR_FLAG(F_AF);
7834 CLEAR_FLAG(F_SF);
7835 SET_FLAG(F_ZF);
7836 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
7838 emu->x86.R_EAX = (uint32_t) div;
7839 emu->x86.R_EDX = (uint32_t) mod;
7841 /****************************************************************************
7842 REMARKS:
7843 Implements the DIV instruction and side effects.
7844 ****************************************************************************/
7845 static void
7846 div_byte(struct X86EMU *emu, uint8_t s)
7848 uint32_t dvd, div, mod;
7850 dvd = emu->x86.R_AX;
7851 if (s == 0) {
7852 x86emu_intr_raise(emu, 8);
7853 return;
7855 div = dvd / (uint8_t) s;
7856 mod = dvd % (uint8_t) s;
7857 if (div > 0xff) {
7858 x86emu_intr_raise(emu, 8);
7859 return;
7861 emu->x86.R_AL = (uint8_t) div;
7862 emu->x86.R_AH = (uint8_t) mod;
7864 /****************************************************************************
7865 REMARKS:
7866 Implements the DIV instruction and side effects.
7867 ****************************************************************************/
7868 static void
7869 div_word(struct X86EMU *emu, uint16_t s)
7871 uint32_t dvd, div, mod;
7873 dvd = (((uint32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX;
7874 if (s == 0) {
7875 x86emu_intr_raise(emu, 8);
7876 return;
7878 div = dvd / (uint16_t) s;
7879 mod = dvd % (uint16_t) s;
7880 if (div > 0xffff) {
7881 x86emu_intr_raise(emu, 8);
7882 return;
7884 CLEAR_FLAG(F_CF);
7885 CLEAR_FLAG(F_SF);
7886 CONDITIONAL_SET_FLAG(div == 0, F_ZF);
7887 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
7889 emu->x86.R_AX = (uint16_t) div;
7890 emu->x86.R_DX = (uint16_t) mod;
7892 /****************************************************************************
7893 REMARKS:
7894 Implements the DIV instruction and side effects.
7895 ****************************************************************************/
7896 static void
7897 div_long(struct X86EMU *emu, uint32_t s)
7899 uint64_t dvd, div, mod;
7901 dvd = (((uint64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX;
7902 if (s == 0) {
7903 x86emu_intr_raise(emu, 8);
7904 return;
7906 div = dvd / (uint32_t) s;
7907 mod = dvd % (uint32_t) s;
7908 if (div > 0xffffffff) {
7909 x86emu_intr_raise(emu, 8);
7910 return;
7912 CLEAR_FLAG(F_CF);
7913 CLEAR_FLAG(F_AF);
7914 CLEAR_FLAG(F_SF);
7915 SET_FLAG(F_ZF);
7916 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
7918 emu->x86.R_EAX = (uint32_t) div;
7919 emu->x86.R_EDX = (uint32_t) mod;
7921 /****************************************************************************
7922 REMARKS:
7923 Implements the IN string instruction and side effects.
7924 ****************************************************************************/
7925 static void
7926 ins(struct X86EMU *emu, int size)
7928 int inc = size;
7930 if (ACCESS_FLAG(F_DF)) {
7931 inc = -size;
7933 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
7934 /* dont care whether REPE or REPNE */
7935 /* in until CX is ZERO. */
7936 uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ?
7937 emu->x86.R_ECX : emu->x86.R_CX);
7938 switch (size) {
7939 case 1:
7940 while (count--) {
7941 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
7942 (*emu->emu_inb) (emu, emu->x86.R_DX));
7943 emu->x86.R_DI += inc;
7945 break;
7947 case 2:
7948 while (count--) {
7949 store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
7950 (*emu->emu_inw) (emu, emu->x86.R_DX));
7951 emu->x86.R_DI += inc;
7953 break;
7954 case 4:
7955 while (count--) {
7956 store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
7957 (*emu->emu_inl) (emu, emu->x86.R_DX));
7958 emu->x86.R_DI += inc;
7959 break;
7962 emu->x86.R_CX = 0;
7963 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
7964 emu->x86.R_ECX = 0;
7966 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
7967 } else {
7968 switch (size) {
7969 case 1:
7970 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
7971 (*emu->emu_inb) (emu, emu->x86.R_DX));
7972 break;
7973 case 2:
7974 store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
7975 (*emu->emu_inw) (emu, emu->x86.R_DX));
7976 break;
7977 case 4:
7978 store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
7979 (*emu->emu_inl) (emu, emu->x86.R_DX));
7980 break;
7982 emu->x86.R_DI += inc;
7985 /****************************************************************************
7986 REMARKS:
7987 Implements the OUT string instruction and side effects.
7988 ****************************************************************************/
7989 static void
7990 outs(struct X86EMU *emu, int size)
7992 int inc = size;
7994 if (ACCESS_FLAG(F_DF)) {
7995 inc = -size;
7997 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
7998 /* dont care whether REPE or REPNE */
7999 /* out until CX is ZERO. */
8000 uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ?
8001 emu->x86.R_ECX : emu->x86.R_CX);
8002 switch (size) {
8003 case 1:
8004 while (count--) {
8005 (*emu->emu_outb) (emu, emu->x86.R_DX,
8006 fetch_byte(emu, emu->x86.R_ES, emu->x86.R_SI));
8007 emu->x86.R_SI += inc;
8009 break;
8011 case 2:
8012 while (count--) {
8013 (*emu->emu_outw) (emu, emu->x86.R_DX,
8014 fetch_word(emu, emu->x86.R_ES, emu->x86.R_SI));
8015 emu->x86.R_SI += inc;
8017 break;
8018 case 4:
8019 while (count--) {
8020 (*emu->emu_outl) (emu, emu->x86.R_DX,
8021 fetch_long(emu, emu->x86.R_ES, emu->x86.R_SI));
8022 emu->x86.R_SI += inc;
8023 break;
8026 emu->x86.R_CX = 0;
8027 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
8028 emu->x86.R_ECX = 0;
8030 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
8031 } else {
8032 switch (size) {
8033 case 1:
8034 (*emu->emu_outb) (emu, emu->x86.R_DX,
8035 fetch_byte(emu, emu->x86.R_ES, emu->x86.R_SI));
8036 break;
8037 case 2:
8038 (*emu->emu_outw) (emu, emu->x86.R_DX,
8039 fetch_word(emu, emu->x86.R_ES, emu->x86.R_SI));
8040 break;
8041 case 4:
8042 (*emu->emu_outl) (emu, emu->x86.R_DX,
8043 fetch_long(emu, emu->x86.R_ES, emu->x86.R_SI));
8044 break;
8046 emu->x86.R_SI += inc;
8049 /****************************************************************************
8050 REMARKS:
8051 Pushes a word onto the stack.
8053 NOTE: Do not inline this, as (*emu->emu_wrX) is already inline!
8054 ****************************************************************************/
8055 static void
8056 push_word(struct X86EMU *emu, uint16_t w)
8058 emu->x86.R_SP -= 2;
8059 store_word(emu, emu->x86.R_SS, emu->x86.R_SP, w);
8061 /****************************************************************************
8062 REMARKS:
8063 Pushes a long onto the stack.
8065 NOTE: Do not inline this, as (*emu->emu_wrX) is already inline!
8066 ****************************************************************************/
8067 static void
8068 push_long(struct X86EMU *emu, uint32_t w)
8070 emu->x86.R_SP -= 4;
8071 store_long(emu, emu->x86.R_SS, emu->x86.R_SP, w);
8073 /****************************************************************************
8074 REMARKS:
8075 Pops a word from the stack.
8077 NOTE: Do not inline this, as (*emu->emu_rdX) is already inline!
8078 ****************************************************************************/
8079 static uint16_t
8080 pop_word(struct X86EMU *emu)
8082 uint16_t res;
8084 res = fetch_word(emu, emu->x86.R_SS, emu->x86.R_SP);
8085 emu->x86.R_SP += 2;
8086 return res;
8088 /****************************************************************************
8089 REMARKS:
8090 Pops a long from the stack.
8092 NOTE: Do not inline this, as (*emu->emu_rdX) is already inline!
8093 ****************************************************************************/
8094 static uint32_t
8095 pop_long(struct X86EMU *emu)
8097 uint32_t res;
8099 res = fetch_long(emu, emu->x86.R_SS, emu->x86.R_SP);
8100 emu->x86.R_SP += 4;
8101 return res;