x86emu.c revision 1.8 1 /* $NetBSD: x86emu.c,v 1.8 2014/08/04 19:19:02 joerg Exp $ */
2
3 /****************************************************************************
4 *
5 * Realmode X86 Emulator Library
6 *
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
11 *
12 * ========================================================================
13 *
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.
23 *
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.
31 *
32 ****************************************************************************/
33
34 #ifndef _KERNEL
35 #include <stdbool.h>
36 #endif
37
38 #include <x86emu/x86emu.h>
39 #include <x86emu/x86emu_regs.h>
40
41 static void x86emu_intr_raise (struct X86EMU *, uint8_t type);
42
43 static void X86EMU_exec_one_byte(struct X86EMU *);
44 static void X86EMU_exec_two_byte(struct X86EMU *);
45
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 *);
70
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 *);
74
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 *);
78
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);
81
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);
85
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 *);
174
175 /****************************************************************************
176 REMARKS:
177 Handles any pending asychronous interrupts.
178 ****************************************************************************/
179 static void
180 x86emu_intr_dispatch(struct X86EMU *emu, uint8_t intno)
181 {
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);
192 }
193 }
194
195 static void
196 x86emu_intr_handle(struct X86EMU *emu)
197 {
198 uint8_t intno;
199
200 if (emu->x86.intr & INTR_SYNCH) {
201 intno = emu->x86.intno;
202 emu->x86.intr = 0;
203 x86emu_intr_dispatch(emu, intno);
204 }
205 }
206 /****************************************************************************
207 PARAMETERS:
208 intrnum - Interrupt number to raise
209
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)
216 {
217 emu->x86.intno = intrnum;
218 emu->x86.intr |= INTR_SYNCH;
219 }
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)
228 {
229 emu->x86.intr = 0;
230
231 #ifdef _KERNEL
232 if (setjmp(&emu->exec_state))
233 return;
234 #else
235 if (setjmp(emu->exec_state))
236 return;
237 #endif
238
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);
244 }
245 }
246 if (emu->x86.R_CS == 0 && emu->x86.R_IP == 0)
247 return;
248 X86EMU_exec_one_byte(emu);
249 ++emu->cur_cycles;
250 }
251 }
252
253 void
254 X86EMU_exec_call(struct X86EMU *emu, uint16_t seg, uint16_t off)
255 {
256 push_word(emu, 0);
257 push_word(emu, 0);
258 emu->x86.R_CS = seg;
259 emu->x86.R_IP = off;
260
261 X86EMU_exec(emu);
262 }
263
264 void
265 X86EMU_exec_intr(struct X86EMU *emu, uint8_t intr)
266 {
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;
275
276 X86EMU_exec(emu);
277 }
278 /****************************************************************************
279 REMARKS:
280 Halts the system by setting the halted system flag.
281 ****************************************************************************/
282 void
283 X86EMU_halt_sys(struct X86EMU *emu)
284 {
285 #ifdef _KERNEL
286 longjmp(&emu->exec_state);
287 #else
288 longjmp(emu->exec_state, 1);
289 #endif
290 }
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
296
297 REMARKS:
298 Raise the specified interrupt to be handled before the execution of the
299 next instruction.
300
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)
305 {
306 int fetched;
307
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;
312 }
313 /****************************************************************************
314 RETURNS:
315 Immediate byte value read from instruction queue
316
317 REMARKS:
318 This function returns the immediate byte from the instruction queue, and
319 moves the instruction pointer to the next value.
320
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)
325 {
326 uint8_t fetched;
327
328 fetched = fetch_byte(emu, emu->x86.R_CS, emu->x86.R_IP);
329 emu->x86.R_IP++;
330 return fetched;
331 }
332 /****************************************************************************
333 RETURNS:
334 Immediate word value read from instruction queue
335
336 REMARKS:
337 This function returns the immediate byte from the instruction queue, and
338 moves the instruction pointer to the next value.
339
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)
344 {
345 uint16_t fetched;
346
347 fetched = fetch_word(emu, emu->x86.R_CS, emu->x86.R_IP);
348 emu->x86.R_IP += 2;
349 return fetched;
350 }
351 /****************************************************************************
352 RETURNS:
353 Immediate lone value read from instruction queue
354
355 REMARKS:
356 This function returns the immediate byte from the instruction queue, and
357 moves the instruction pointer to the next value.
358
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)
363 {
364 uint32_t fetched;
365
366 fetched = fetch_long(emu, emu->x86.R_CS, emu->x86.R_IP);
367 emu->x86.R_IP += 4;
368 return fetched;
369 }
370 /****************************************************************************
371 RETURNS:
372 Value of the default data segment
373
374 REMARKS:
375 Inline function that returns the default data segment for the current
376 instruction.
377
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:
384
385 repe prefix seen (handled elsewhere)
386 repne prefix seen (ditto)
387
388 cs segment override
389 ds segment override
390 es segment override
391 fs segment override
392 gs segment override
393 ss segment override
394
395 ds/ss select (in absense of override)
396
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)
401 {
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;
424 }
425 X86EMU_halt_sys(emu);
426 }
427 /****************************************************************************
428 PARAMETERS:
429 offset - Offset to load data from
430
431 RETURNS:
432 Byte value read from the absolute memory location.
433
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)
438 {
439 return fetch_byte(emu, get_data_segment(emu), offset);
440 }
441 /****************************************************************************
442 PARAMETERS:
443 offset - Offset to load data from
444
445 RETURNS:
446 Word value read from the absolute memory location.
447
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)
452 {
453 return fetch_word(emu, get_data_segment(emu), offset);
454 }
455 /****************************************************************************
456 PARAMETERS:
457 offset - Offset to load data from
458
459 RETURNS:
460 Long value read from the absolute memory location.
461
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)
466 {
467 return fetch_long(emu, get_data_segment(emu), offset);
468 }
469 /****************************************************************************
470 PARAMETERS:
471 segment - Segment to load data from
472 offset - Offset to load data from
473
474 RETURNS:
475 Byte value read from the absolute memory location.
476
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)
481 {
482 return (*emu->emu_rdb) (emu, ((uint32_t) segment << 4) + offset);
483 }
484 /****************************************************************************
485 PARAMETERS:
486 segment - Segment to load data from
487 offset - Offset to load data from
488
489 RETURNS:
490 Word value read from the absolute memory location.
491
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)
496 {
497 return (*emu->emu_rdw) (emu, ((uint32_t) segment << 4) + offset);
498 }
499 /****************************************************************************
500 PARAMETERS:
501 segment - Segment to load data from
502 offset - Offset to load data from
503
504 RETURNS:
505 Long value read from the absolute memory location.
506
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)
511 {
512 return (*emu->emu_rdl) (emu, ((uint32_t) segment << 4) + offset);
513 }
514 /****************************************************************************
515 PARAMETERS:
516 offset - Offset to store data at
517 val - Value to store
518
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.
522
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)
527 {
528 store_byte(emu, get_data_segment(emu), offset, val);
529 }
530 /****************************************************************************
531 PARAMETERS:
532 offset - Offset to store data at
533 val - Value to store
534
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.
538
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)
543 {
544 store_word(emu, get_data_segment(emu), offset, val);
545 }
546 /****************************************************************************
547 PARAMETERS:
548 offset - Offset to store data at
549 val - Value to store
550
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.
554
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)
559 {
560 store_long(emu, get_data_segment(emu), offset, val);
561 }
562 /****************************************************************************
563 PARAMETERS:
564 segment - Segment to store data at
565 offset - Offset to store data at
566 val - Value to store
567
568 REMARKS:
569 Writes a byte value to an absolute memory location.
570
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)
575 {
576 (*emu->emu_wrb) (emu, ((uint32_t) segment << 4) + offset, val);
577 }
578 /****************************************************************************
579 PARAMETERS:
580 segment - Segment to store data at
581 offset - Offset to store data at
582 val - Value to store
583
584 REMARKS:
585 Writes a word value to an absolute memory location.
586
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)
591 {
592 (*emu->emu_wrw) (emu, ((uint32_t) segment << 4) + offset, val);
593 }
594 /****************************************************************************
595 PARAMETERS:
596 segment - Segment to store data at
597 offset - Offset to store data at
598 val - Value to store
599
600 REMARKS:
601 Writes a long value to an absolute memory location.
602
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)
607 {
608 (*emu->emu_wrl) (emu, ((uint32_t) segment << 4) + offset, val);
609 }
610 /****************************************************************************
611 PARAMETERS:
612 reg - Register to decode
613
614 RETURNS:
615 Pointer to the appropriate register
616
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)
623 {
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);
643 }
644 }
645
646 static uint8_t *
647 decode_rl_byte_register(struct X86EMU *emu)
648 {
649 return decode_rm_byte_register(emu, emu->cur_rl);
650 }
651
652 static uint8_t *
653 decode_rh_byte_register(struct X86EMU *emu)
654 {
655 return decode_rm_byte_register(emu, emu->cur_rh);
656 }
657 /****************************************************************************
658 PARAMETERS:
659 reg - Register to decode
660
661 RETURNS:
662 Pointer to the appropriate register
663
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)
670 {
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);
690 }
691 }
692
693 static uint16_t *
694 decode_rl_word_register(struct X86EMU *emu)
695 {
696 return decode_rm_word_register(emu, emu->cur_rl);
697 }
698
699 static uint16_t *
700 decode_rh_word_register(struct X86EMU *emu)
701 {
702 return decode_rm_word_register(emu, emu->cur_rh);
703 }
704 /****************************************************************************
705 PARAMETERS:
706 reg - Register to decode
707
708 RETURNS:
709 Pointer to the appropriate register
710
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)
717 {
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);
737 }
738 }
739
740 static uint32_t *
741 decode_rl_long_register(struct X86EMU *emu)
742 {
743 return decode_rm_long_register(emu, emu->cur_rl);
744 }
745
746 static uint32_t *
747 decode_rh_long_register(struct X86EMU *emu)
748 {
749 return decode_rm_long_register(emu, emu->cur_rh);
750 }
751
752 /****************************************************************************
753 PARAMETERS:
754 reg - Register to decode
755
756 RETURNS:
757 Pointer to the appropriate register
758
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)
766 {
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);
782 }
783 }
784 /*
785 *
786 * return offset from the SIB Byte
787 */
788 static uint32_t
789 decode_sib_address(struct X86EMU *emu, int sib, int mod)
790 {
791 uint32_t base = 0, i = 0, scale = 1;
792
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;
816 }
817 break;
818 case 6:
819 base = emu->x86.R_ESI;
820 break;
821 case 7:
822 base = emu->x86.R_EDI;
823 break;
824 }
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;
850 }
851 scale = 1 << ((sib >> 6) & 0x03);
852 return base + (i * scale);
853 }
854 /****************************************************************************
855 PARAMETERS:
856 rm - RM value to decode
857
858 RETURNS:
859 Offset in memory for the address decoding
860
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)
867 {
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;
894 }
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);
904 }
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;
912
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;
941 }
942 break;
943 case 7:
944 offset = emu->x86.R_BX;
945 break;
946 default:
947 X86EMU_halt_sys(emu);
948 }
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;
954 }
955 }
956
957 static uint8_t
958 decode_and_fetch_byte(struct X86EMU *emu)
959 {
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);
965 }
966 }
967
968 static uint16_t
969 decode_and_fetch_word_disp(struct X86EMU *emu, int16_t disp)
970 {
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);
979 }
980 }
981
982 static uint32_t
983 decode_and_fetch_long_disp(struct X86EMU *emu, int16_t disp)
984 {
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);
993 }
994 }
995
996 uint16_t
997 decode_and_fetch_word(struct X86EMU *emu)
998 {
999 return decode_and_fetch_word_disp(emu, 0);
1000 }
1001
1002 uint32_t
1003 decode_and_fetch_long(struct X86EMU *emu)
1004 {
1005 return decode_and_fetch_long_disp(emu, 0);
1006 }
1007
1008 uint8_t
1009 decode_and_fetch_byte_imm8(struct X86EMU *emu, uint8_t *imm)
1010 {
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);
1018 }
1019 }
1020
1021 static uint16_t
1022 decode_and_fetch_word_imm8(struct X86EMU *emu, uint8_t *imm)
1023 {
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);
1031 }
1032 }
1033
1034 static uint32_t
1035 decode_and_fetch_long_imm8(struct X86EMU *emu, uint8_t *imm)
1036 {
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);
1044 }
1045 }
1046
1047 static void
1048 write_back_byte(struct X86EMU *emu, uint8_t val)
1049 {
1050 if (emu->cur_mod != 3)
1051 store_data_byte(emu, emu->cur_offset, val);
1052 else
1053 *decode_rl_byte_register(emu) = val;
1054 }
1055
1056 static void
1057 write_back_word(struct X86EMU *emu, uint16_t val)
1058 {
1059 if (emu->cur_mod != 3)
1060 store_data_word(emu, emu->cur_offset, val);
1061 else
1062 *decode_rl_word_register(emu) = val;
1063 }
1064
1065 static void
1066 write_back_long(struct X86EMU *emu, uint32_t val)
1067 {
1068 if (emu->cur_mod != 3)
1069 store_data_long(emu, emu->cur_offset, val);
1070 else
1071 *decode_rl_long_register(emu) = val;
1072 }
1073
1074 static void
1075 common_inc_word_long(struct X86EMU *emu, union X86EMU_register *reg)
1076 {
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);
1081 }
1082
1083 static void
1084 common_dec_word_long(struct X86EMU *emu, union X86EMU_register *reg)
1085 {
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);
1090 }
1091
1092 static void
1093 common_binop_byte_rm_r(struct X86EMU *emu, uint8_t (*binop)(struct X86EMU *, uint8_t, uint8_t))
1094 {
1095 uint32_t destoffset;
1096 uint8_t *destreg, srcval;
1097 uint8_t destval;
1098
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);
1109 }
1110 }
1111
1112 static void
1113 common_binop_ns_byte_rm_r(struct X86EMU *emu, void (*binop)(struct X86EMU *, uint8_t, uint8_t))
1114 {
1115 uint32_t destoffset;
1116 uint8_t destval, srcval;
1117
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);
1125 }
1126 (*binop)(emu, destval, srcval);
1127 }
1128
1129 static void
1130 common_binop_word_rm_r(struct X86EMU *emu, uint16_t (*binop)(struct X86EMU *, uint16_t, uint16_t))
1131 {
1132 uint32_t destoffset;
1133 uint16_t destval, *destreg, srcval;
1134
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);
1145 }
1146 }
1147
1148 static void
1149 common_binop_byte_r_rm(struct X86EMU *emu, uint8_t (*binop)(struct X86EMU *, uint8_t, uint8_t))
1150 {
1151 uint8_t *destreg, srcval;
1152 uint32_t srcoffset;
1153
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);
1161 }
1162 *destreg = (*binop)(emu, *destreg, srcval);
1163 }
1164
1165 static void
1166 common_binop_long_rm_r(struct X86EMU *emu, uint32_t (*binop)(struct X86EMU *, uint32_t, uint32_t))
1167 {
1168 uint32_t destoffset;
1169 uint32_t destval, *destreg, srcval;
1170
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);
1181 }
1182 }
1183
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))
1187 {
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);
1192 }
1193
1194 static void
1195 common_binop_ns_word_rm_r(struct X86EMU *emu, void (*binop)(struct X86EMU *, uint16_t, uint16_t))
1196 {
1197 uint32_t destoffset;
1198 uint16_t destval, srcval;
1199
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);
1207 }
1208 (*binop)(emu, destval, srcval);
1209 }
1210
1211
1212 static void
1213 common_binop_ns_long_rm_r(struct X86EMU *emu, void (*binop)(struct X86EMU *, uint32_t, uint32_t))
1214 {
1215 uint32_t destoffset;
1216 uint32_t destval, srcval;
1217
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);
1225 }
1226 (*binop)(emu, destval, srcval);
1227 }
1228
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))
1232 {
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);
1237 }
1238
1239 static void
1240 common_binop_long_r_rm(struct X86EMU *emu, uint32_t (*binop)(struct X86EMU *, uint32_t, uint32_t))
1241 {
1242 uint32_t srcoffset;
1243 uint32_t *destreg, srcval;
1244
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);
1252 }
1253 *destreg = (*binop)(emu, *destreg, srcval);
1254 }
1255
1256 static void
1257 common_binop_word_r_rm(struct X86EMU *emu, uint16_t (*binop)(struct X86EMU *, uint16_t, uint16_t))
1258 {
1259 uint32_t srcoffset;
1260 uint16_t *destreg, srcval;
1261
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);
1269 }
1270 *destreg = (*binop)(emu, *destreg, srcval);
1271 }
1272
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))
1276 {
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);
1281 }
1282
1283 static void
1284 common_binop_byte_imm(struct X86EMU *emu, uint8_t (*binop)(struct X86EMU *, uint8_t, uint8_t))
1285 {
1286 uint8_t srcval;
1287
1288 srcval = fetch_byte_imm(emu);
1289 emu->x86.R_AL = (*binop)(emu, emu->x86.R_AL, srcval);
1290 }
1291
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))
1295 {
1296 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1297 uint32_t srcval;
1298
1299 srcval = fetch_long_imm(emu);
1300 emu->x86.R_EAX = (*binop32)(emu, emu->x86.R_EAX, srcval);
1301 } else {
1302 uint16_t srcval;
1303
1304 srcval = fetch_word_imm(emu);
1305 emu->x86.R_AX = (*binop16)(emu, emu->x86.R_AX, srcval);
1306 }
1307 }
1308
1309 static void
1310 common_push_word_long(struct X86EMU *emu, union X86EMU_register *reg)
1311 {
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);
1316 }
1317
1318 static void
1319 common_pop_word_long(struct X86EMU *emu, union X86EMU_register *reg)
1320 {
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);
1325 }
1326
1327 static void
1328 common_imul_long_IMM(struct X86EMU *emu, bool byte_imm)
1329 {
1330 uint32_t srcoffset;
1331 uint32_t *destreg, srcval;
1332 int32_t imm;
1333 uint64_t res;
1334
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);
1342 }
1343
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;
1349
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);
1356 }
1357 *destreg = (uint32_t)res;
1358 }
1359
1360 static void
1361 common_imul_word_IMM(struct X86EMU *emu, bool byte_imm)
1362 {
1363 uint32_t srcoffset;
1364 uint16_t *destreg, srcval;
1365 int16_t imm;
1366 uint32_t res;
1367
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);
1375 }
1376
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;
1382
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);
1389 }
1390 *destreg = (uint16_t) res;
1391 }
1392
1393 static void
1394 common_imul_imm(struct X86EMU *emu, bool byte_imm)
1395 {
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);
1400 }
1401
1402 static void
1403 common_jmp_near(struct X86EMU *emu, bool cond)
1404 {
1405 int8_t offset;
1406 uint16_t target;
1407
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;
1412 }
1413
1414 static void
1415 common_load_far_pointer(struct X86EMU *emu, uint16_t *seg)
1416 {
1417 uint16_t *dstreg;
1418 uint32_t srcoffset;
1419
1420 fetch_decode_modrm(emu);
1421 if (emu->cur_mod == 3)
1422 X86EMU_halt_sys(emu);
1423
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);
1428 }
1429
1430 /*----------------------------- Implementation ----------------------------*/
1431 /****************************************************************************
1432 REMARKS:
1433 Handles opcode 0x3a
1434 ****************************************************************************/
1435 static void
1436 x86emuOp_cmp_byte_R_RM(struct X86EMU *emu)
1437 {
1438 uint8_t *destreg, srcval;
1439
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);
1444 }
1445 /****************************************************************************
1446 REMARKS:
1447 Handles opcode 0x3b
1448 ****************************************************************************/
1449 static void
1450 x86emuOp32_cmp_word_R_RM(struct X86EMU *emu)
1451 {
1452 uint32_t srcval, *destreg;
1453
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);
1458 }
1459
1460 static void
1461 x86emuOp16_cmp_word_R_RM(struct X86EMU *emu)
1462 {
1463 uint16_t srcval, *destreg;
1464
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);
1469 }
1470
1471 static void
1472 x86emuOp_cmp_word_R_RM(struct X86EMU *emu)
1473 {
1474 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1475 x86emuOp32_cmp_word_R_RM(emu);
1476 else
1477 x86emuOp16_cmp_word_R_RM(emu);
1478 }
1479 /****************************************************************************
1480 REMARKS:
1481 Handles opcode 0x3c
1482 ****************************************************************************/
1483 static void
1484 x86emuOp_cmp_byte_AL_IMM(struct X86EMU *emu)
1485 {
1486 uint8_t srcval;
1487
1488 srcval = fetch_byte_imm(emu);
1489 cmp_byte(emu, emu->x86.R_AL, srcval);
1490 }
1491 /****************************************************************************
1492 REMARKS:
1493 Handles opcode 0x3d
1494 ****************************************************************************/
1495 static void
1496 x86emuOp32_cmp_word_AX_IMM(struct X86EMU *emu)
1497 {
1498 uint32_t srcval;
1499
1500 srcval = fetch_long_imm(emu);
1501 cmp_long(emu, emu->x86.R_EAX, srcval);
1502 }
1503
1504 static void
1505 x86emuOp16_cmp_word_AX_IMM(struct X86EMU *emu)
1506 {
1507 uint16_t srcval;
1508
1509 srcval = fetch_word_imm(emu);
1510 cmp_word(emu, emu->x86.R_AX, srcval);
1511 }
1512
1513 static void
1514 x86emuOp_cmp_word_AX_IMM(struct X86EMU *emu)
1515 {
1516 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1517 x86emuOp32_cmp_word_AX_IMM(emu);
1518 else
1519 x86emuOp16_cmp_word_AX_IMM(emu);
1520 }
1521 /****************************************************************************
1522 REMARKS:
1523 Handles opcode 0x60
1524 ****************************************************************************/
1525 static void
1526 x86emuOp_push_all(struct X86EMU *emu)
1527 {
1528 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1529 uint32_t old_sp = emu->x86.R_ESP;
1530
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;
1541
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);
1550 }
1551 }
1552 /****************************************************************************
1553 REMARKS:
1554 Handles opcode 0x61
1555 ****************************************************************************/
1556 static void
1557 x86emuOp_pop_all(struct X86EMU *emu)
1558 {
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);
1577 }
1578 }
1579 /*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */
1580 /*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */
1581
1582 /****************************************************************************
1583 REMARKS:
1584 Handles opcode 0x68
1585 ****************************************************************************/
1586 static void
1587 x86emuOp_push_word_IMM(struct X86EMU *emu)
1588 {
1589 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1590 uint32_t imm;
1591
1592 imm = fetch_long_imm(emu);
1593 push_long(emu, imm);
1594 } else {
1595 uint16_t imm;
1596
1597 imm = fetch_word_imm(emu);
1598 push_word(emu, imm);
1599 }
1600 }
1601 /****************************************************************************
1602 REMARKS:
1603 Handles opcode 0x6a
1604 ****************************************************************************/
1605 static void
1606 x86emuOp_push_byte_IMM(struct X86EMU *emu)
1607 {
1608 int16_t imm;
1609
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);
1615 }
1616 }
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)
1627 {
1628 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1629 ins(emu, 4);
1630 } else {
1631 ins(emu, 2);
1632 }
1633 }
1634 /****************************************************************************
1635 REMARKS:
1636 Handles opcode 0x6f
1637 ****************************************************************************/
1638 static void
1639 x86emuOp_outs_word(struct X86EMU *emu)
1640 {
1641 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1642 outs(emu, 4);
1643 } else {
1644 outs(emu, 2);
1645 }
1646 }
1647 /****************************************************************************
1648 REMARKS:
1649 Handles opcode 0x7c
1650 ****************************************************************************/
1651 static void
1652 x86emuOp_jump_near_L(struct X86EMU *emu)
1653 {
1654 bool sf, of;
1655
1656 sf = ACCESS_FLAG(F_SF) != 0;
1657 of = ACCESS_FLAG(F_OF) != 0;
1658
1659 common_jmp_near(emu, sf != of);
1660 }
1661 /****************************************************************************
1662 REMARKS:
1663 Handles opcode 0x7d
1664 ****************************************************************************/
1665 static void
1666 x86emuOp_jump_near_NL(struct X86EMU *emu)
1667 {
1668 bool sf, of;
1669
1670 sf = ACCESS_FLAG(F_SF) != 0;
1671 of = ACCESS_FLAG(F_OF) != 0;
1672
1673 common_jmp_near(emu, sf == of);
1674 }
1675 /****************************************************************************
1676 REMARKS:
1677 Handles opcode 0x7e
1678 ****************************************************************************/
1679 static void
1680 x86emuOp_jump_near_LE(struct X86EMU *emu)
1681 {
1682 bool sf, of;
1683
1684 sf = ACCESS_FLAG(F_SF) != 0;
1685 of = ACCESS_FLAG(F_OF) != 0;
1686
1687 common_jmp_near(emu, sf != of || ACCESS_FLAG(F_ZF));
1688 }
1689 /****************************************************************************
1690 REMARKS:
1691 Handles opcode 0x7f
1692 ****************************************************************************/
1693 static void
1694 x86emuOp_jump_near_NLE(struct X86EMU *emu)
1695 {
1696 bool sf, of;
1697
1698 sf = ACCESS_FLAG(F_SF) != 0;
1699 of = ACCESS_FLAG(F_OF) != 0;
1700
1701 common_jmp_near(emu, sf == of && !ACCESS_FLAG(F_ZF));
1702 }
1703
1704 static
1705 uint8_t(*const opc80_byte_operation[]) (struct X86EMU *, uint8_t d, uint8_t s) =
1706 {
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 */
1715 };
1716 /****************************************************************************
1717 REMARKS:
1718 Handles opcode 0x80
1719 ****************************************************************************/
1720 static void
1721 x86emuOp_opc80_byte_RM_IMM(struct X86EMU *emu)
1722 {
1723 uint8_t imm, destval;
1724
1725 /*
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
1729 */
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);
1736 }
1737
1738 static
1739 uint16_t(* const opc81_word_operation[]) (struct X86EMU *, uint16_t d, uint16_t s) =
1740 {
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 */
1749 };
1750
1751 static
1752 uint32_t(* const opc81_long_operation[]) (struct X86EMU *, uint32_t d, uint32_t s) =
1753 {
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 */
1762 };
1763 /****************************************************************************
1764 REMARKS:
1765 Handles opcode 0x81
1766 ****************************************************************************/
1767 static void
1768 x86emuOp32_opc81_word_RM_IMM(struct X86EMU *emu)
1769 {
1770 uint32_t destval, imm;
1771
1772 /*
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
1776 */
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);
1783 }
1784
1785 static void
1786 x86emuOp16_opc81_word_RM_IMM(struct X86EMU *emu)
1787 {
1788 uint16_t destval, imm;
1789
1790 /*
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
1794 */
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);
1801 }
1802
1803 static void
1804 x86emuOp_opc81_word_RM_IMM(struct X86EMU *emu)
1805 {
1806 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1807 x86emuOp32_opc81_word_RM_IMM(emu);
1808 else
1809 x86emuOp16_opc81_word_RM_IMM(emu);
1810 }
1811
1812 static
1813 uint8_t(* const opc82_byte_operation[]) (struct X86EMU *, uint8_t s, uint8_t d) =
1814 {
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 */
1823 };
1824 /****************************************************************************
1825 REMARKS:
1826 Handles opcode 0x82
1827 ****************************************************************************/
1828 static void
1829 x86emuOp_opc82_byte_RM_IMM(struct X86EMU *emu)
1830 {
1831 uint8_t imm, destval;
1832
1833 /*
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.
1838 */
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);
1845 }
1846
1847 static
1848 uint16_t(* const opc83_word_operation[]) (struct X86EMU *, uint16_t s, uint16_t d) =
1849 {
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 */
1858 };
1859
1860 static
1861 uint32_t(* const opc83_long_operation[]) (struct X86EMU *, uint32_t s, uint32_t d) =
1862 {
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 */
1871 };
1872 /****************************************************************************
1873 REMARKS:
1874 Handles opcode 0x83
1875 ****************************************************************************/
1876 static void
1877 x86emuOp32_opc83_word_RM_IMM(struct X86EMU *emu)
1878 {
1879 uint32_t destval, imm;
1880
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);
1887 }
1888
1889 static void
1890 x86emuOp16_opc83_word_RM_IMM(struct X86EMU *emu)
1891 {
1892 uint16_t destval, imm;
1893
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);
1900 }
1901
1902 static void
1903 x86emuOp_opc83_word_RM_IMM(struct X86EMU *emu)
1904 {
1905 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1906 x86emuOp32_opc83_word_RM_IMM(emu);
1907 else
1908 x86emuOp16_opc83_word_RM_IMM(emu);
1909 }
1910 /****************************************************************************
1911 REMARKS:
1912 Handles opcode 0x86
1913 ****************************************************************************/
1914 static void
1915 x86emuOp_xchg_byte_RM_R(struct X86EMU *emu)
1916 {
1917 uint8_t *srcreg, destval, tmp;
1918
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);
1926 }
1927 /****************************************************************************
1928 REMARKS:
1929 Handles opcode 0x87
1930 ****************************************************************************/
1931 static void
1932 x86emuOp32_xchg_word_RM_R(struct X86EMU *emu)
1933 {
1934 uint32_t *srcreg, destval, tmp;
1935
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);
1943 }
1944
1945 static void
1946 x86emuOp16_xchg_word_RM_R(struct X86EMU *emu)
1947 {
1948 uint16_t *srcreg, destval, tmp;
1949
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);
1957 }
1958
1959 static void
1960 x86emuOp_xchg_word_RM_R(struct X86EMU *emu)
1961 {
1962 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1963 x86emuOp32_xchg_word_RM_R(emu);
1964 else
1965 x86emuOp16_xchg_word_RM_R(emu);
1966 }
1967 /****************************************************************************
1968 REMARKS:
1969 Handles opcode 0x88
1970 ****************************************************************************/
1971 static void
1972 x86emuOp_mov_byte_RM_R(struct X86EMU *emu)
1973 {
1974 uint8_t *destreg, *srcreg;
1975 uint32_t destoffset;
1976
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;
1985 }
1986 }
1987 /****************************************************************************
1988 REMARKS:
1989 Handles opcode 0x89
1990 ****************************************************************************/
1991 static void
1992 x86emuOp32_mov_word_RM_R(struct X86EMU *emu)
1993 {
1994 uint32_t destoffset;
1995 uint32_t *destreg, srcval;
1996
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;
2005 }
2006 }
2007
2008 static void
2009 x86emuOp16_mov_word_RM_R(struct X86EMU *emu)
2010 {
2011 uint32_t destoffset;
2012 uint16_t *destreg, srcval;
2013
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;
2022 }
2023 }
2024
2025 static void
2026 x86emuOp_mov_word_RM_R(struct X86EMU *emu)
2027 {
2028 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2029 x86emuOp32_mov_word_RM_R(emu);
2030 else
2031 x86emuOp16_mov_word_RM_R(emu);
2032 }
2033 /****************************************************************************
2034 REMARKS:
2035 Handles opcode 0x8a
2036 ****************************************************************************/
2037 static void
2038 x86emuOp_mov_byte_R_RM(struct X86EMU *emu)
2039 {
2040 uint8_t *destreg;
2041
2042 fetch_decode_modrm(emu);
2043 destreg = decode_rh_byte_register(emu);
2044 *destreg = decode_and_fetch_byte(emu);
2045 }
2046 /****************************************************************************
2047 REMARKS:
2048 Handles opcode 0x8b
2049 ****************************************************************************/
2050 static void
2051 x86emuOp_mov_word_R_RM(struct X86EMU *emu)
2052 {
2053 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2054 uint32_t *destreg;
2055
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;
2061
2062 fetch_decode_modrm(emu);
2063 destreg = decode_rh_word_register(emu);
2064 *destreg = decode_and_fetch_word(emu);
2065 }
2066 }
2067 /****************************************************************************
2068 REMARKS:
2069 Handles opcode 0x8c
2070 ****************************************************************************/
2071 static void
2072 x86emuOp_mov_word_RM_SR(struct X86EMU *emu)
2073 {
2074 uint16_t *destreg, srcval;
2075 uint32_t destoffset;
2076
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;
2085 }
2086 }
2087 /****************************************************************************
2088 REMARKS:
2089 Handles opcode 0x8d
2090 ****************************************************************************/
2091 static void
2092 x86emuOp_lea_word_R_M(struct X86EMU *emu)
2093 {
2094 uint16_t *srcreg;
2095 uint32_t destoffset;
2096
2097 /*
2098 * TODO: Need to handle address size prefix!
2099 *
2100 * lea eax,[eax+ebx*2] ??
2101 */
2102 fetch_decode_modrm(emu);
2103 if (emu->cur_mod == 3)
2104 X86EMU_halt_sys(emu);
2105
2106 srcreg = decode_rh_word_register(emu);
2107 destoffset = decode_rl_address(emu);
2108 *srcreg = (uint16_t) destoffset;
2109 }
2110 /****************************************************************************
2111 REMARKS:
2112 Handles opcode 0x8e
2113 ****************************************************************************/
2114 static void
2115 x86emuOp_mov_word_SR_RM(struct X86EMU *emu)
2116 {
2117 uint16_t *destreg;
2118
2119 fetch_decode_modrm(emu);
2120 destreg = decode_rh_seg_register(emu);
2121 *destreg = decode_and_fetch_word(emu);
2122 /*
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.
2127 */
2128 }
2129 /****************************************************************************
2130 REMARKS:
2131 Handles opcode 0x8f
2132 ****************************************************************************/
2133 static void
2134 x86emuOp32_pop_RM(struct X86EMU *emu)
2135 {
2136 uint32_t destoffset;
2137 uint32_t destval, *destreg;
2138
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);
2147 }
2148 }
2149
2150 static void
2151 x86emuOp16_pop_RM(struct X86EMU *emu)
2152 {
2153 uint32_t destoffset;
2154 uint16_t destval, *destreg;
2155
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);
2164 }
2165 }
2166
2167 static void
2168 x86emuOp_pop_RM(struct X86EMU *emu)
2169 {
2170 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2171 x86emuOp32_pop_RM(emu);
2172 else
2173 x86emuOp16_pop_RM(emu);
2174 }
2175 /****************************************************************************
2176 REMARKS:
2177 Handles opcode 0x91
2178 ****************************************************************************/
2179 static void
2180 x86emuOp_xchg_word_AX_CX(struct X86EMU *emu)
2181 {
2182 uint32_t tmp;
2183
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;
2192 }
2193 }
2194 /****************************************************************************
2195 REMARKS:
2196 Handles opcode 0x92
2197 ****************************************************************************/
2198 static void
2199 x86emuOp_xchg_word_AX_DX(struct X86EMU *emu)
2200 {
2201 uint32_t tmp;
2202
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;
2211 }
2212 }
2213 /****************************************************************************
2214 REMARKS:
2215 Handles opcode 0x93
2216 ****************************************************************************/
2217 static void
2218 x86emuOp_xchg_word_AX_BX(struct X86EMU *emu)
2219 {
2220 uint32_t tmp;
2221
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;
2230 }
2231 }
2232 /****************************************************************************
2233 REMARKS:
2234 Handles opcode 0x94
2235 ****************************************************************************/
2236 static void
2237 x86emuOp_xchg_word_AX_SP(struct X86EMU *emu)
2238 {
2239 uint32_t tmp;
2240
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;
2249 }
2250 }
2251 /****************************************************************************
2252 REMARKS:
2253 Handles opcode 0x95
2254 ****************************************************************************/
2255 static void
2256 x86emuOp_xchg_word_AX_BP(struct X86EMU *emu)
2257 {
2258 uint32_t tmp;
2259
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;
2268 }
2269 }
2270 /****************************************************************************
2271 REMARKS:
2272 Handles opcode 0x96
2273 ****************************************************************************/
2274 static void
2275 x86emuOp_xchg_word_AX_SI(struct X86EMU *emu)
2276 {
2277 uint32_t tmp;
2278
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;
2287 }
2288 }
2289 /****************************************************************************
2290 REMARKS:
2291 Handles opcode 0x97
2292 ****************************************************************************/
2293 static void
2294 x86emuOp_xchg_word_AX_DI(struct X86EMU *emu)
2295 {
2296 uint32_t tmp;
2297
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;
2306 }
2307 }
2308 /****************************************************************************
2309 REMARKS:
2310 Handles opcode 0x98
2311 ****************************************************************************/
2312 static void
2313 x86emuOp_cbw(struct X86EMU *emu)
2314 {
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;
2320 }
2321 } else {
2322 if (emu->x86.R_AL & 0x80) {
2323 emu->x86.R_AH = 0xff;
2324 } else {
2325 emu->x86.R_AH = 0x0;
2326 }
2327 }
2328 }
2329 /****************************************************************************
2330 REMARKS:
2331 Handles opcode 0x99
2332 ****************************************************************************/
2333 static void
2334 x86emuOp_cwd(struct X86EMU *emu)
2335 {
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;
2341 }
2342 } else {
2343 if (emu->x86.R_AX & 0x8000) {
2344 emu->x86.R_DX = 0xffff;
2345 } else {
2346 emu->x86.R_DX = 0x0;
2347 }
2348 }
2349 }
2350 /****************************************************************************
2351 REMARKS:
2352 Handles opcode 0x9a
2353 ****************************************************************************/
2354 static void
2355 x86emuOp_call_far_IMM(struct X86EMU *emu)
2356 {
2357 uint16_t farseg, faroff;
2358
2359 faroff = fetch_word_imm(emu);
2360 farseg = fetch_word_imm(emu);
2361 /* XXX
2362 *
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;
2370 }
2371 /****************************************************************************
2372 REMARKS:
2373 Handles opcode 0x9c
2374 ****************************************************************************/
2375 static void
2376 x86emuOp_pushf_word(struct X86EMU *emu)
2377 {
2378 uint32_t flags;
2379
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);
2386 }
2387 }
2388 /****************************************************************************
2389 REMARKS:
2390 Handles opcode 0x9d
2391 ****************************************************************************/
2392 static void
2393 x86emuOp_popf_word(struct X86EMU *emu)
2394 {
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);
2399 }
2400 }
2401 /****************************************************************************
2402 REMARKS:
2403 Handles opcode 0x9e
2404 ****************************************************************************/
2405 static void
2406 x86emuOp_sahf(struct X86EMU *emu)
2407 {
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;
2412 }
2413 /****************************************************************************
2414 REMARKS:
2415 Handles opcode 0x9f
2416 ****************************************************************************/
2417 static void
2418 x86emuOp_lahf(struct X86EMU *emu)
2419 {
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;
2424 }
2425 /****************************************************************************
2426 REMARKS:
2427 Handles opcode 0xa0
2428 ****************************************************************************/
2429 static void
2430 x86emuOp_mov_AL_M_IMM(struct X86EMU *emu)
2431 {
2432 uint16_t offset;
2433
2434 offset = fetch_word_imm(emu);
2435 emu->x86.R_AL = fetch_data_byte(emu, offset);
2436 }
2437 /****************************************************************************
2438 REMARKS:
2439 Handles opcode 0xa1
2440 ****************************************************************************/
2441 static void
2442 x86emuOp_mov_AX_M_IMM(struct X86EMU *emu)
2443 {
2444 uint16_t offset;
2445
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);
2451 }
2452 }
2453 /****************************************************************************
2454 REMARKS:
2455 Handles opcode 0xa2
2456 ****************************************************************************/
2457 static void
2458 x86emuOp_mov_M_AL_IMM(struct X86EMU *emu)
2459 {
2460 uint16_t offset;
2461
2462 offset = fetch_word_imm(emu);
2463 store_data_byte(emu, offset, emu->x86.R_AL);
2464 }
2465 /****************************************************************************
2466 REMARKS:
2467 Handles opcode 0xa3
2468 ****************************************************************************/
2469 static void
2470 x86emuOp_mov_M_AX_IMM(struct X86EMU *emu)
2471 {
2472 uint16_t offset;
2473
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);
2479 }
2480 }
2481 /****************************************************************************
2482 REMARKS:
2483 Handles opcode 0xa4
2484 ****************************************************************************/
2485 static void
2486 x86emuOp_movs_byte(struct X86EMU *emu)
2487 {
2488 uint8_t val;
2489 uint32_t count;
2490 int inc;
2491
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);
2503 }
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;
2509 }
2510 }
2511 /****************************************************************************
2512 REMARKS:
2513 Handles opcode 0xa5
2514 ****************************************************************************/
2515 static void
2516 x86emuOp_movs_word(struct X86EMU *emu)
2517 {
2518 uint32_t val;
2519 int inc;
2520 uint32_t count;
2521
2522 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2523 inc = 4;
2524 else
2525 inc = 2;
2526
2527 if (ACCESS_FLAG(F_DF)) /* down */
2528 inc = -inc;
2529
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);
2537 }
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);
2545 }
2546 emu->x86.R_SI += inc;
2547 emu->x86.R_DI += inc;
2548 }
2549 }
2550 /****************************************************************************
2551 REMARKS:
2552 Handles opcode 0xa6
2553 ****************************************************************************/
2554 static void
2555 x86emuOp_cmps_byte(struct X86EMU *emu)
2556 {
2557 int8_t val1, val2;
2558 int inc;
2559
2560 if (ACCESS_FLAG(F_DF)) /* down */
2561 inc = -1;
2562 else
2563 inc = 1;
2564
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;
2577 }
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 */
2591 }
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;
2599 }
2600 }
2601 /****************************************************************************
2602 REMARKS:
2603 Handles opcode 0xa7
2604 ****************************************************************************/
2605 static void
2606 x86emuOp_cmps_word(struct X86EMU *emu)
2607 {
2608 uint32_t val1, val2;
2609 int inc;
2610
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;
2621 }
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);
2634 }
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;
2640 }
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);
2654 }
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 */
2660 }
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);
2671 }
2672 emu->x86.R_SI += inc;
2673 emu->x86.R_DI += inc;
2674 }
2675 }
2676 /****************************************************************************
2677 REMARKS:
2678 Handles opcode 0xa9
2679 ****************************************************************************/
2680 static void
2681 x86emuOp_test_AX_IMM(struct X86EMU *emu)
2682 {
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));
2687 }
2688 }
2689 /****************************************************************************
2690 REMARKS:
2691 Handles opcode 0xaa
2692 ****************************************************************************/
2693 static void
2694 x86emuOp_stos_byte(struct X86EMU *emu)
2695 {
2696 int inc;
2697
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;
2709 }
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;
2714 }
2715 }
2716 /****************************************************************************
2717 REMARKS:
2718 Handles opcode 0xab
2719 ****************************************************************************/
2720 static void
2721 x86emuOp_stos_word(struct X86EMU *emu)
2722 {
2723 int inc;
2724 uint32_t count;
2725
2726 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2727 inc = 4;
2728 else
2729 inc = 2;
2730
2731 if (ACCESS_FLAG(F_DF)) /* down */
2732 inc = -inc;
2733
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);
2741 }
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);
2747 }
2748 emu->x86.R_DI += inc;
2749 }
2750 }
2751 /****************************************************************************
2752 REMARKS:
2753 Handles opcode 0xac
2754 ****************************************************************************/
2755 static void
2756 x86emuOp_lods_byte(struct X86EMU *emu)
2757 {
2758 int inc;
2759
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;
2771 }
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;
2776 }
2777 }
2778 /****************************************************************************
2779 REMARKS:
2780 Handles opcode 0xad
2781 ****************************************************************************/
2782 static void
2783 x86emuOp_lods_word(struct X86EMU *emu)
2784 {
2785 int inc;
2786 uint32_t count;
2787
2788 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2789 inc = 4;
2790 else
2791 inc = 2;
2792
2793 if (ACCESS_FLAG(F_DF)) /* down */
2794 inc = -inc;
2795
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);
2803 }
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);
2809 }
2810 emu->x86.R_SI += inc;
2811 }
2812 }
2813 /****************************************************************************
2814 REMARKS:
2815 Handles opcode 0xae
2816 ****************************************************************************/
2817 static void
2818 x86emuOp_scas_byte(struct X86EMU *emu)
2819 {
2820 int8_t val2;
2821 int inc;
2822
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;
2837 }
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 */
2849 }
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;
2855 }
2856 }
2857 /****************************************************************************
2858 REMARKS:
2859 Handles opcode 0xaf
2860 ****************************************************************************/
2861 static void
2862 x86emuOp_scas_word(struct X86EMU *emu)
2863 {
2864 int inc;
2865 uint32_t val;
2866
2867 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2868 inc = 4;
2869 else
2870 inc = 2;
2871
2872 if (ACCESS_FLAG(F_DF)) /* down */
2873 inc = -inc;
2874
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);
2885 }
2886 emu->x86.R_CX -= 1;
2887 emu->x86.R_DI += inc;
2888 if (ACCESS_FLAG(F_ZF) == 0)
2889 break;
2890 }
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);
2902 }
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 */
2907 }
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);
2916 }
2917 emu->x86.R_DI += inc;
2918 }
2919 }
2920 /****************************************************************************
2921 REMARKS:
2922 Handles opcode 0xb8
2923 ****************************************************************************/
2924 static void
2925 x86emuOp_mov_word_AX_IMM(struct X86EMU *emu)
2926 {
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);
2931 }
2932 /****************************************************************************
2933 REMARKS:
2934 Handles opcode 0xb9
2935 ****************************************************************************/
2936 static void
2937 x86emuOp_mov_word_CX_IMM(struct X86EMU *emu)
2938 {
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);
2943 }
2944 /****************************************************************************
2945 REMARKS:
2946 Handles opcode 0xba
2947 ****************************************************************************/
2948 static void
2949 x86emuOp_mov_word_DX_IMM(struct X86EMU *emu)
2950 {
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);
2955 }
2956 /****************************************************************************
2957 REMARKS:
2958 Handles opcode 0xbb
2959 ****************************************************************************/
2960 static void
2961 x86emuOp_mov_word_BX_IMM(struct X86EMU *emu)
2962 {
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);
2967 }
2968 /****************************************************************************
2969 REMARKS:
2970 Handles opcode 0xbc
2971 ****************************************************************************/
2972 static void
2973 x86emuOp_mov_word_SP_IMM(struct X86EMU *emu)
2974 {
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);
2979 }
2980 /****************************************************************************
2981 REMARKS:
2982 Handles opcode 0xbd
2983 ****************************************************************************/
2984 static void
2985 x86emuOp_mov_word_BP_IMM(struct X86EMU *emu)
2986 {
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);
2991 }
2992 /****************************************************************************
2993 REMARKS:
2994 Handles opcode 0xbe
2995 ****************************************************************************/
2996 static void
2997 x86emuOp_mov_word_SI_IMM(struct X86EMU *emu)
2998 {
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);
3003 }
3004 /****************************************************************************
3005 REMARKS:
3006 Handles opcode 0xbf
3007 ****************************************************************************/
3008 static void
3009 x86emuOp_mov_word_DI_IMM(struct X86EMU *emu)
3010 {
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);
3015 }
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) =
3019 {
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,
3028 };
3029 /****************************************************************************
3030 REMARKS:
3031 Handles opcode 0xc0
3032 ****************************************************************************/
3033 static void
3034 x86emuOp_opcC0_byte_RM_MEM(struct X86EMU *emu)
3035 {
3036 uint8_t destval, amt;
3037
3038 /*
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
3042 */
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);
3048 }
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) =
3052 {
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,
3061 };
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) =
3065 {
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,
3074 };
3075 /****************************************************************************
3076 REMARKS:
3077 Handles opcode 0xc1
3078 ****************************************************************************/
3079 static void
3080 x86emuOp_opcC1_word_RM_MEM(struct X86EMU *emu)
3081 {
3082 uint8_t amt;
3083
3084 /*
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
3088 */
3089 fetch_decode_modrm(emu);
3090 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3091 uint32_t destval;
3092
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;
3098
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);
3102 }
3103 }
3104 /****************************************************************************
3105 REMARKS:
3106 Handles opcode 0xc2
3107 ****************************************************************************/
3108 static void
3109 x86emuOp_ret_near_IMM(struct X86EMU *emu)
3110 {
3111 uint16_t imm;
3112
3113 imm = fetch_word_imm(emu);
3114 emu->x86.R_IP = pop_word(emu);
3115 emu->x86.R_SP += imm;
3116 }
3117 /****************************************************************************
3118 REMARKS:
3119 Handles opcode 0xc6
3120 ****************************************************************************/
3121 static void
3122 x86emuOp_mov_byte_RM_IMM(struct X86EMU *emu)
3123 {
3124 uint8_t *destreg;
3125 uint32_t destoffset;
3126 uint8_t imm;
3127
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;
3139 }
3140 }
3141 /****************************************************************************
3142 REMARKS:
3143 Handles opcode 0xc7
3144 ****************************************************************************/
3145 static void
3146 x86emuOp32_mov_word_RM_IMM(struct X86EMU *emu)
3147 {
3148 uint32_t destoffset;
3149 uint32_t imm, *destreg;
3150
3151 fetch_decode_modrm(emu);
3152 if (emu->cur_rh != 0)
3153 X86EMU_halt_sys(emu);
3154
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;
3163 }
3164 }
3165
3166 static void
3167 x86emuOp16_mov_word_RM_IMM(struct X86EMU *emu)
3168 {
3169 uint32_t destoffset;
3170 uint16_t imm, *destreg;
3171
3172 fetch_decode_modrm(emu);
3173 if (emu->cur_rh != 0)
3174 X86EMU_halt_sys(emu);
3175
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;
3184 }
3185 }
3186
3187 static void
3188 x86emuOp_mov_word_RM_IMM(struct X86EMU *emu)
3189 {
3190 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3191 x86emuOp32_mov_word_RM_IMM(emu);
3192 else
3193 x86emuOp16_mov_word_RM_IMM(emu);
3194 }
3195 /****************************************************************************
3196 REMARKS:
3197 Handles opcode 0xc8
3198 ****************************************************************************/
3199 static void
3200 x86emuOp_enter(struct X86EMU *emu)
3201 {
3202 uint16_t local, frame_pointer;
3203 uint8_t nesting;
3204 int i;
3205
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));
3214 }
3215 push_word(emu, frame_pointer);
3216 }
3217 emu->x86.R_BP = frame_pointer;
3218 emu->x86.R_SP = (uint16_t) (emu->x86.R_SP - local);
3219 }
3220 /****************************************************************************
3221 REMARKS:
3222 Handles opcode 0xc9
3223 ****************************************************************************/
3224 static void
3225 x86emuOp_leave(struct X86EMU *emu)
3226 {
3227 emu->x86.R_SP = emu->x86.R_BP;
3228 emu->x86.R_BP = pop_word(emu);
3229 }
3230 /****************************************************************************
3231 REMARKS:
3232 Handles opcode 0xca
3233 ****************************************************************************/
3234 static void
3235 x86emuOp_ret_far_IMM(struct X86EMU *emu)
3236 {
3237 uint16_t imm;
3238
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;
3243 }
3244 /****************************************************************************
3245 REMARKS:
3246 Handles opcode 0xcb
3247 ****************************************************************************/
3248 static void
3249 x86emuOp_ret_far(struct X86EMU *emu)
3250 {
3251 emu->x86.R_IP = pop_word(emu);
3252 emu->x86.R_CS = pop_word(emu);
3253 }
3254 /****************************************************************************
3255 REMARKS:
3256 Handles opcode 0xcc
3257 ****************************************************************************/
3258 static void
3259 x86emuOp_int3(struct X86EMU *emu)
3260 {
3261 x86emu_intr_dispatch(emu, 3);
3262 }
3263 /****************************************************************************
3264 REMARKS:
3265 Handles opcode 0xcd
3266 ****************************************************************************/
3267 static void
3268 x86emuOp_int_IMM(struct X86EMU *emu)
3269 {
3270 uint8_t intnum;
3271
3272 intnum = fetch_byte_imm(emu);
3273 x86emu_intr_dispatch(emu, intnum);
3274 }
3275 /****************************************************************************
3276 REMARKS:
3277 Handles opcode 0xce
3278 ****************************************************************************/
3279 static void
3280 x86emuOp_into(struct X86EMU *emu)
3281 {
3282 if (ACCESS_FLAG(F_OF))
3283 x86emu_intr_dispatch(emu, 4);
3284 }
3285 /****************************************************************************
3286 REMARKS:
3287 Handles opcode 0xcf
3288 ****************************************************************************/
3289 static void
3290 x86emuOp_iret(struct X86EMU *emu)
3291 {
3292 emu->x86.R_IP = pop_word(emu);
3293 emu->x86.R_CS = pop_word(emu);
3294 emu->x86.R_FLG = pop_word(emu);
3295 }
3296 /****************************************************************************
3297 REMARKS:
3298 Handles opcode 0xd0
3299 ****************************************************************************/
3300 static void
3301 x86emuOp_opcD0_byte_RM_1(struct X86EMU *emu)
3302 {
3303 uint8_t destval;
3304
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);
3309 }
3310 /****************************************************************************
3311 REMARKS:
3312 Handles opcode 0xd1
3313 ****************************************************************************/
3314 static void
3315 x86emuOp_opcD1_word_RM_1(struct X86EMU *emu)
3316 {
3317 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3318 uint32_t destval;
3319
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;
3326
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);
3331 }
3332 }
3333 /****************************************************************************
3334 REMARKS:
3335 Handles opcode 0xd2
3336 ****************************************************************************/
3337 static void
3338 x86emuOp_opcD2_byte_RM_CL(struct X86EMU *emu)
3339 {
3340 uint8_t destval;
3341
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);
3346 }
3347 /****************************************************************************
3348 REMARKS:
3349 Handles opcode 0xd3
3350 ****************************************************************************/
3351 static void
3352 x86emuOp_opcD3_word_RM_CL(struct X86EMU *emu)
3353 {
3354 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3355 uint32_t destval;
3356
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;
3363
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);
3368 }
3369 }
3370 /****************************************************************************
3371 REMARKS:
3372 Handles opcode 0xd4
3373 ****************************************************************************/
3374 static void
3375 x86emuOp_aam(struct X86EMU *emu)
3376 {
3377 uint8_t a;
3378
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);
3383 }
3384 /* note the type change here --- returning AL and AH in AX. */
3385 emu->x86.R_AX = aam_word(emu, emu->x86.R_AL);
3386 }
3387 /****************************************************************************
3388 REMARKS:
3389 Handles opcode 0xd5
3390 ****************************************************************************/
3391 static void
3392 x86emuOp_aad(struct X86EMU *emu)
3393 {
3394 uint8_t a;
3395
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);
3400 }
3401 emu->x86.R_AX = aad_word(emu, emu->x86.R_AX);
3402 }
3403 /* opcode 0xd6 ILLEGAL OPCODE */
3404
3405 /****************************************************************************
3406 REMARKS:
3407 Handles opcode 0xd7
3408 ****************************************************************************/
3409 static void
3410 x86emuOp_xlat(struct X86EMU *emu)
3411 {
3412 uint16_t addr;
3413
3414 addr = (uint16_t) (emu->x86.R_BX + (uint8_t) emu->x86.R_AL);
3415 emu->x86.R_AL = fetch_data_byte(emu, addr);
3416 }
3417
3418 /* opcode=0xd8 */
3419 static void
3420 x86emuOp_esc_coprocess_d8(struct X86EMU *emu)
3421 {
3422 }
3423 /* opcode=0xd9 */
3424 static void
3425 x86emuOp_esc_coprocess_d9(struct X86EMU *emu)
3426 {
3427 fetch_decode_modrm(emu);
3428 if (emu->cur_mod != 3)
3429 decode_rl_address(emu);
3430 }
3431 /* opcode=0xda */
3432 static void
3433 x86emuOp_esc_coprocess_da(struct X86EMU *emu)
3434 {
3435 fetch_decode_modrm(emu);
3436 if (emu->cur_mod != 3)
3437 decode_rl_address(emu);
3438 }
3439 /* opcode=0xdb */
3440 static void
3441 x86emuOp_esc_coprocess_db(struct X86EMU *emu)
3442 {
3443 fetch_decode_modrm(emu);
3444 if (emu->cur_mod != 3)
3445 decode_rl_address(emu);
3446 }
3447 /* opcode=0xdc */
3448 static void
3449 x86emuOp_esc_coprocess_dc(struct X86EMU *emu)
3450 {
3451 fetch_decode_modrm(emu);
3452 if (emu->cur_mod != 3)
3453 decode_rl_address(emu);
3454 }
3455 /* opcode=0xdd */
3456 static void
3457 x86emuOp_esc_coprocess_dd(struct X86EMU *emu)
3458 {
3459 fetch_decode_modrm(emu);
3460 if (emu->cur_mod != 3)
3461 decode_rl_address(emu);
3462 }
3463 /* opcode=0xde */
3464 static void
3465 x86emuOp_esc_coprocess_de(struct X86EMU *emu)
3466 {
3467 fetch_decode_modrm(emu);
3468 if (emu->cur_mod != 3)
3469 decode_rl_address(emu);
3470 }
3471 /* opcode=0xdf */
3472 static void
3473 x86emuOp_esc_coprocess_df(struct X86EMU *emu)
3474 {
3475 fetch_decode_modrm(emu);
3476 if (emu->cur_mod != 3)
3477 decode_rl_address(emu);
3478 }
3479
3480 /****************************************************************************
3481 REMARKS:
3482 Handles opcode 0xe0
3483 ****************************************************************************/
3484 static void
3485 x86emuOp_loopne(struct X86EMU *emu)
3486 {
3487 int16_t ip;
3488
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;
3494 }
3495 /****************************************************************************
3496 REMARKS:
3497 Handles opcode 0xe1
3498 ****************************************************************************/
3499 static void
3500 x86emuOp_loope(struct X86EMU *emu)
3501 {
3502 int16_t ip;
3503
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;
3509 }
3510 /****************************************************************************
3511 REMARKS:
3512 Handles opcode 0xe2
3513 ****************************************************************************/
3514 static void
3515 x86emuOp_loop(struct X86EMU *emu)
3516 {
3517 int16_t ip;
3518
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;
3524 }
3525 /****************************************************************************
3526 REMARKS:
3527 Handles opcode 0xe3
3528 ****************************************************************************/
3529 static void
3530 x86emuOp_jcxz(struct X86EMU *emu)
3531 {
3532 uint16_t target;
3533 int8_t offset;
3534
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;
3540 }
3541 /****************************************************************************
3542 REMARKS:
3543 Handles opcode 0xe4
3544 ****************************************************************************/
3545 static void
3546 x86emuOp_in_byte_AL_IMM(struct X86EMU *emu)
3547 {
3548 uint8_t port;
3549
3550 port = (uint8_t) fetch_byte_imm(emu);
3551 emu->x86.R_AL = (*emu->emu_inb) (emu, port);
3552 }
3553 /****************************************************************************
3554 REMARKS:
3555 Handles opcode 0xe5
3556 ****************************************************************************/
3557 static void
3558 x86emuOp_in_word_AX_IMM(struct X86EMU *emu)
3559 {
3560 uint8_t port;
3561
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);
3567 }
3568 }
3569 /****************************************************************************
3570 REMARKS:
3571 Handles opcode 0xe6
3572 ****************************************************************************/
3573 static void
3574 x86emuOp_out_byte_IMM_AL(struct X86EMU *emu)
3575 {
3576 uint8_t port;
3577
3578 port = (uint8_t) fetch_byte_imm(emu);
3579 (*emu->emu_outb) (emu, port, emu->x86.R_AL);
3580 }
3581 /****************************************************************************
3582 REMARKS:
3583 Handles opcode 0xe7
3584 ****************************************************************************/
3585 static void
3586 x86emuOp_out_word_IMM_AX(struct X86EMU *emu)
3587 {
3588 uint8_t port;
3589
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);
3595 }
3596 }
3597 /****************************************************************************
3598 REMARKS:
3599 Handles opcode 0xe8
3600 ****************************************************************************/
3601 static void
3602 x86emuOp_call_near_IMM(struct X86EMU *emu)
3603 {
3604 int16_t ip;
3605
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;
3610 }
3611 /****************************************************************************
3612 REMARKS:
3613 Handles opcode 0xe9
3614 ****************************************************************************/
3615 static void
3616 x86emuOp_jump_near_IMM(struct X86EMU *emu)
3617 {
3618 int ip;
3619
3620 ip = (int16_t) fetch_word_imm(emu);
3621 ip += (int16_t) emu->x86.R_IP;
3622 emu->x86.R_IP = (uint16_t) ip;
3623 }
3624 /****************************************************************************
3625 REMARKS:
3626 Handles opcode 0xea
3627 ****************************************************************************/
3628 static void
3629 x86emuOp_jump_far_IMM(struct X86EMU *emu)
3630 {
3631 uint16_t cs, ip;
3632
3633 ip = fetch_word_imm(emu);
3634 cs = fetch_word_imm(emu);
3635 emu->x86.R_IP = ip;
3636 emu->x86.R_CS = cs;
3637 }
3638 /****************************************************************************
3639 REMARKS:
3640 Handles opcode 0xeb
3641 ****************************************************************************/
3642 static void
3643 x86emuOp_jump_byte_IMM(struct X86EMU *emu)
3644 {
3645 uint16_t target;
3646 int8_t offset;
3647
3648 offset = (int8_t) fetch_byte_imm(emu);
3649 target = (uint16_t) (emu->x86.R_IP + offset);
3650 emu->x86.R_IP = target;
3651 }
3652 /****************************************************************************
3653 REMARKS:
3654 Handles opcode 0xec
3655 ****************************************************************************/
3656 static void
3657 x86emuOp_in_byte_AL_DX(struct X86EMU *emu)
3658 {
3659 emu->x86.R_AL = (*emu->emu_inb) (emu, emu->x86.R_DX);
3660 }
3661 /****************************************************************************
3662 REMARKS:
3663 Handles opcode 0xed
3664 ****************************************************************************/
3665 static void
3666 x86emuOp_in_word_AX_DX(struct X86EMU *emu)
3667 {
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);
3672 }
3673 }
3674 /****************************************************************************
3675 REMARKS:
3676 Handles opcode 0xee
3677 ****************************************************************************/
3678 static void
3679 x86emuOp_out_byte_DX_AL(struct X86EMU *emu)
3680 {
3681 (*emu->emu_outb) (emu, emu->x86.R_DX, emu->x86.R_AL);
3682 }
3683 /****************************************************************************
3684 REMARKS:
3685 Handles opcode 0xef
3686 ****************************************************************************/
3687 static void
3688 x86emuOp_out_word_DX_AX(struct X86EMU *emu)
3689 {
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);
3694 }
3695 }
3696 /****************************************************************************
3697 REMARKS:
3698 Handles opcode 0xf0
3699 ****************************************************************************/
3700 static void
3701 x86emuOp_lock(struct X86EMU *emu)
3702 {
3703 }
3704 /*opcode 0xf1 ILLEGAL OPERATION */
3705
3706 /****************************************************************************
3707 REMARKS:
3708 Handles opcode 0xf5
3709 ****************************************************************************/
3710 static void
3711 x86emuOp_cmc(struct X86EMU *emu)
3712 {
3713 if (ACCESS_FLAG(F_CF))
3714 CLEAR_FLAG(F_CF);
3715 else
3716 SET_FLAG(F_CF);
3717 }
3718 /****************************************************************************
3719 REMARKS:
3720 Handles opcode 0xf6
3721 ****************************************************************************/
3722 static void
3723 x86emuOp_opcF6_byte_RM(struct X86EMU *emu)
3724 {
3725 uint8_t destval, srcval;
3726
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);
3732
3733 if (emu->cur_rh == 0) {
3734 destval = decode_and_fetch_byte_imm8(emu, &srcval);
3735 test_byte(emu, destval, srcval);
3736 return;
3737 }
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;
3760 }
3761 }
3762 /****************************************************************************
3763 REMARKS:
3764 Handles opcode 0xf7
3765 ****************************************************************************/
3766 static void
3767 x86emuOp32_opcF7_word_RM(struct X86EMU *emu)
3768 {
3769 uint32_t destval, srcval;
3770
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);
3776
3777 if (emu->cur_rh == 0) {
3778 if (emu->cur_mod != 3) {
3779 uint32_t destoffset;
3780
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);
3787 }
3788 test_long(emu, destval, srcval);
3789 return;
3790 }
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;
3813 }
3814 }
3815 static void
3816 x86emuOp16_opcF7_word_RM(struct X86EMU *emu)
3817 {
3818 uint16_t destval, srcval;
3819
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);
3825
3826 if (emu->cur_rh == 0) {
3827 if (emu->cur_mod != 3) {
3828 uint32_t destoffset;
3829
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);
3836 }
3837 test_word(emu, destval, srcval);
3838 return;
3839 }
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;
3862 }
3863 }
3864 static void
3865 x86emuOp_opcF7_word_RM(struct X86EMU *emu)
3866 {
3867 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3868 x86emuOp32_opcF7_word_RM(emu);
3869 else
3870 x86emuOp16_opcF7_word_RM(emu);
3871 }
3872 /****************************************************************************
3873 REMARKS:
3874 Handles opcode 0xfe
3875 ****************************************************************************/
3876 static void
3877 x86emuOp_opcFE_byte_RM(struct X86EMU *emu)
3878 {
3879 uint8_t destval;
3880 uint32_t destoffset;
3881 uint8_t *destreg;
3882
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;
3898 }
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;
3908 }
3909 }
3910 }
3911 /****************************************************************************
3912 REMARKS:
3913 Handles opcode 0xff
3914 ****************************************************************************/
3915 static void
3916 x86emuOp32_opcFF_word_RM(struct X86EMU *emu)
3917 {
3918 uint32_t destoffset = 0;
3919 uint32_t destval, *destreg;
3920
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;
3936 }
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;
3949 }
3950 }
3951 }
3952
3953 static void
3954 x86emuOp16_opcFF_word_RM(struct X86EMU *emu)
3955 {
3956 uint32_t destoffset = 0;
3957 uint16_t *destreg;
3958 uint16_t destval;
3959
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;
3975 }
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;
3988 }
3989 }
3990 }
3991
3992 static void
3993 x86emuOp_opcFF_word_RM(struct X86EMU *emu)
3994 {
3995 uint32_t destoffset = 0;
3996 uint16_t destval, destval2;
3997
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;
4008 }
4009
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;
4026 }
4027 } else {
4028 destval = *decode_rl_word_register(emu);
4029 }
4030
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;
4039 }
4040 }
4041 /***************************************************************************
4042 * Single byte operation code table:
4043 **************************************************************************/
4044 static void
4045 X86EMU_exec_one_byte(struct X86EMU * emu)
4046 {
4047 uint8_t op1;
4048
4049 op1 = fetch_byte_imm(emu);
4050
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;
4076
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;
4101
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;
4126
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;
4151
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;
4176
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;
4201
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;
4226
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;
4252
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;
4277
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;
4302
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;
4327
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;
4352
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;
4373
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;
4398
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;
4423
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;
4448
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;
4473
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;
4498
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;
4523
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;
4548
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;
4573
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;
4598
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;
4623
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;
4648
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;
4697
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;
4744
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;
4769
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;
4794
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;
4816
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;
4844 }
4845 if (op1 != 0x26 && op1 != 0x2e && op1 != 0x36 && op1 != 0x3e &&
4846 (op1 | 3) != 0x67)
4847 emu->x86.mode &= ~SYSMODE_CLRMASK;
4848 }
4849
4850 static void
4851 common_jmp_long(struct X86EMU *emu, bool cond)
4852 {
4853 int16_t target;
4854
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;
4859 }
4860
4861 static void
4862 common_set_byte(struct X86EMU *emu, bool cond)
4863 {
4864 uint32_t destoffset;
4865 uint8_t *destreg, destval;
4866
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;
4875 }
4876 }
4877
4878 static void
4879 common_bitstring32(struct X86EMU *emu, int op)
4880 {
4881 int bit;
4882 uint32_t srcval, *shiftreg, mask;
4883
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);
4890
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;
4903 }
4904 }
4905
4906 static void
4907 common_bitstring16(struct X86EMU *emu, int op)
4908 {
4909 int bit;
4910 uint16_t srcval, *shiftreg, mask;
4911
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);
4918
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;
4931 }
4932 }
4933
4934 static void
4935 common_bitstring(struct X86EMU *emu, int op)
4936 {
4937 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
4938 common_bitstring32(emu, op);
4939 else
4940 common_bitstring16(emu, op);
4941 }
4942
4943 static void
4944 common_bitsearch32(struct X86EMU *emu, int diff)
4945 {
4946 uint32_t srcval, *dstreg;
4947
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;
4955 }
4956 }
4957
4958 static void
4959 common_bitsearch16(struct X86EMU *emu, int diff)
4960 {
4961 uint16_t srcval, *dstreg;
4962
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;
4970 }
4971 }
4972
4973 static void
4974 common_bitsearch(struct X86EMU *emu, int diff)
4975 {
4976 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
4977 common_bitsearch32(emu, diff);
4978 else
4979 common_bitsearch16(emu, diff);
4980 }
4981
4982 static void
4983 common_shift32(struct X86EMU *emu, bool shift_left, bool use_cl)
4984 {
4985 uint8_t shift;
4986 uint32_t destval, *shiftreg;
4987
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);
4995 }
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);
5001 }
5002
5003 static void
5004 common_shift16(struct X86EMU *emu, bool shift_left, bool use_cl)
5005 {
5006 uint8_t shift;
5007 uint16_t destval, *shiftreg;
5008
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);
5016 }
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);
5022 }
5023
5024 static void
5025 common_shift(struct X86EMU *emu, bool shift_left, bool use_cl)
5026 {
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);
5031 }
5032
5033 /*----------------------------- Implementation ----------------------------*/
5034 #define xorl(a,b) ((a) && !(b)) || (!(a) && (b))
5035
5036 /****************************************************************************
5037 REMARKS:
5038 Handles opcode 0x0f,0x31
5039 ****************************************************************************/
5040 static void
5041 x86emuOp2_rdtsc(struct X86EMU *emu)
5042 {
5043 emu->x86.R_EAX = emu->cur_cycles & 0xffffffff;
5044 emu->x86.R_EDX = emu->cur_cycles >> 32;
5045 }
5046 /****************************************************************************
5047 REMARKS:
5048 Handles opcode 0x0f,0xa0
5049 ****************************************************************************/
5050 static void
5051 x86emuOp2_push_FS(struct X86EMU *emu)
5052 {
5053 push_word(emu, emu->x86.R_FS);
5054 }
5055 /****************************************************************************
5056 REMARKS:
5057 Handles opcode 0x0f,0xa1
5058 ****************************************************************************/
5059 static void
5060 x86emuOp2_pop_FS(struct X86EMU *emu)
5061 {
5062 emu->x86.R_FS = pop_word(emu);
5063 }
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)
5071 {
5072 __asm__ __volatile__("cpuid"
5073 : "=a" (*a), "=b" (*b),
5074 "=c" (*c), "=d" (*d)
5075 : "a" (*a), "c" (*c)
5076 : "cc");
5077 }
5078 #endif
5079 static void
5080 x86emuOp2_cpuid(struct X86EMU *emu)
5081 {
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;
5109 }
5110 }
5111 /****************************************************************************
5112 REMARKS:
5113 Handles opcode 0x0f,0xa3
5114 ****************************************************************************/
5115 static void
5116 x86emuOp2_bt_R(struct X86EMU *emu)
5117 {
5118 common_bitstring(emu, 0);
5119 }
5120 /****************************************************************************
5121 REMARKS:
5122 Handles opcode 0x0f,0xa4
5123 ****************************************************************************/
5124 static void
5125 x86emuOp2_shld_IMM(struct X86EMU *emu)
5126 {
5127 common_shift(emu, true, false);
5128 }
5129 /****************************************************************************
5130 REMARKS:
5131 Handles opcode 0x0f,0xa5
5132 ****************************************************************************/
5133 static void
5134 x86emuOp2_shld_CL(struct X86EMU *emu)
5135 {
5136 common_shift(emu, true, true);
5137 }
5138 /****************************************************************************
5139 REMARKS:
5140 Handles opcode 0x0f,0xa8
5141 ****************************************************************************/
5142 static void
5143 x86emuOp2_push_GS(struct X86EMU *emu)
5144 {
5145 push_word(emu, emu->x86.R_GS);
5146 }
5147 /****************************************************************************
5148 REMARKS:
5149 Handles opcode 0x0f,0xa9
5150 ****************************************************************************/
5151 static void
5152 x86emuOp2_pop_GS(struct X86EMU *emu)
5153 {
5154 emu->x86.R_GS = pop_word(emu);
5155 }
5156 /****************************************************************************
5157 REMARKS:
5158 Handles opcode 0x0f,0xab
5159 ****************************************************************************/
5160 static void
5161 x86emuOp2_bts_R(struct X86EMU *emu)
5162 {
5163 common_bitstring(emu, 1);
5164 }
5165 /****************************************************************************
5166 REMARKS:
5167 Handles opcode 0x0f,0xac
5168 ****************************************************************************/
5169 static void
5170 x86emuOp2_shrd_IMM(struct X86EMU *emu)
5171 {
5172 common_shift(emu, false, false);
5173 }
5174 /****************************************************************************
5175 REMARKS:
5176 Handles opcode 0x0f,0xad
5177 ****************************************************************************/
5178 static void
5179 x86emuOp2_shrd_CL(struct X86EMU *emu)
5180 {
5181 common_shift(emu, false, true);
5182 }
5183 /****************************************************************************
5184 REMARKS:
5185 Handles opcode 0x0f,0xaf
5186 ****************************************************************************/
5187 static void
5188 x86emuOp2_32_imul_R_RM(struct X86EMU *emu)
5189 {
5190 uint32_t *destreg, srcval;
5191 uint64_t res;
5192
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);
5203 }
5204 *destreg = (uint32_t) res;
5205 }
5206
5207 static void
5208 x86emuOp2_16_imul_R_RM(struct X86EMU *emu)
5209 {
5210 uint16_t *destreg, srcval;
5211 uint32_t res;
5212
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);
5223 }
5224 *destreg = (uint16_t) res;
5225 }
5226
5227 static void
5228 x86emuOp2_imul_R_RM(struct X86EMU *emu)
5229 {
5230 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5231 x86emuOp2_32_imul_R_RM(emu);
5232 else
5233 x86emuOp2_16_imul_R_RM(emu);
5234 }
5235 /****************************************************************************
5236 REMARKS:
5237 Handles opcode 0x0f,0xb2
5238 ****************************************************************************/
5239 static void
5240 x86emuOp2_lss_R_IMM(struct X86EMU *emu)
5241 {
5242 common_load_far_pointer(emu, &emu->x86.R_SS);
5243 }
5244 /****************************************************************************
5245 REMARKS:
5246 Handles opcode 0x0f,0xb3
5247 ****************************************************************************/
5248 static void
5249 x86emuOp2_btr_R(struct X86EMU *emu)
5250 {
5251 common_bitstring(emu, 2);
5252 }
5253 /****************************************************************************
5254 REMARKS:
5255 Handles opcode 0x0f,0xb4
5256 ****************************************************************************/
5257 static void
5258 x86emuOp2_lfs_R_IMM(struct X86EMU *emu)
5259 {
5260 common_load_far_pointer(emu, &emu->x86.R_FS);
5261 }
5262 /****************************************************************************
5263 REMARKS:
5264 Handles opcode 0x0f,0xb5
5265 ****************************************************************************/
5266 static void
5267 x86emuOp2_lgs_R_IMM(struct X86EMU *emu)
5268 {
5269 common_load_far_pointer(emu, &emu->x86.R_GS);
5270 }
5271 /****************************************************************************
5272 REMARKS:
5273 Handles opcode 0x0f,0xb6
5274 ****************************************************************************/
5275 static void
5276 x86emuOp2_32_movzx_byte_R_RM(struct X86EMU *emu)
5277 {
5278 uint32_t *destreg;
5279
5280 fetch_decode_modrm(emu);
5281 destreg = decode_rh_long_register(emu);
5282 *destreg = decode_and_fetch_byte(emu);
5283 }
5284
5285 static void
5286 x86emuOp2_16_movzx_byte_R_RM(struct X86EMU *emu)
5287 {
5288 uint16_t *destreg;
5289
5290 fetch_decode_modrm(emu);
5291 destreg = decode_rh_word_register(emu);
5292 *destreg = decode_and_fetch_byte(emu);
5293 }
5294
5295 static void
5296 x86emuOp2_movzx_byte_R_RM(struct X86EMU *emu)
5297 {
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);
5302 }
5303 /****************************************************************************
5304 REMARKS:
5305 Handles opcode 0x0f,0xb7
5306 ****************************************************************************/
5307 static void
5308 x86emuOp2_movzx_word_R_RM(struct X86EMU *emu)
5309 {
5310 uint32_t *destreg;
5311
5312 fetch_decode_modrm(emu);
5313 destreg = decode_rh_long_register(emu);
5314 *destreg = decode_and_fetch_word(emu);
5315 }
5316 /****************************************************************************
5317 REMARKS:
5318 Handles opcode 0x0f,0xba
5319 ****************************************************************************/
5320 static void
5321 x86emuOp2_32_btX_I(struct X86EMU *emu)
5322 {
5323 int bit;
5324 uint32_t srcval, mask;
5325 uint8_t shift;
5326
5327 fetch_decode_modrm(emu);
5328 if (emu->cur_rh < 4)
5329 X86EMU_halt_sys(emu);
5330
5331 srcval = decode_and_fetch_long_imm8(emu, &shift);
5332 bit = shift & 0x1F;
5333 mask = (0x1 << bit);
5334
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;
5345 }
5346 CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5347 }
5348
5349 static void
5350 x86emuOp2_16_btX_I(struct X86EMU *emu)
5351 {
5352 int bit;
5353
5354 uint16_t srcval, mask;
5355 uint8_t shift;
5356
5357 fetch_decode_modrm(emu);
5358 if (emu->cur_rh < 4)
5359 X86EMU_halt_sys(emu);
5360
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;
5374 }
5375 CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5376 }
5377
5378 static void
5379 x86emuOp2_btX_I(struct X86EMU *emu)
5380 {
5381 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5382 x86emuOp2_32_btX_I(emu);
5383 else
5384 x86emuOp2_16_btX_I(emu);
5385 }
5386 /****************************************************************************
5387 REMARKS:
5388 Handles opcode 0x0f,0xbb
5389 ****************************************************************************/
5390 static void
5391 x86emuOp2_btc_R(struct X86EMU *emu)
5392 {
5393 common_bitstring(emu, 3);
5394 }
5395 /****************************************************************************
5396 REMARKS:
5397 Handles opcode 0x0f,0xbc
5398 ****************************************************************************/
5399 static void
5400 x86emuOp2_bsf(struct X86EMU *emu)
5401 {
5402 common_bitsearch(emu, +1);
5403 }
5404 /****************************************************************************
5405 REMARKS:
5406 Handles opcode 0x0f,0xbd
5407 ****************************************************************************/
5408 static void
5409 x86emuOp2_bsr(struct X86EMU *emu)
5410 {
5411 common_bitsearch(emu, -1);
5412 }
5413 /****************************************************************************
5414 REMARKS:
5415 Handles opcode 0x0f,0xbe
5416 ****************************************************************************/
5417 static void
5418 x86emuOp2_32_movsx_byte_R_RM(struct X86EMU *emu)
5419 {
5420 uint32_t *destreg;
5421
5422 fetch_decode_modrm(emu);
5423 destreg = decode_rh_long_register(emu);
5424 *destreg = (int32_t)(int8_t)decode_and_fetch_byte(emu);
5425 }
5426
5427 static void
5428 x86emuOp2_16_movsx_byte_R_RM(struct X86EMU *emu)
5429 {
5430 uint16_t *destreg;
5431
5432 fetch_decode_modrm(emu);
5433 destreg = decode_rh_word_register(emu);
5434 *destreg = (int16_t)(int8_t)decode_and_fetch_byte(emu);
5435 }
5436
5437 static void
5438 x86emuOp2_movsx_byte_R_RM(struct X86EMU *emu)
5439 {
5440 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5441 x86emuOp2_32_movsx_byte_R_RM(emu);
5442 else
5443 x86emuOp2_16_movsx_byte_R_RM(emu);
5444 }
5445 /****************************************************************************
5446 REMARKS:
5447 Handles opcode 0x0f,0xbf
5448 ****************************************************************************/
5449 static void
5450 x86emuOp2_movsx_word_R_RM(struct X86EMU *emu)
5451 {
5452 uint32_t *destreg;
5453
5454 fetch_decode_modrm(emu);
5455 destreg = decode_rh_long_register(emu);
5456 *destreg = (int32_t)(int16_t)decode_and_fetch_word(emu);
5457 }
5458
5459 static void
5460 X86EMU_exec_two_byte(struct X86EMU * emu)
5461 {
5462 uint8_t op2;
5463
5464 op2 = fetch_byte_imm(emu);
5465
5466 switch (op2) {
5467 /* 0x00 Group F (ring 0 PM) */
5468 /* 0x01 Group G (ring 0 PM) */
5469 /* 0x02 lar (ring 0 PM) */
5470 /* 0x03 lsl (ring 0 PM) */
5471 /* 0x05 loadall (undocumented) */
5472 /* 0x06 clts (ring 0 PM) */
5473 /* 0x07 loadall (undocumented) */
5474 /* 0x08 invd (ring 0 PM) */
5475 /* 0x09 wbinvd (ring 0 PM) */
5476
5477 /* 0x20 mov reg32(op2); break;creg (ring 0 PM) */
5478 /* 0x21 mov reg32(op2); break;dreg (ring 0 PM) */
5479 /* 0x22 mov creg(op2); break;reg32 (ring 0 PM) */
5480 /* 0x23 mov dreg(op2); break;reg32 (ring 0 PM) */
5481 /* 0x24 mov reg32(op2); break;treg (ring 0 PM) */
5482 /* 0x26 mov treg(op2); break;reg32 (ring 0 PM) */
5483
5484 case 0x31:
5485 x86emuOp2_rdtsc(emu);
5486 break;
5487
5488 case 0x80:
5489 common_jmp_long(emu, ACCESS_FLAG(F_OF));
5490 break;
5491 case 0x81:
5492 common_jmp_long(emu, !ACCESS_FLAG(F_OF));
5493 break;
5494 case 0x82:
5495 common_jmp_long(emu, ACCESS_FLAG(F_CF));
5496 break;
5497 case 0x83:
5498 common_jmp_long(emu, !ACCESS_FLAG(F_CF));
5499 break;
5500 case 0x84:
5501 common_jmp_long(emu, ACCESS_FLAG(F_ZF));
5502 break;
5503 case 0x85:
5504 common_jmp_long(emu, !ACCESS_FLAG(F_ZF));
5505 break;
5506 case 0x86:
5507 common_jmp_long(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
5508 break;
5509 case 0x87:
5510 common_jmp_long(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)));
5511 break;
5512 case 0x88:
5513 common_jmp_long(emu, ACCESS_FLAG(F_SF));
5514 break;
5515 case 0x89:
5516 common_jmp_long(emu, !ACCESS_FLAG(F_SF));
5517 break;
5518 case 0x8a:
5519 common_jmp_long(emu, ACCESS_FLAG(F_PF));
5520 break;
5521 case 0x8b:
5522 common_jmp_long(emu, !ACCESS_FLAG(F_PF));
5523 break;
5524 case 0x8c:
5525 common_jmp_long(emu, xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)));
5526 break;
5527 case 0x8d:
5528 common_jmp_long(emu, !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF))));
5529 break;
5530 case 0x8e:
5531 common_jmp_long(emu,
5532 (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || ACCESS_FLAG(F_ZF)));
5533 break;
5534 case 0x8f:
5535 common_jmp_long(emu,
5536 !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || ACCESS_FLAG(F_ZF)));
5537 break;
5538
5539 case 0x90:
5540 common_set_byte(emu, ACCESS_FLAG(F_OF));
5541 break;
5542 case 0x91:
5543 common_set_byte(emu, !ACCESS_FLAG(F_OF));
5544 break;
5545 case 0x92:
5546 common_set_byte(emu, ACCESS_FLAG(F_CF));
5547 break;
5548 case 0x93:
5549 common_set_byte(emu, !ACCESS_FLAG(F_CF));
5550 break;
5551 case 0x94:
5552 common_set_byte(emu, ACCESS_FLAG(F_ZF));
5553 break;
5554 case 0x95:
5555 common_set_byte(emu, !ACCESS_FLAG(F_ZF));
5556 break;
5557 case 0x96:
5558 common_set_byte(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
5559 break;
5560 case 0x97:
5561 common_set_byte(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)));
5562 break;
5563 case 0x98:
5564 common_set_byte(emu, ACCESS_FLAG(F_SF));
5565 break;
5566 case 0x99:
5567 common_set_byte(emu, !ACCESS_FLAG(F_SF));
5568 break;
5569 case 0x9a:
5570 common_set_byte(emu, ACCESS_FLAG(F_PF));
5571 break;
5572 case 0x9b:
5573 common_set_byte(emu, !ACCESS_FLAG(F_PF));
5574 break;
5575 case 0x9c:
5576 common_set_byte(emu, xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)));
5577 break;
5578 case 0x9d:
5579 common_set_byte(emu, xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)));
5580 break;
5581 case 0x9e:
5582 common_set_byte(emu,
5583 (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
5584 ACCESS_FLAG(F_ZF)));
5585 break;
5586 case 0x9f:
5587 common_set_byte(emu,
5588 !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
5589 ACCESS_FLAG(F_ZF)));
5590 break;
5591
5592 case 0xa0:
5593 x86emuOp2_push_FS(emu);
5594 break;
5595 case 0xa1:
5596 x86emuOp2_pop_FS(emu);
5597 break;
5598 case 0xa2:
5599 x86emuOp2_cpuid(emu);
5600 break;
5601 case 0xa3:
5602 x86emuOp2_bt_R(emu);
5603 break;
5604 case 0xa4:
5605 x86emuOp2_shld_IMM(emu);
5606 break;
5607 case 0xa5:
5608 x86emuOp2_shld_CL(emu);
5609 break;
5610 case 0xa8:
5611 x86emuOp2_push_GS(emu);
5612 break;
5613 case 0xa9:
5614 x86emuOp2_pop_GS(emu);
5615 break;
5616 case 0xab:
5617 x86emuOp2_bts_R(emu);
5618 break;
5619 case 0xac:
5620 x86emuOp2_shrd_IMM(emu);
5621 break;
5622 case 0xad:
5623 x86emuOp2_shrd_CL(emu);
5624 break;
5625 case 0xaf:
5626 x86emuOp2_imul_R_RM(emu);
5627 break;
5628
5629 /* 0xb0 TODO: cmpxchg */
5630 /* 0xb1 TODO: cmpxchg */
5631 case 0xb2:
5632 x86emuOp2_lss_R_IMM(emu);
5633 break;
5634 case 0xb3:
5635 x86emuOp2_btr_R(emu);
5636 break;
5637 case 0xb4:
5638 x86emuOp2_lfs_R_IMM(emu);
5639 break;
5640 case 0xb5:
5641 x86emuOp2_lgs_R_IMM(emu);
5642 break;
5643 case 0xb6:
5644 x86emuOp2_movzx_byte_R_RM(emu);
5645 break;
5646 case 0xb7:
5647 x86emuOp2_movzx_word_R_RM(emu);
5648 break;
5649 case 0xba:
5650 x86emuOp2_btX_I(emu);
5651 break;
5652 case 0xbb:
5653 x86emuOp2_btc_R(emu);
5654 break;
5655 case 0xbc:
5656 x86emuOp2_bsf(emu);
5657 break;
5658 case 0xbd:
5659 x86emuOp2_bsr(emu);
5660 break;
5661 case 0xbe:
5662 x86emuOp2_movsx_byte_R_RM(emu);
5663 break;
5664 case 0xbf:
5665 x86emuOp2_movsx_word_R_RM(emu);
5666 break;
5667
5668 /* 0xc0 TODO: xadd */
5669 /* 0xc1 TODO: xadd */
5670 /* 0xc8 TODO: bswap */
5671 /* 0xc9 TODO: bswap */
5672 /* 0xca TODO: bswap */
5673 /* 0xcb TODO: bswap */
5674 /* 0xcc TODO: bswap */
5675 /* 0xcd TODO: bswap */
5676 /* 0xce TODO: bswap */
5677 /* 0xcf TODO: bswap */
5678
5679 default:
5680 X86EMU_halt_sys(emu);
5681 break;
5682 }
5683 }
5684
5685 /*
5686 * Carry Chain Calculation
5687 *
5688 * This represents a somewhat expensive calculation which is
5689 * apparently required to emulate the setting of the OF and AF flag.
5690 * The latter is not so important, but the former is. The overflow
5691 * flag is the XOR of the top two bits of the carry chain for an
5692 * addition (similar for subtraction). Since we do not want to
5693 * simulate the addition in a bitwise manner, we try to calculate the
5694 * carry chain given the two operands and the result.
5695 *
5696 * So, given the following table, which represents the addition of two
5697 * bits, we can derive a formula for the carry chain.
5698 *
5699 * a b cin r cout
5700 * 0 0 0 0 0
5701 * 0 0 1 1 0
5702 * 0 1 0 1 0
5703 * 0 1 1 0 1
5704 * 1 0 0 1 0
5705 * 1 0 1 0 1
5706 * 1 1 0 0 1
5707 * 1 1 1 1 1
5708 *
5709 * Construction of table for cout:
5710 *
5711 * ab
5712 * r \ 00 01 11 10
5713 * |------------------
5714 * 0 | 0 1 1 1
5715 * 1 | 0 0 1 0
5716 *
5717 * By inspection, one gets: cc = ab + r'(a + b)
5718 *
5719 * That represents alot of operations, but NO CHOICE....
5720 *
5721 * Borrow Chain Calculation.
5722 *
5723 * The following table represents the subtraction of two bits, from
5724 * which we can derive a formula for the borrow chain.
5725 *
5726 * a b bin r bout
5727 * 0 0 0 0 0
5728 * 0 0 1 1 1
5729 * 0 1 0 1 1
5730 * 0 1 1 0 1
5731 * 1 0 0 1 0
5732 * 1 0 1 0 0
5733 * 1 1 0 0 0
5734 * 1 1 1 1 1
5735 *
5736 * Construction of table for cout:
5737 *
5738 * ab
5739 * r \ 00 01 11 10
5740 * |------------------
5741 * 0 | 0 1 0 0
5742 * 1 | 1 1 1 0
5743 *
5744 * By inspection, one gets: bc = a'b + r(a' + b)
5745 *
5746 ****************************************************************************/
5747
5748 /*------------------------- Global Variables ------------------------------*/
5749
5750 static uint32_t x86emu_parity_tab[8] =
5751 {
5752 0x96696996,
5753 0x69969669,
5754 0x69969669,
5755 0x96696996,
5756 0x69969669,
5757 0x96696996,
5758 0x96696996,
5759 0x69969669,
5760 };
5761 #define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
5762 #define XOR2(x) (((x) ^ ((x)>>1)) & 0x1)
5763
5764 /****************************************************************************
5765 REMARKS:
5766 Implements the AAA instruction and side effects.
5767 ****************************************************************************/
5768 static uint16_t
5769 aaa_word(struct X86EMU *emu, uint16_t d)
5770 {
5771 uint16_t res;
5772 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
5773 d += 0x6;
5774 d += 0x100;
5775 SET_FLAG(F_AF);
5776 SET_FLAG(F_CF);
5777 } else {
5778 CLEAR_FLAG(F_CF);
5779 CLEAR_FLAG(F_AF);
5780 }
5781 res = (uint16_t) (d & 0xFF0F);
5782 CLEAR_FLAG(F_SF);
5783 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
5784 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
5785 return res;
5786 }
5787 /****************************************************************************
5788 REMARKS:
5789 Implements the AAA instruction and side effects.
5790 ****************************************************************************/
5791 static uint16_t
5792 aas_word(struct X86EMU *emu, uint16_t d)
5793 {
5794 uint16_t res;
5795 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
5796 d -= 0x6;
5797 d -= 0x100;
5798 SET_FLAG(F_AF);
5799 SET_FLAG(F_CF);
5800 } else {
5801 CLEAR_FLAG(F_CF);
5802 CLEAR_FLAG(F_AF);
5803 }
5804 res = (uint16_t) (d & 0xFF0F);
5805 CLEAR_FLAG(F_SF);
5806 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
5807 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
5808 return res;
5809 }
5810 /****************************************************************************
5811 REMARKS:
5812 Implements the AAD instruction and side effects.
5813 ****************************************************************************/
5814 static uint16_t
5815 aad_word(struct X86EMU *emu, uint16_t d)
5816 {
5817 uint16_t l;
5818 uint8_t hb, lb;
5819
5820 hb = (uint8_t) ((d >> 8) & 0xff);
5821 lb = (uint8_t) ((d & 0xff));
5822 l = (uint16_t) ((lb + 10 * hb) & 0xFF);
5823
5824 CLEAR_FLAG(F_CF);
5825 CLEAR_FLAG(F_AF);
5826 CLEAR_FLAG(F_OF);
5827 CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
5828 CONDITIONAL_SET_FLAG(l == 0, F_ZF);
5829 CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
5830 return l;
5831 }
5832 /****************************************************************************
5833 REMARKS:
5834 Implements the AAM instruction and side effects.
5835 ****************************************************************************/
5836 static uint16_t
5837 aam_word(struct X86EMU *emu, uint8_t d)
5838 {
5839 uint16_t h, l;
5840
5841 h = (uint16_t) (d / 10);
5842 l = (uint16_t) (d % 10);
5843 l |= (uint16_t) (h << 8);
5844
5845 CLEAR_FLAG(F_CF);
5846 CLEAR_FLAG(F_AF);
5847 CLEAR_FLAG(F_OF);
5848 CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
5849 CONDITIONAL_SET_FLAG(l == 0, F_ZF);
5850 CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
5851 return l;
5852 }
5853 /****************************************************************************
5854 REMARKS:
5855 Implements the ADC instruction and side effects.
5856 ****************************************************************************/
5857 static uint8_t
5858 adc_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
5859 {
5860 uint32_t res; /* all operands in native machine order */
5861 uint32_t cc;
5862
5863 if (ACCESS_FLAG(F_CF))
5864 res = 1 + d + s;
5865 else
5866 res = d + s;
5867
5868 CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
5869 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
5870 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
5871 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
5872
5873 /* calculate the carry chain SEE NOTE AT TOP. */
5874 cc = (s & d) | ((~res) & (s | d));
5875 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
5876 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
5877 return (uint8_t) res;
5878 }
5879 /****************************************************************************
5880 REMARKS:
5881 Implements the ADC instruction and side effects.
5882 ****************************************************************************/
5883 static uint16_t
5884 adc_word(struct X86EMU *emu, uint16_t d, uint16_t s)
5885 {
5886 uint32_t res; /* all operands in native machine order */
5887 uint32_t cc;
5888
5889 if (ACCESS_FLAG(F_CF))
5890 res = 1 + d + s;
5891 else
5892 res = d + s;
5893
5894 CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
5895 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
5896 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
5897 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
5898
5899 /* calculate the carry chain SEE NOTE AT TOP. */
5900 cc = (s & d) | ((~res) & (s | d));
5901 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
5902 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
5903 return (uint16_t) res;
5904 }
5905 /****************************************************************************
5906 REMARKS:
5907 Implements the ADC instruction and side effects.
5908 ****************************************************************************/
5909 static uint32_t
5910 adc_long(struct X86EMU *emu, uint32_t d, uint32_t s)
5911 {
5912 uint32_t lo; /* all operands in native machine order */
5913 uint32_t hi;
5914 uint32_t res;
5915 uint32_t cc;
5916
5917 if (ACCESS_FLAG(F_CF)) {
5918 lo = 1 + (d & 0xFFFF) + (s & 0xFFFF);
5919 res = 1 + d + s;
5920 } else {
5921 lo = (d & 0xFFFF) + (s & 0xFFFF);
5922 res = d + s;
5923 }
5924 hi = (lo >> 16) + (d >> 16) + (s >> 16);
5925
5926 CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
5927 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
5928 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
5929 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
5930
5931 /* calculate the carry chain SEE NOTE AT TOP. */
5932 cc = (s & d) | ((~res) & (s | d));
5933 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
5934 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
5935 return res;
5936 }
5937 /****************************************************************************
5938 REMARKS:
5939 Implements the ADD instruction and side effects.
5940 ****************************************************************************/
5941 static uint8_t
5942 add_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
5943 {
5944 uint32_t res; /* all operands in native machine order */
5945 uint32_t cc;
5946
5947 res = d + s;
5948 CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
5949 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
5950 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
5951 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
5952
5953 /* calculate the carry chain SEE NOTE AT TOP. */
5954 cc = (s & d) | ((~res) & (s | d));
5955 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
5956 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
5957 return (uint8_t) res;
5958 }
5959 /****************************************************************************
5960 REMARKS:
5961 Implements the ADD instruction and side effects.
5962 ****************************************************************************/
5963 static uint16_t
5964 add_word(struct X86EMU *emu, uint16_t d, uint16_t s)
5965 {
5966 uint32_t res; /* all operands in native machine order */
5967 uint32_t cc;
5968
5969 res = d + s;
5970 CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
5971 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
5972 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
5973 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
5974
5975 /* calculate the carry chain SEE NOTE AT TOP. */
5976 cc = (s & d) | ((~res) & (s | d));
5977 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
5978 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
5979 return (uint16_t) res;
5980 }
5981 /****************************************************************************
5982 REMARKS:
5983 Implements the ADD instruction and side effects.
5984 ****************************************************************************/
5985 static uint32_t
5986 add_long(struct X86EMU *emu, uint32_t d, uint32_t s)
5987 {
5988 uint32_t lo; /* all operands in native machine order */
5989 uint32_t hi;
5990 uint32_t res;
5991 uint32_t cc;
5992
5993 lo = (d & 0xFFFF) + (s & 0xFFFF);
5994 res = d + s;
5995 hi = (lo >> 16) + (d >> 16) + (s >> 16);
5996
5997 CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
5998 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
5999 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6000 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6001
6002 /* calculate the carry chain SEE NOTE AT TOP. */
6003 cc = (s & d) | ((~res) & (s | d));
6004 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
6005 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6006
6007 return res;
6008 }
6009 /****************************************************************************
6010 REMARKS:
6011 Implements the AND instruction and side effects.
6012 ****************************************************************************/
6013 static uint8_t
6014 and_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
6015 {
6016 uint8_t res; /* all operands in native machine order */
6017
6018 res = d & s;
6019
6020 /* set the flags */
6021 CLEAR_FLAG(F_OF);
6022 CLEAR_FLAG(F_CF);
6023 CLEAR_FLAG(F_AF);
6024 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6025 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6026 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6027 return res;
6028 }
6029 /****************************************************************************
6030 REMARKS:
6031 Implements the AND instruction and side effects.
6032 ****************************************************************************/
6033 static uint16_t
6034 and_word(struct X86EMU *emu, uint16_t d, uint16_t s)
6035 {
6036 uint16_t res; /* all operands in native machine order */
6037
6038 res = d & s;
6039
6040 /* set the flags */
6041 CLEAR_FLAG(F_OF);
6042 CLEAR_FLAG(F_CF);
6043 CLEAR_FLAG(F_AF);
6044 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6045 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6046 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6047 return res;
6048 }
6049 /****************************************************************************
6050 REMARKS:
6051 Implements the AND instruction and side effects.
6052 ****************************************************************************/
6053 static uint32_t
6054 and_long(struct X86EMU *emu, uint32_t d, uint32_t s)
6055 {
6056 uint32_t res; /* all operands in native machine order */
6057
6058 res = d & s;
6059
6060 /* set the flags */
6061 CLEAR_FLAG(F_OF);
6062 CLEAR_FLAG(F_CF);
6063 CLEAR_FLAG(F_AF);
6064 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6065 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6066 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6067 return res;
6068 }
6069 /****************************************************************************
6070 REMARKS:
6071 Implements the CMP instruction and side effects.
6072 ****************************************************************************/
6073 static uint8_t
6074 cmp_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
6075 {
6076 uint32_t res; /* all operands in native machine order */
6077 uint32_t bc;
6078
6079 res = d - s;
6080 CLEAR_FLAG(F_CF);
6081 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6082 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6083 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6084
6085 /* calculate the borrow chain. See note at top */
6086 bc = (res & (~d | s)) | (~d & s);
6087 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
6088 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6089 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6090 return d;
6091 }
6092
6093 static void
6094 cmp_byte_no_return(struct X86EMU *emu, uint8_t d, uint8_t s)
6095 {
6096 cmp_byte(emu, d, s);
6097 }
6098 /****************************************************************************
6099 REMARKS:
6100 Implements the CMP instruction and side effects.
6101 ****************************************************************************/
6102 static uint16_t
6103 cmp_word(struct X86EMU *emu, uint16_t d, uint16_t s)
6104 {
6105 uint32_t res; /* all operands in native machine order */
6106 uint32_t bc;
6107
6108 res = d - s;
6109 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6110 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6111 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6112
6113 /* calculate the borrow chain. See note at top */
6114 bc = (res & (~d | s)) | (~d & s);
6115 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
6116 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6117 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6118 return d;
6119 }
6120
6121 static void
6122 cmp_word_no_return(struct X86EMU *emu, uint16_t d, uint16_t s)
6123 {
6124 cmp_word(emu, d, s);
6125 }
6126 /****************************************************************************
6127 REMARKS:
6128 Implements the CMP instruction and side effects.
6129 ****************************************************************************/
6130 static uint32_t
6131 cmp_long(struct X86EMU *emu, uint32_t d, uint32_t s)
6132 {
6133 uint32_t res; /* all operands in native machine order */
6134 uint32_t bc;
6135
6136 res = d - s;
6137 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6138 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6139 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6140
6141 /* calculate the borrow chain. See note at top */
6142 bc = (res & (~d | s)) | (~d & s);
6143 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
6144 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6145 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6146 return d;
6147 }
6148
6149 static void
6150 cmp_long_no_return(struct X86EMU *emu, uint32_t d, uint32_t s)
6151 {
6152 cmp_long(emu, d, s);
6153 }
6154 /****************************************************************************
6155 REMARKS:
6156 Implements the DAA instruction and side effects.
6157 ****************************************************************************/
6158 static uint8_t
6159 daa_byte(struct X86EMU *emu, uint8_t d)
6160 {
6161 uint32_t res = d;
6162 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
6163 res += 6;
6164 SET_FLAG(F_AF);
6165 }
6166 if (res > 0x9F || ACCESS_FLAG(F_CF)) {
6167 res += 0x60;
6168 SET_FLAG(F_CF);
6169 }
6170 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6171 CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF);
6172 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6173 return (uint8_t) res;
6174 }
6175 /****************************************************************************
6176 REMARKS:
6177 Implements the DAS instruction and side effects.
6178 ****************************************************************************/
6179 static uint8_t
6180 das_byte(struct X86EMU *emu, uint8_t d)
6181 {
6182 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
6183 d -= 6;
6184 SET_FLAG(F_AF);
6185 }
6186 if (d > 0x9F || ACCESS_FLAG(F_CF)) {
6187 d -= 0x60;
6188 SET_FLAG(F_CF);
6189 }
6190 CONDITIONAL_SET_FLAG(d & 0x80, F_SF);
6191 CONDITIONAL_SET_FLAG(d == 0, F_ZF);
6192 CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF);
6193 return d;
6194 }
6195 /****************************************************************************
6196 REMARKS:
6197 Implements the DEC instruction and side effects.
6198 ****************************************************************************/
6199 static uint8_t
6200 dec_byte(struct X86EMU *emu, uint8_t d)
6201 {
6202 uint32_t res; /* all operands in native machine order */
6203 uint32_t bc;
6204
6205 res = d - 1;
6206 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6207 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6208 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6209
6210 /* calculate the borrow chain. See note at top */
6211 /* based on sub_byte, uses s==1. */
6212 bc = (res & (~d | 1)) | (~d & 1);
6213 /* carry flag unchanged */
6214 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6215 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6216 return (uint8_t) res;
6217 }
6218 /****************************************************************************
6219 REMARKS:
6220 Implements the DEC instruction and side effects.
6221 ****************************************************************************/
6222 static uint16_t
6223 dec_word(struct X86EMU *emu, uint16_t d)
6224 {
6225 uint32_t res; /* all operands in native machine order */
6226 uint32_t bc;
6227
6228 res = d - 1;
6229 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6230 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6231 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6232
6233 /* calculate the borrow chain. See note at top */
6234 /* based on the sub_byte routine, with s==1 */
6235 bc = (res & (~d | 1)) | (~d & 1);
6236 /* carry flag unchanged */
6237 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6238 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6239 return (uint16_t) res;
6240 }
6241 /****************************************************************************
6242 REMARKS:
6243 Implements the DEC instruction and side effects.
6244 ****************************************************************************/
6245 static uint32_t
6246 dec_long(struct X86EMU *emu, uint32_t d)
6247 {
6248 uint32_t res; /* all operands in native machine order */
6249 uint32_t bc;
6250
6251 res = d - 1;
6252
6253 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6254 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6255 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6256
6257 /* calculate the borrow chain. See note at top */
6258 bc = (res & (~d | 1)) | (~d & 1);
6259 /* carry flag unchanged */
6260 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6261 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6262 return res;
6263 }
6264 /****************************************************************************
6265 REMARKS:
6266 Implements the INC instruction and side effects.
6267 ****************************************************************************/
6268 static uint8_t
6269 inc_byte(struct X86EMU *emu, uint8_t d)
6270 {
6271 uint32_t res; /* all operands in native machine order */
6272 uint32_t cc;
6273
6274 res = d + 1;
6275 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6276 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6277 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6278
6279 /* calculate the carry chain SEE NOTE AT TOP. */
6280 cc = ((1 & d) | (~res)) & (1 | d);
6281 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
6282 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6283 return (uint8_t) res;
6284 }
6285 /****************************************************************************
6286 REMARKS:
6287 Implements the INC instruction and side effects.
6288 ****************************************************************************/
6289 static uint16_t
6290 inc_word(struct X86EMU *emu, uint16_t d)
6291 {
6292 uint32_t res; /* all operands in native machine order */
6293 uint32_t cc;
6294
6295 res = d + 1;
6296 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6297 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6298 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6299
6300 /* calculate the carry chain SEE NOTE AT TOP. */
6301 cc = (1 & d) | ((~res) & (1 | d));
6302 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
6303 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6304 return (uint16_t) res;
6305 }
6306 /****************************************************************************
6307 REMARKS:
6308 Implements the INC instruction and side effects.
6309 ****************************************************************************/
6310 static uint32_t
6311 inc_long(struct X86EMU *emu, uint32_t d)
6312 {
6313 uint32_t res; /* all operands in native machine order */
6314 uint32_t cc;
6315
6316 res = d + 1;
6317 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6318 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6319 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6320
6321 /* calculate the carry chain SEE NOTE AT TOP. */
6322 cc = (1 & d) | ((~res) & (1 | d));
6323 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
6324 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6325 return res;
6326 }
6327 /****************************************************************************
6328 REMARKS:
6329 Implements the OR instruction and side effects.
6330 ****************************************************************************/
6331 static uint8_t
6332 or_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
6333 {
6334 uint8_t res; /* all operands in native machine order */
6335
6336 res = d | s;
6337 CLEAR_FLAG(F_OF);
6338 CLEAR_FLAG(F_CF);
6339 CLEAR_FLAG(F_AF);
6340 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6341 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6342 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6343 return res;
6344 }
6345 /****************************************************************************
6346 REMARKS:
6347 Implements the OR instruction and side effects.
6348 ****************************************************************************/
6349 static uint16_t
6350 or_word(struct X86EMU *emu, uint16_t d, uint16_t s)
6351 {
6352 uint16_t res; /* all operands in native machine order */
6353
6354 res = d | s;
6355 /* set the carry flag to be bit 8 */
6356 CLEAR_FLAG(F_OF);
6357 CLEAR_FLAG(F_CF);
6358 CLEAR_FLAG(F_AF);
6359 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6360 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6361 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6362 return res;
6363 }
6364 /****************************************************************************
6365 REMARKS:
6366 Implements the OR instruction and side effects.
6367 ****************************************************************************/
6368 static uint32_t
6369 or_long(struct X86EMU *emu, uint32_t d, uint32_t s)
6370 {
6371 uint32_t res; /* all operands in native machine order */
6372
6373 res = d | s;
6374
6375 /* set the carry flag to be bit 8 */
6376 CLEAR_FLAG(F_OF);
6377 CLEAR_FLAG(F_CF);
6378 CLEAR_FLAG(F_AF);
6379 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6380 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6381 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6382 return res;
6383 }
6384 /****************************************************************************
6385 REMARKS:
6386 Implements the OR instruction and side effects.
6387 ****************************************************************************/
6388 static uint8_t
6389 neg_byte(struct X86EMU *emu, uint8_t s)
6390 {
6391 uint8_t res;
6392 uint8_t bc;
6393
6394 CONDITIONAL_SET_FLAG(s != 0, F_CF);
6395 res = (uint8_t) - s;
6396 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6397 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6398 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6399 /* calculate the borrow chain --- modified such that d=0.
6400 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for
6401 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6402 * res&0xfff... == res. Similarly ~d&s == s. So the simplified
6403 * result is: */
6404 bc = res | s;
6405 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6406 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6407 return res;
6408 }
6409 /****************************************************************************
6410 REMARKS:
6411 Implements the OR instruction and side effects.
6412 ****************************************************************************/
6413 static uint16_t
6414 neg_word(struct X86EMU *emu, uint16_t s)
6415 {
6416 uint16_t res;
6417 uint16_t bc;
6418
6419 CONDITIONAL_SET_FLAG(s != 0, F_CF);
6420 res = (uint16_t) - s;
6421 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6422 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6423 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6424
6425 /* calculate the borrow chain --- modified such that d=0.
6426 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for
6427 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6428 * res&0xfff... == res. Similarly ~d&s == s. So the simplified
6429 * result is: */
6430 bc = res | s;
6431 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6432 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6433 return res;
6434 }
6435 /****************************************************************************
6436 REMARKS:
6437 Implements the OR instruction and side effects.
6438 ****************************************************************************/
6439 static uint32_t
6440 neg_long(struct X86EMU *emu, uint32_t s)
6441 {
6442 uint32_t res;
6443 uint32_t bc;
6444
6445 CONDITIONAL_SET_FLAG(s != 0, F_CF);
6446 res = (uint32_t) - s;
6447 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6448 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6449 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6450
6451 /* calculate the borrow chain --- modified such that d=0.
6452 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for
6453 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6454 * res&0xfff... == res. Similarly ~d&s == s. So the simplified
6455 * result is: */
6456 bc = res | s;
6457 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6458 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6459 return res;
6460 }
6461 /****************************************************************************
6462 REMARKS:
6463 Implements the RCL instruction and side effects.
6464 ****************************************************************************/
6465 static uint8_t
6466 rcl_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
6467 {
6468 unsigned int res, cnt, mask, cf;
6469
6470 /* s is the rotate distance. It varies from 0 - 8. */
6471 /* have
6472 *
6473 * CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
6474 *
6475 * want to rotate through the carry by "s" bits. We could loop, but
6476 * that's inefficient. So the width is 9, and we split into three
6477 * parts:
6478 *
6479 * The new carry flag (was B_n) the stuff in B_n-1 .. B_0 the stuff in
6480 * B_7 .. B_n+1
6481 *
6482 * The new rotate is done mod 9, and given this, for a rotation of n bits
6483 * (mod 9) the new carry flag is then located n bits from the MSB.
6484 * The low part is then shifted up cnt bits, and the high part is or'd
6485 * in. Using CAPS for new values, and lowercase for the original
6486 * values, this can be expressed as:
6487 *
6488 * IF n > 0 1) CF <- b_(8-n) 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0
6489 * 3) B_(n-1) <- cf 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */
6490 res = d;
6491 if ((cnt = s % 9) != 0) {
6492 /* extract the new CARRY FLAG. */
6493 /* CF <- b_(8-n) */
6494 cf = (d >> (8 - cnt)) & 0x1;
6495
6496 /* get the low stuff which rotated into the range B_7 .. B_cnt */
6497 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 */
6498 /* note that the right hand side done by the mask */
6499 res = (d << cnt) & 0xff;
6500
6501 /* now the high stuff which rotated around into the positions
6502 * B_cnt-2 .. B_0 */
6503 /* B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */
6504 /* shift it downward, 7-(n-2) = 9-n positions. and mask off
6505 * the result before or'ing in. */
6506 mask = (1 << (cnt - 1)) - 1;
6507 res |= (d >> (9 - cnt)) & mask;
6508
6509 /* if the carry flag was set, or it in. */
6510 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
6511 /* B_(n-1) <- cf */
6512 res |= 1 << (cnt - 1);
6513 }
6514 /* set the new carry flag, based on the variable "cf" */
6515 CONDITIONAL_SET_FLAG(cf, F_CF);
6516 /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and
6517 * the most significant bit. Blecck. */
6518 /* parenthesized this expression since it appears to be
6519 * causing OF to be misset */
6520 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
6521 F_OF);
6522
6523 }
6524 return (uint8_t) res;
6525 }
6526 /****************************************************************************
6527 REMARKS:
6528 Implements the RCL instruction and side effects.
6529 ****************************************************************************/
6530 static uint16_t
6531 rcl_word(struct X86EMU *emu, uint16_t d, uint8_t s)
6532 {
6533 unsigned int res, cnt, mask, cf;
6534
6535 res = d;
6536 if ((cnt = s % 17) != 0) {
6537 cf = (d >> (16 - cnt)) & 0x1;
6538 res = (d << cnt) & 0xffff;
6539 mask = (1 << (cnt - 1)) - 1;
6540 res |= (d >> (17 - cnt)) & mask;
6541 if (ACCESS_FLAG(F_CF)) {
6542 res |= 1 << (cnt - 1);
6543 }
6544 CONDITIONAL_SET_FLAG(cf, F_CF);
6545 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
6546 F_OF);
6547 }
6548 return (uint16_t) res;
6549 }
6550 /****************************************************************************
6551 REMARKS:
6552 Implements the RCL instruction and side effects.
6553 ****************************************************************************/
6554 static uint32_t
6555 rcl_long(struct X86EMU *emu, uint32_t d, uint8_t s)
6556 {
6557 uint32_t res, cnt, mask, cf;
6558
6559 res = d;
6560 if ((cnt = s % 33) != 0) {
6561 cf = (d >> (32 - cnt)) & 0x1;
6562 res = (d << cnt) & 0xffffffff;
6563 mask = (1 << (cnt - 1)) - 1;
6564 res |= (d >> (33 - cnt)) & mask;
6565 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
6566 res |= 1 << (cnt - 1);
6567 }
6568 CONDITIONAL_SET_FLAG(cf, F_CF);
6569 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
6570 F_OF);
6571 }
6572 return res;
6573 }
6574 /****************************************************************************
6575 REMARKS:
6576 Implements the RCR instruction and side effects.
6577 ****************************************************************************/
6578 static uint8_t
6579 rcr_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
6580 {
6581 uint32_t res, cnt;
6582 uint32_t mask, cf, ocf = 0;
6583
6584 /* rotate right through carry */
6585 /* s is the rotate distance. It varies from 0 - 8. d is the byte
6586 * object rotated.
6587 *
6588 * have
6589 *
6590 * CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
6591 *
6592 * The new rotate is done mod 9, and given this, for a rotation of n bits
6593 * (mod 9) the new carry flag is then located n bits from the LSB.
6594 * The low part is then shifted up cnt bits, and the high part is or'd
6595 * in. Using CAPS for new values, and lowercase for the original
6596 * values, this can be expressed as:
6597 *
6598 * IF n > 0 1) CF <- b_(n-1) 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
6599 * 3) B_(8-n) <- cf 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */
6600 res = d;
6601 if ((cnt = s % 9) != 0) {
6602 /* extract the new CARRY FLAG. */
6603 /* CF <- b_(n-1) */
6604 if (cnt == 1) {
6605 cf = d & 0x1;
6606 /* note hackery here. Access_flag(..) evaluates to
6607 * either 0 if flag not set non-zero if flag is set.
6608 * doing access_flag(..) != 0 casts that into either
6609 * 0..1 in any representation of the flags register
6610 * (i.e. packed bit array or unpacked.) */
6611 ocf = ACCESS_FLAG(F_CF) != 0;
6612 } else
6613 cf = (d >> (cnt - 1)) & 0x1;
6614
6615 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */
6616 /* note that the right hand side done by the mask This is
6617 * effectively done by shifting the object to the right. The
6618 * result must be masked, in case the object came in and was
6619 * treated as a negative number. Needed??? */
6620
6621 mask = (1 << (8 - cnt)) - 1;
6622 res = (d >> cnt) & mask;
6623
6624 /* now the high stuff which rotated around into the positions
6625 * B_cnt-2 .. B_0 */
6626 /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */
6627 /* shift it downward, 7-(n-2) = 9-n positions. and mask off
6628 * the result before or'ing in. */
6629 res |= (d << (9 - cnt));
6630
6631 /* if the carry flag was set, or it in. */
6632 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
6633 /* B_(8-n) <- cf */
6634 res |= 1 << (8 - cnt);
6635 }
6636 /* set the new carry flag, based on the variable "cf" */
6637 CONDITIONAL_SET_FLAG(cf, F_CF);
6638 /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and
6639 * the most significant bit. Blecck. */
6640 /* parenthesized... */
6641 if (cnt == 1) {
6642 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
6643 F_OF);
6644 }
6645 }
6646 return (uint8_t) res;
6647 }
6648 /****************************************************************************
6649 REMARKS:
6650 Implements the RCR instruction and side effects.
6651 ****************************************************************************/
6652 static uint16_t
6653 rcr_word(struct X86EMU *emu, uint16_t d, uint8_t s)
6654 {
6655 uint32_t res, cnt;
6656 uint32_t mask, cf, ocf = 0;
6657
6658 /* rotate right through carry */
6659 res = d;
6660 if ((cnt = s % 17) != 0) {
6661 if (cnt == 1) {
6662 cf = d & 0x1;
6663 ocf = ACCESS_FLAG(F_CF) != 0;
6664 } else
6665 cf = (d >> (cnt - 1)) & 0x1;
6666 mask = (1 << (16 - cnt)) - 1;
6667 res = (d >> cnt) & mask;
6668 res |= (d << (17 - cnt));
6669 if (ACCESS_FLAG(F_CF)) {
6670 res |= 1 << (16 - cnt);
6671 }
6672 CONDITIONAL_SET_FLAG(cf, F_CF);
6673 if (cnt == 1) {
6674 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
6675 F_OF);
6676 }
6677 }
6678 return (uint16_t) res;
6679 }
6680 /****************************************************************************
6681 REMARKS:
6682 Implements the RCR instruction and side effects.
6683 ****************************************************************************/
6684 static uint32_t
6685 rcr_long(struct X86EMU *emu, uint32_t d, uint8_t s)
6686 {
6687 uint32_t res, cnt;
6688 uint32_t mask, cf, ocf = 0;
6689
6690 /* rotate right through carry */
6691 res = d;
6692 if ((cnt = s % 33) != 0) {
6693 if (cnt == 1) {
6694 cf = d & 0x1;
6695 ocf = ACCESS_FLAG(F_CF) != 0;
6696 } else
6697 cf = (d >> (cnt - 1)) & 0x1;
6698 mask = (1 << (32 - cnt)) - 1;
6699 res = (d >> cnt) & mask;
6700 if (cnt != 1)
6701 res |= (d << (33 - cnt));
6702 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
6703 res |= 1 << (32 - cnt);
6704 }
6705 CONDITIONAL_SET_FLAG(cf, F_CF);
6706 if (cnt == 1) {
6707 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
6708 F_OF);
6709 }
6710 }
6711 return res;
6712 }
6713 /****************************************************************************
6714 REMARKS:
6715 Implements the ROL instruction and side effects.
6716 ****************************************************************************/
6717 static uint8_t
6718 rol_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
6719 {
6720 unsigned int res, cnt, mask;
6721
6722 /* rotate left */
6723 /* s is the rotate distance. It varies from 0 - 8. d is the byte
6724 * object rotated.
6725 *
6726 * have
6727 *
6728 * CF B_7 ... B_0
6729 *
6730 * The new rotate is done mod 8. Much simpler than the "rcl" or "rcr"
6731 * operations.
6732 *
6733 * IF n > 0 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) 2) B_(n-1) ..
6734 * B_(0) <- b_(7) .. b_(8-n) */
6735 res = d;
6736 if ((cnt = s % 8) != 0) {
6737 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */
6738 res = (d << cnt);
6739
6740 /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */
6741 mask = (1 << cnt) - 1;
6742 res |= (d >> (8 - cnt)) & mask;
6743
6744 /* set the new carry flag, Note that it is the low order bit
6745 * of the result!!! */
6746 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
6747 /* OVERFLOW is set *IFF* s==1, then it is the xor of CF and
6748 * the most significant bit. Blecck. */
6749 CONDITIONAL_SET_FLAG(s == 1 &&
6750 XOR2((res & 0x1) + ((res >> 6) & 0x2)),
6751 F_OF);
6752 } if (s != 0) {
6753 /* set the new carry flag, Note that it is the low order bit
6754 * of the result!!! */
6755 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
6756 }
6757 return (uint8_t) res;
6758 }
6759 /****************************************************************************
6760 REMARKS:
6761 Implements the ROL instruction and side effects.
6762 ****************************************************************************/
6763 static uint16_t
6764 rol_word(struct X86EMU *emu, uint16_t d, uint8_t s)
6765 {
6766 unsigned int res, cnt, mask;
6767
6768 res = d;
6769 if ((cnt = s % 16) != 0) {
6770 res = (d << cnt);
6771 mask = (1 << cnt) - 1;
6772 res |= (d >> (16 - cnt)) & mask;
6773 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
6774 CONDITIONAL_SET_FLAG(s == 1 &&
6775 XOR2((res & 0x1) + ((res >> 14) & 0x2)),
6776 F_OF);
6777 } if (s != 0) {
6778 /* set the new carry flag, Note that it is the low order bit
6779 * of the result!!! */
6780 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
6781 }
6782 return (uint16_t) res;
6783 }
6784 /****************************************************************************
6785 REMARKS:
6786 Implements the ROL instruction and side effects.
6787 ****************************************************************************/
6788 static uint32_t
6789 rol_long(struct X86EMU *emu, uint32_t d, uint8_t s)
6790 {
6791 uint32_t res, cnt, mask;
6792
6793 res = d;
6794 if ((cnt = s % 32) != 0) {
6795 res = (d << cnt);
6796 mask = (1 << cnt) - 1;
6797 res |= (d >> (32 - cnt)) & mask;
6798 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
6799 CONDITIONAL_SET_FLAG(s == 1 &&
6800 XOR2((res & 0x1) + ((res >> 30) & 0x2)),
6801 F_OF);
6802 } if (s != 0) {
6803 /* set the new carry flag, Note that it is the low order bit
6804 * of the result!!! */
6805 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
6806 }
6807 return res;
6808 }
6809 /****************************************************************************
6810 REMARKS:
6811 Implements the ROR instruction and side effects.
6812 ****************************************************************************/
6813 static uint8_t
6814 ror_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
6815 {
6816 unsigned int res, cnt, mask;
6817
6818 /* rotate right */
6819 /* s is the rotate distance. It varies from 0 - 8. d is the byte
6820 * object rotated.
6821 *
6822 * have
6823 *
6824 * B_7 ... B_0
6825 *
6826 * The rotate is done mod 8.
6827 *
6828 * IF n > 0 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) 2) B_(7) ..
6829 * B_(8-n) <- b_(n-1) .. b_(0) */
6830 res = d;
6831 if ((cnt = s % 8) != 0) { /* not a typo, do nada if cnt==0 */
6832 /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */
6833 res = (d << (8 - cnt));
6834
6835 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */
6836 mask = (1 << (8 - cnt)) - 1;
6837 res |= (d >> (cnt)) & mask;
6838
6839 /* set the new carry flag, Note that it is the low order bit
6840 * of the result!!! */
6841 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
6842 /* OVERFLOW is set *IFF* s==1, then it is the xor of the two
6843 * most significant bits. Blecck. */
6844 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
6845 } else if (s != 0) {
6846 /* set the new carry flag, Note that it is the low order bit
6847 * of the result!!! */
6848 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
6849 }
6850 return (uint8_t) res;
6851 }
6852 /****************************************************************************
6853 REMARKS:
6854 Implements the ROR instruction and side effects.
6855 ****************************************************************************/
6856 static uint16_t
6857 ror_word(struct X86EMU *emu, uint16_t d, uint8_t s)
6858 {
6859 unsigned int res, cnt, mask;
6860
6861 res = d;
6862 if ((cnt = s % 16) != 0) {
6863 res = (d << (16 - cnt));
6864 mask = (1 << (16 - cnt)) - 1;
6865 res |= (d >> (cnt)) & mask;
6866 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
6867 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
6868 } else if (s != 0) {
6869 /* set the new carry flag, Note that it is the low order bit
6870 * of the result!!! */
6871 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
6872 }
6873 return (uint16_t) res;
6874 }
6875 /****************************************************************************
6876 REMARKS:
6877 Implements the ROR instruction and side effects.
6878 ****************************************************************************/
6879 static uint32_t
6880 ror_long(struct X86EMU *emu, uint32_t d, uint8_t s)
6881 {
6882 uint32_t res, cnt, mask;
6883
6884 res = d;
6885 if ((cnt = s % 32) != 0) {
6886 res = (d << (32 - cnt));
6887 mask = (1 << (32 - cnt)) - 1;
6888 res |= (d >> (cnt)) & mask;
6889 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
6890 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
6891 } else if (s != 0) {
6892 /* set the new carry flag, Note that it is the low order bit
6893 * of the result!!! */
6894 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
6895 }
6896 return res;
6897 }
6898 /****************************************************************************
6899 REMARKS:
6900 Implements the SHL instruction and side effects.
6901 ****************************************************************************/
6902 static uint8_t
6903 shl_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
6904 {
6905 unsigned int cnt, res, cf;
6906
6907 if (s < 8) {
6908 cnt = s % 8;
6909
6910 /* last bit shifted out goes into carry flag */
6911 if (cnt > 0) {
6912 res = d << cnt;
6913 cf = d & (1 << (8 - cnt));
6914 CONDITIONAL_SET_FLAG(cf, F_CF);
6915 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6916 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6917 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6918 } else {
6919 res = (uint8_t) d;
6920 }
6921
6922 if (cnt == 1) {
6923 /* Needs simplification. */
6924 CONDITIONAL_SET_FLAG(
6925 (((res & 0x80) == 0x80) ^
6926 (ACCESS_FLAG(F_CF) != 0)),
6927 /* was (emu->x86.R_FLG&F_CF)==F_CF)), */
6928 F_OF);
6929 } else {
6930 CLEAR_FLAG(F_OF);
6931 }
6932 } else {
6933 res = 0;
6934 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80, F_CF);
6935 CLEAR_FLAG(F_OF);
6936 CLEAR_FLAG(F_SF);
6937 SET_FLAG(F_PF);
6938 SET_FLAG(F_ZF);
6939 }
6940 return (uint8_t) res;
6941 }
6942 /****************************************************************************
6943 REMARKS:
6944 Implements the SHL instruction and side effects.
6945 ****************************************************************************/
6946 static uint16_t
6947 shl_word(struct X86EMU *emu, uint16_t d, uint8_t s)
6948 {
6949 unsigned int cnt, res, cf;
6950
6951 if (s < 16) {
6952 cnt = s % 16;
6953 if (cnt > 0) {
6954 res = d << cnt;
6955 cf = d & (1 << (16 - cnt));
6956 CONDITIONAL_SET_FLAG(cf, F_CF);
6957 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6958 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6959 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6960 } else {
6961 res = (uint16_t) d;
6962 }
6963
6964 if (cnt == 1) {
6965 CONDITIONAL_SET_FLAG(
6966 (((res & 0x8000) == 0x8000) ^
6967 (ACCESS_FLAG(F_CF) != 0)),
6968 F_OF);
6969 } else {
6970 CLEAR_FLAG(F_OF);
6971 }
6972 } else {
6973 res = 0;
6974 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF);
6975 CLEAR_FLAG(F_OF);
6976 CLEAR_FLAG(F_SF);
6977 SET_FLAG(F_PF);
6978 SET_FLAG(F_ZF);
6979 }
6980 return (uint16_t) res;
6981 }
6982 /****************************************************************************
6983 REMARKS:
6984 Implements the SHL instruction and side effects.
6985 ****************************************************************************/
6986 static uint32_t
6987 shl_long(struct X86EMU *emu, uint32_t d, uint8_t s)
6988 {
6989 unsigned int cnt, res, cf;
6990
6991 if (s < 32) {
6992 cnt = s % 32;
6993 if (cnt > 0) {
6994 res = d << cnt;
6995 cf = d & (1 << (32 - cnt));
6996 CONDITIONAL_SET_FLAG(cf, F_CF);
6997 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6998 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6999 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7000 } else {
7001 res = d;
7002 }
7003 if (cnt == 1) {
7004 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
7005 (ACCESS_FLAG(F_CF) != 0)), F_OF);
7006 } else {
7007 CLEAR_FLAG(F_OF);
7008 }
7009 } else {
7010 res = 0;
7011 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF);
7012 CLEAR_FLAG(F_OF);
7013 CLEAR_FLAG(F_SF);
7014 SET_FLAG(F_PF);
7015 SET_FLAG(F_ZF);
7016 }
7017 return res;
7018 }
7019 /****************************************************************************
7020 REMARKS:
7021 Implements the SHR instruction and side effects.
7022 ****************************************************************************/
7023 static uint8_t
7024 shr_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
7025 {
7026 unsigned int cnt, res, cf;
7027
7028 if (s < 8) {
7029 cnt = s % 8;
7030 if (cnt > 0) {
7031 cf = d & (1 << (cnt - 1));
7032 res = d >> cnt;
7033 CONDITIONAL_SET_FLAG(cf, F_CF);
7034 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7035 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7036 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7037 } else {
7038 res = (uint8_t) d;
7039 }
7040
7041 if (cnt == 1) {
7042 CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
7043 } else {
7044 CLEAR_FLAG(F_OF);
7045 }
7046 } else {
7047 res = 0;
7048 CONDITIONAL_SET_FLAG((d >> (s - 1)) & 0x1, F_CF);
7049 CLEAR_FLAG(F_OF);
7050 CLEAR_FLAG(F_SF);
7051 SET_FLAG(F_PF);
7052 SET_FLAG(F_ZF);
7053 }
7054 return (uint8_t) res;
7055 }
7056 /****************************************************************************
7057 REMARKS:
7058 Implements the SHR instruction and side effects.
7059 ****************************************************************************/
7060 static uint16_t
7061 shr_word(struct X86EMU *emu, uint16_t d, uint8_t s)
7062 {
7063 unsigned int cnt, res, cf;
7064
7065 if (s < 16) {
7066 cnt = s % 16;
7067 if (cnt > 0) {
7068 cf = d & (1 << (cnt - 1));
7069 res = d >> cnt;
7070 CONDITIONAL_SET_FLAG(cf, F_CF);
7071 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7072 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7073 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7074 } else {
7075 res = d;
7076 }
7077
7078 if (cnt == 1) {
7079 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
7080 } else {
7081 CLEAR_FLAG(F_OF);
7082 }
7083 } else {
7084 res = 0;
7085 CLEAR_FLAG(F_CF);
7086 CLEAR_FLAG(F_OF);
7087 SET_FLAG(F_ZF);
7088 CLEAR_FLAG(F_SF);
7089 CLEAR_FLAG(F_PF);
7090 }
7091 return (uint16_t) res;
7092 }
7093 /****************************************************************************
7094 REMARKS:
7095 Implements the SHR instruction and side effects.
7096 ****************************************************************************/
7097 static uint32_t
7098 shr_long(struct X86EMU *emu, uint32_t d, uint8_t s)
7099 {
7100 unsigned int cnt, res, cf;
7101
7102 if (s < 32) {
7103 cnt = s % 32;
7104 if (cnt > 0) {
7105 cf = d & (1 << (cnt - 1));
7106 res = d >> cnt;
7107 CONDITIONAL_SET_FLAG(cf, F_CF);
7108 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7109 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7110 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7111 } else {
7112 res = d;
7113 }
7114 if (cnt == 1) {
7115 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
7116 } else {
7117 CLEAR_FLAG(F_OF);
7118 }
7119 } else {
7120 res = 0;
7121 CLEAR_FLAG(F_CF);
7122 CLEAR_FLAG(F_OF);
7123 SET_FLAG(F_ZF);
7124 CLEAR_FLAG(F_SF);
7125 CLEAR_FLAG(F_PF);
7126 }
7127 return res;
7128 }
7129 /****************************************************************************
7130 REMARKS:
7131 Implements the SAR instruction and side effects.
7132 ****************************************************************************/
7133 static uint8_t
7134 sar_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
7135 {
7136 unsigned int cnt, res, cf, mask, sf;
7137
7138 res = d;
7139 sf = d & 0x80;
7140 cnt = s % 8;
7141 if (cnt > 0 && cnt < 8) {
7142 mask = (1 << (8 - cnt)) - 1;
7143 cf = d & (1 << (cnt - 1));
7144 res = (d >> cnt) & mask;
7145 CONDITIONAL_SET_FLAG(cf, F_CF);
7146 if (sf) {
7147 res |= ~mask;
7148 }
7149 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7150 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7151 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7152 } else if (cnt >= 8) {
7153 if (sf) {
7154 res = 0xff;
7155 SET_FLAG(F_CF);
7156 CLEAR_FLAG(F_ZF);
7157 SET_FLAG(F_SF);
7158 SET_FLAG(F_PF);
7159 } else {
7160 res = 0;
7161 CLEAR_FLAG(F_CF);
7162 SET_FLAG(F_ZF);
7163 CLEAR_FLAG(F_SF);
7164 CLEAR_FLAG(F_PF);
7165 }
7166 }
7167 return (uint8_t) res;
7168 }
7169 /****************************************************************************
7170 REMARKS:
7171 Implements the SAR instruction and side effects.
7172 ****************************************************************************/
7173 static uint16_t
7174 sar_word(struct X86EMU *emu, uint16_t d, uint8_t s)
7175 {
7176 unsigned int cnt, res, cf, mask, sf;
7177
7178 sf = d & 0x8000;
7179 cnt = s % 16;
7180 res = d;
7181 if (cnt > 0 && cnt < 16) {
7182 mask = (1 << (16 - cnt)) - 1;
7183 cf = d & (1 << (cnt - 1));
7184 res = (d >> cnt) & mask;
7185 CONDITIONAL_SET_FLAG(cf, F_CF);
7186 if (sf) {
7187 res |= ~mask;
7188 }
7189 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7190 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7191 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7192 } else if (cnt >= 16) {
7193 if (sf) {
7194 res = 0xffff;
7195 SET_FLAG(F_CF);
7196 CLEAR_FLAG(F_ZF);
7197 SET_FLAG(F_SF);
7198 SET_FLAG(F_PF);
7199 } else {
7200 res = 0;
7201 CLEAR_FLAG(F_CF);
7202 SET_FLAG(F_ZF);
7203 CLEAR_FLAG(F_SF);
7204 CLEAR_FLAG(F_PF);
7205 }
7206 }
7207 return (uint16_t) res;
7208 }
7209 /****************************************************************************
7210 REMARKS:
7211 Implements the SAR instruction and side effects.
7212 ****************************************************************************/
7213 static uint32_t
7214 sar_long(struct X86EMU *emu, uint32_t d, uint8_t s)
7215 {
7216 uint32_t cnt, res, cf, mask, sf;
7217
7218 sf = d & 0x80000000;
7219 cnt = s % 32;
7220 res = d;
7221 if (cnt > 0 && cnt < 32) {
7222 mask = (1 << (32 - cnt)) - 1;
7223 cf = d & (1 << (cnt - 1));
7224 res = (d >> cnt) & mask;
7225 CONDITIONAL_SET_FLAG(cf, F_CF);
7226 if (sf) {
7227 res |= ~mask;
7228 }
7229 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7230 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7231 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7232 } else if (cnt >= 32) {
7233 if (sf) {
7234 res = 0xffffffff;
7235 SET_FLAG(F_CF);
7236 CLEAR_FLAG(F_ZF);
7237 SET_FLAG(F_SF);
7238 SET_FLAG(F_PF);
7239 } else {
7240 res = 0;
7241 CLEAR_FLAG(F_CF);
7242 SET_FLAG(F_ZF);
7243 CLEAR_FLAG(F_SF);
7244 CLEAR_FLAG(F_PF);
7245 }
7246 }
7247 return res;
7248 }
7249 /****************************************************************************
7250 REMARKS:
7251 Implements the SHLD instruction and side effects.
7252 ****************************************************************************/
7253 static uint16_t
7254 shld_word(struct X86EMU *emu, uint16_t d, uint16_t fill, uint8_t s)
7255 {
7256 unsigned int cnt, res, cf;
7257
7258 if (s < 16) {
7259 cnt = s % 16;
7260 if (cnt > 0) {
7261 res = (d << cnt) | (fill >> (16 - cnt));
7262 cf = d & (1 << (16 - cnt));
7263 CONDITIONAL_SET_FLAG(cf, F_CF);
7264 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7265 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7266 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7267 } else {
7268 res = d;
7269 }
7270 if (cnt == 1) {
7271 CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
7272 (ACCESS_FLAG(F_CF) != 0)), F_OF);
7273 } else {
7274 CLEAR_FLAG(F_OF);
7275 }
7276 } else {
7277 res = 0;
7278 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF);
7279 CLEAR_FLAG(F_OF);
7280 CLEAR_FLAG(F_SF);
7281 SET_FLAG(F_PF);
7282 SET_FLAG(F_ZF);
7283 }
7284 return (uint16_t) res;
7285 }
7286 /****************************************************************************
7287 REMARKS:
7288 Implements the SHLD instruction and side effects.
7289 ****************************************************************************/
7290 static uint32_t
7291 shld_long(struct X86EMU *emu, uint32_t d, uint32_t fill, uint8_t s)
7292 {
7293 unsigned int cnt, res, cf;
7294
7295 if (s < 32) {
7296 cnt = s % 32;
7297 if (cnt > 0) {
7298 res = (d << cnt) | (fill >> (32 - cnt));
7299 cf = d & (1 << (32 - cnt));
7300 CONDITIONAL_SET_FLAG(cf, F_CF);
7301 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7302 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7303 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7304 } else {
7305 res = d;
7306 }
7307 if (cnt == 1) {
7308 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
7309 (ACCESS_FLAG(F_CF) != 0)), F_OF);
7310 } else {
7311 CLEAR_FLAG(F_OF);
7312 }
7313 } else {
7314 res = 0;
7315 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF);
7316 CLEAR_FLAG(F_OF);
7317 CLEAR_FLAG(F_SF);
7318 SET_FLAG(F_PF);
7319 SET_FLAG(F_ZF);
7320 }
7321 return res;
7322 }
7323 /****************************************************************************
7324 REMARKS:
7325 Implements the SHRD instruction and side effects.
7326 ****************************************************************************/
7327 static uint16_t
7328 shrd_word(struct X86EMU *emu, uint16_t d, uint16_t fill, uint8_t s)
7329 {
7330 unsigned int cnt, res, cf;
7331
7332 if (s < 16) {
7333 cnt = s % 16;
7334 if (cnt > 0) {
7335 cf = d & (1 << (cnt - 1));
7336 res = (d >> cnt) | (fill << (16 - cnt));
7337 CONDITIONAL_SET_FLAG(cf, F_CF);
7338 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7339 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7340 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7341 } else {
7342 res = d;
7343 }
7344
7345 if (cnt == 1) {
7346 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
7347 } else {
7348 CLEAR_FLAG(F_OF);
7349 }
7350 } else {
7351 res = 0;
7352 CLEAR_FLAG(F_CF);
7353 CLEAR_FLAG(F_OF);
7354 SET_FLAG(F_ZF);
7355 CLEAR_FLAG(F_SF);
7356 CLEAR_FLAG(F_PF);
7357 }
7358 return (uint16_t) res;
7359 }
7360 /****************************************************************************
7361 REMARKS:
7362 Implements the SHRD instruction and side effects.
7363 ****************************************************************************/
7364 static uint32_t
7365 shrd_long(struct X86EMU *emu, uint32_t d, uint32_t fill, uint8_t s)
7366 {
7367 unsigned int cnt, res, cf;
7368
7369 if (s < 32) {
7370 cnt = s % 32;
7371 if (cnt > 0) {
7372 cf = d & (1 << (cnt - 1));
7373 res = (d >> cnt) | (fill << (32 - cnt));
7374 CONDITIONAL_SET_FLAG(cf, F_CF);
7375 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7376 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7377 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7378 } else {
7379 res = d;
7380 }
7381 if (cnt == 1) {
7382 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
7383 } else {
7384 CLEAR_FLAG(F_OF);
7385 }
7386 } else {
7387 res = 0;
7388 CLEAR_FLAG(F_CF);
7389 CLEAR_FLAG(F_OF);
7390 SET_FLAG(F_ZF);
7391 CLEAR_FLAG(F_SF);
7392 CLEAR_FLAG(F_PF);
7393 }
7394 return res;
7395 }
7396 /****************************************************************************
7397 REMARKS:
7398 Implements the SBB instruction and side effects.
7399 ****************************************************************************/
7400 static uint8_t
7401 sbb_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
7402 {
7403 uint32_t res; /* all operands in native machine order */
7404 uint32_t bc;
7405
7406 if (ACCESS_FLAG(F_CF))
7407 res = d - s - 1;
7408 else
7409 res = d - s;
7410 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7411 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7412 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7413
7414 /* calculate the borrow chain. See note at top */
7415 bc = (res & (~d | s)) | (~d & s);
7416 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
7417 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
7418 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7419 return (uint8_t) res;
7420 }
7421 /****************************************************************************
7422 REMARKS:
7423 Implements the SBB instruction and side effects.
7424 ****************************************************************************/
7425 static uint16_t
7426 sbb_word(struct X86EMU *emu, uint16_t d, uint16_t s)
7427 {
7428 uint32_t res; /* all operands in native machine order */
7429 uint32_t bc;
7430
7431 if (ACCESS_FLAG(F_CF))
7432 res = d - s - 1;
7433 else
7434 res = d - s;
7435 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7436 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7437 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7438
7439 /* calculate the borrow chain. See note at top */
7440 bc = (res & (~d | s)) | (~d & s);
7441 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
7442 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
7443 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7444 return (uint16_t) res;
7445 }
7446 /****************************************************************************
7447 REMARKS:
7448 Implements the SBB instruction and side effects.
7449 ****************************************************************************/
7450 static uint32_t
7451 sbb_long(struct X86EMU *emu, uint32_t d, uint32_t s)
7452 {
7453 uint32_t res; /* all operands in native machine order */
7454 uint32_t bc;
7455
7456 if (ACCESS_FLAG(F_CF))
7457 res = d - s - 1;
7458 else
7459 res = d - s;
7460 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7461 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7462 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7463
7464 /* calculate the borrow chain. See note at top */
7465 bc = (res & (~d | s)) | (~d & s);
7466 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
7467 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
7468 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7469 return res;
7470 }
7471 /****************************************************************************
7472 REMARKS:
7473 Implements the SUB instruction and side effects.
7474 ****************************************************************************/
7475 static uint8_t
7476 sub_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
7477 {
7478 uint32_t res; /* all operands in native machine order */
7479 uint32_t bc;
7480
7481 res = d - s;
7482 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7483 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7484 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7485
7486 /* calculate the borrow chain. See note at top */
7487 bc = (res & (~d | s)) | (~d & s);
7488 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
7489 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
7490 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7491 return (uint8_t) res;
7492 }
7493 /****************************************************************************
7494 REMARKS:
7495 Implements the SUB instruction and side effects.
7496 ****************************************************************************/
7497 static uint16_t
7498 sub_word(struct X86EMU *emu, uint16_t d, uint16_t s)
7499 {
7500 uint32_t res; /* all operands in native machine order */
7501 uint32_t bc;
7502
7503 res = d - s;
7504 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7505 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7506 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7507
7508 /* calculate the borrow chain. See note at top */
7509 bc = (res & (~d | s)) | (~d & s);
7510 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
7511 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
7512 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7513 return (uint16_t) res;
7514 }
7515 /****************************************************************************
7516 REMARKS:
7517 Implements the SUB instruction and side effects.
7518 ****************************************************************************/
7519 static uint32_t
7520 sub_long(struct X86EMU *emu, uint32_t d, uint32_t s)
7521 {
7522 uint32_t res; /* all operands in native machine order */
7523 uint32_t bc;
7524
7525 res = d - s;
7526 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7527 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7528 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7529
7530 /* calculate the borrow chain. See note at top */
7531 bc = (res & (~d | s)) | (~d & s);
7532 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
7533 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
7534 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7535 return res;
7536 }
7537 /****************************************************************************
7538 REMARKS:
7539 Implements the TEST instruction and side effects.
7540 ****************************************************************************/
7541 static void
7542 test_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
7543 {
7544 uint32_t res; /* all operands in native machine order */
7545
7546 res = d & s;
7547
7548 CLEAR_FLAG(F_OF);
7549 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7550 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7551 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7552 /* AF == dont care */
7553 CLEAR_FLAG(F_CF);
7554 }
7555 /****************************************************************************
7556 REMARKS:
7557 Implements the TEST instruction and side effects.
7558 ****************************************************************************/
7559 static void
7560 test_word(struct X86EMU *emu, uint16_t d, uint16_t s)
7561 {
7562 uint32_t res; /* all operands in native machine order */
7563
7564 res = d & s;
7565
7566 CLEAR_FLAG(F_OF);
7567 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7568 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7569 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7570 /* AF == dont care */
7571 CLEAR_FLAG(F_CF);
7572 }
7573 /****************************************************************************
7574 REMARKS:
7575 Implements the TEST instruction and side effects.
7576 ****************************************************************************/
7577 static void
7578 test_long(struct X86EMU *emu, uint32_t d, uint32_t s)
7579 {
7580 uint32_t res; /* all operands in native machine order */
7581
7582 res = d & s;
7583
7584 CLEAR_FLAG(F_OF);
7585 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7586 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7587 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7588 /* AF == dont care */
7589 CLEAR_FLAG(F_CF);
7590 }
7591 /****************************************************************************
7592 REMARKS:
7593 Implements the XOR instruction and side effects.
7594 ****************************************************************************/
7595 static uint8_t
7596 xor_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
7597 {
7598 uint8_t res; /* all operands in native machine order */
7599
7600 res = d ^ s;
7601 CLEAR_FLAG(F_OF);
7602 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7603 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7604 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
7605 CLEAR_FLAG(F_CF);
7606 CLEAR_FLAG(F_AF);
7607 return res;
7608 }
7609 /****************************************************************************
7610 REMARKS:
7611 Implements the XOR instruction and side effects.
7612 ****************************************************************************/
7613 static uint16_t
7614 xor_word(struct X86EMU *emu, uint16_t d, uint16_t s)
7615 {
7616 uint16_t res; /* all operands in native machine order */
7617
7618 res = d ^ s;
7619 CLEAR_FLAG(F_OF);
7620 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7621 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7622 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7623 CLEAR_FLAG(F_CF);
7624 CLEAR_FLAG(F_AF);
7625 return res;
7626 }
7627 /****************************************************************************
7628 REMARKS:
7629 Implements the XOR instruction and side effects.
7630 ****************************************************************************/
7631 static uint32_t
7632 xor_long(struct X86EMU *emu, uint32_t d, uint32_t s)
7633 {
7634 uint32_t res; /* all operands in native machine order */
7635
7636 res = d ^ s;
7637 CLEAR_FLAG(F_OF);
7638 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7639 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7640 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7641 CLEAR_FLAG(F_CF);
7642 CLEAR_FLAG(F_AF);
7643 return res;
7644 }
7645 /****************************************************************************
7646 REMARKS:
7647 Implements the IMUL instruction and side effects.
7648 ****************************************************************************/
7649 static void
7650 imul_byte(struct X86EMU *emu, uint8_t s)
7651 {
7652 int16_t res = (int16_t) ((int8_t) emu->x86.R_AL * (int8_t) s);
7653
7654 emu->x86.R_AX = res;
7655 if (((emu->x86.R_AL & 0x80) == 0 && emu->x86.R_AH == 0x00) ||
7656 ((emu->x86.R_AL & 0x80) != 0 && emu->x86.R_AH == 0xFF)) {
7657 CLEAR_FLAG(F_CF);
7658 CLEAR_FLAG(F_OF);
7659 } else {
7660 SET_FLAG(F_CF);
7661 SET_FLAG(F_OF);
7662 }
7663 }
7664 /****************************************************************************
7665 REMARKS:
7666 Implements the IMUL instruction and side effects.
7667 ****************************************************************************/
7668 static void
7669 imul_word(struct X86EMU *emu, uint16_t s)
7670 {
7671 int32_t res = (int16_t) emu->x86.R_AX * (int16_t) s;
7672
7673 emu->x86.R_AX = (uint16_t) res;
7674 emu->x86.R_DX = (uint16_t) (res >> 16);
7675 if (((emu->x86.R_AX & 0x8000) == 0 && emu->x86.R_DX == 0x00) ||
7676 ((emu->x86.R_AX & 0x8000) != 0 && emu->x86.R_DX == 0xFF)) {
7677 CLEAR_FLAG(F_CF);
7678 CLEAR_FLAG(F_OF);
7679 } else {
7680 SET_FLAG(F_CF);
7681 SET_FLAG(F_OF);
7682 }
7683 }
7684 /****************************************************************************
7685 REMARKS:
7686 Implements the IMUL instruction and side effects.
7687 ****************************************************************************/
7688 static void
7689 imul_long(struct X86EMU *emu, uint32_t s)
7690 {
7691 int64_t res;
7692
7693 res = (int64_t)(int32_t)emu->x86.R_EAX * (int32_t)s;
7694 emu->x86.R_EAX = (uint32_t)res;
7695 emu->x86.R_EDX = ((uint64_t)res) >> 32;
7696 if (((emu->x86.R_EAX & 0x80000000) == 0 && emu->x86.R_EDX == 0x00) ||
7697 ((emu->x86.R_EAX & 0x80000000) != 0 && emu->x86.R_EDX == 0xFF)) {
7698 CLEAR_FLAG(F_CF);
7699 CLEAR_FLAG(F_OF);
7700 } else {
7701 SET_FLAG(F_CF);
7702 SET_FLAG(F_OF);
7703 }
7704 }
7705 /****************************************************************************
7706 REMARKS:
7707 Implements the MUL instruction and side effects.
7708 ****************************************************************************/
7709 static void
7710 mul_byte(struct X86EMU *emu, uint8_t s)
7711 {
7712 uint16_t res = (uint16_t) (emu->x86.R_AL * s);
7713
7714 emu->x86.R_AX = res;
7715 if (emu->x86.R_AH == 0) {
7716 CLEAR_FLAG(F_CF);
7717 CLEAR_FLAG(F_OF);
7718 } else {
7719 SET_FLAG(F_CF);
7720 SET_FLAG(F_OF);
7721 }
7722 }
7723 /****************************************************************************
7724 REMARKS:
7725 Implements the MUL instruction and side effects.
7726 ****************************************************************************/
7727 static void
7728 mul_word(struct X86EMU *emu, uint16_t s)
7729 {
7730 uint32_t res = emu->x86.R_AX * s;
7731
7732 emu->x86.R_AX = (uint16_t) res;
7733 emu->x86.R_DX = (uint16_t) (res >> 16);
7734 if (emu->x86.R_DX == 0) {
7735 CLEAR_FLAG(F_CF);
7736 CLEAR_FLAG(F_OF);
7737 } else {
7738 SET_FLAG(F_CF);
7739 SET_FLAG(F_OF);
7740 }
7741 }
7742 /****************************************************************************
7743 REMARKS:
7744 Implements the MUL instruction and side effects.
7745 ****************************************************************************/
7746 static void
7747 mul_long(struct X86EMU *emu, uint32_t s)
7748 {
7749 uint64_t res = (uint64_t) emu->x86.R_EAX * s;
7750
7751 emu->x86.R_EAX = (uint32_t) res;
7752 emu->x86.R_EDX = (uint32_t) (res >> 32);
7753
7754 if (emu->x86.R_EDX == 0) {
7755 CLEAR_FLAG(F_CF);
7756 CLEAR_FLAG(F_OF);
7757 } else {
7758 SET_FLAG(F_CF);
7759 SET_FLAG(F_OF);
7760 }
7761 }
7762 /****************************************************************************
7763 REMARKS:
7764 Implements the IDIV instruction and side effects.
7765 ****************************************************************************/
7766 static void
7767 idiv_byte(struct X86EMU *emu, uint8_t s)
7768 {
7769 int32_t dvd, div, mod;
7770
7771 dvd = (int16_t) emu->x86.R_AX;
7772 if (s == 0) {
7773 x86emu_intr_raise(emu, 8);
7774 return;
7775 }
7776 div = dvd / (int8_t) s;
7777 mod = dvd % (int8_t) s;
7778 if (div > 0x7f || div < -0x7f) {
7779 x86emu_intr_raise(emu, 8);
7780 return;
7781 }
7782 emu->x86.R_AL = (int8_t) div;
7783 emu->x86.R_AH = (int8_t) mod;
7784 }
7785 /****************************************************************************
7786 REMARKS:
7787 Implements the IDIV instruction and side effects.
7788 ****************************************************************************/
7789 static void
7790 idiv_word(struct X86EMU *emu, uint16_t s)
7791 {
7792 int32_t dvd, div, mod;
7793
7794 dvd = (((int32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX;
7795 if (s == 0) {
7796 x86emu_intr_raise(emu, 8);
7797 return;
7798 }
7799 div = dvd / (int16_t) s;
7800 mod = dvd % (int16_t) s;
7801 if (div > 0x7fff || div < -0x7fff) {
7802 x86emu_intr_raise(emu, 8);
7803 return;
7804 }
7805 CLEAR_FLAG(F_CF);
7806 CLEAR_FLAG(F_SF);
7807 CONDITIONAL_SET_FLAG(div == 0, F_ZF);
7808 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
7809
7810 emu->x86.R_AX = (uint16_t) div;
7811 emu->x86.R_DX = (uint16_t) mod;
7812 }
7813 /****************************************************************************
7814 REMARKS:
7815 Implements the IDIV instruction and side effects.
7816 ****************************************************************************/
7817 static void
7818 idiv_long(struct X86EMU *emu, uint32_t s)
7819 {
7820 int64_t dvd, div, mod;
7821
7822 dvd = (((int64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX;
7823 if (s == 0) {
7824 x86emu_intr_raise(emu, 8);
7825 return;
7826 }
7827 div = dvd / (int32_t) s;
7828 mod = dvd % (int32_t) s;
7829 if (div > 0x7fffffff || div < -0x7fffffff) {
7830 x86emu_intr_raise(emu, 8);
7831 return;
7832 }
7833 CLEAR_FLAG(F_CF);
7834 CLEAR_FLAG(F_AF);
7835 CLEAR_FLAG(F_SF);
7836 SET_FLAG(F_ZF);
7837 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
7838
7839 emu->x86.R_EAX = (uint32_t) div;
7840 emu->x86.R_EDX = (uint32_t) mod;
7841 }
7842 /****************************************************************************
7843 REMARKS:
7844 Implements the DIV instruction and side effects.
7845 ****************************************************************************/
7846 static void
7847 div_byte(struct X86EMU *emu, uint8_t s)
7848 {
7849 uint32_t dvd, div, mod;
7850
7851 dvd = emu->x86.R_AX;
7852 if (s == 0) {
7853 x86emu_intr_raise(emu, 8);
7854 return;
7855 }
7856 div = dvd / (uint8_t) s;
7857 mod = dvd % (uint8_t) s;
7858 if (div > 0xff) {
7859 x86emu_intr_raise(emu, 8);
7860 return;
7861 }
7862 emu->x86.R_AL = (uint8_t) div;
7863 emu->x86.R_AH = (uint8_t) mod;
7864 }
7865 /****************************************************************************
7866 REMARKS:
7867 Implements the DIV instruction and side effects.
7868 ****************************************************************************/
7869 static void
7870 div_word(struct X86EMU *emu, uint16_t s)
7871 {
7872 uint32_t dvd, div, mod;
7873
7874 dvd = (((uint32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX;
7875 if (s == 0) {
7876 x86emu_intr_raise(emu, 8);
7877 return;
7878 }
7879 div = dvd / (uint16_t) s;
7880 mod = dvd % (uint16_t) s;
7881 if (div > 0xffff) {
7882 x86emu_intr_raise(emu, 8);
7883 return;
7884 }
7885 CLEAR_FLAG(F_CF);
7886 CLEAR_FLAG(F_SF);
7887 CONDITIONAL_SET_FLAG(div == 0, F_ZF);
7888 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
7889
7890 emu->x86.R_AX = (uint16_t) div;
7891 emu->x86.R_DX = (uint16_t) mod;
7892 }
7893 /****************************************************************************
7894 REMARKS:
7895 Implements the DIV instruction and side effects.
7896 ****************************************************************************/
7897 static void
7898 div_long(struct X86EMU *emu, uint32_t s)
7899 {
7900 uint64_t dvd, div, mod;
7901
7902 dvd = (((uint64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX;
7903 if (s == 0) {
7904 x86emu_intr_raise(emu, 8);
7905 return;
7906 }
7907 div = dvd / (uint32_t) s;
7908 mod = dvd % (uint32_t) s;
7909 if (div > 0xffffffff) {
7910 x86emu_intr_raise(emu, 8);
7911 return;
7912 }
7913 CLEAR_FLAG(F_CF);
7914 CLEAR_FLAG(F_AF);
7915 CLEAR_FLAG(F_SF);
7916 SET_FLAG(F_ZF);
7917 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
7918
7919 emu->x86.R_EAX = (uint32_t) div;
7920 emu->x86.R_EDX = (uint32_t) mod;
7921 }
7922 /****************************************************************************
7923 REMARKS:
7924 Implements the IN string instruction and side effects.
7925 ****************************************************************************/
7926 static void
7927 ins(struct X86EMU *emu, int size)
7928 {
7929 int inc = size;
7930
7931 if (ACCESS_FLAG(F_DF)) {
7932 inc = -size;
7933 }
7934 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
7935 /* dont care whether REPE or REPNE */
7936 /* in until CX is ZERO. */
7937 uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ?
7938 emu->x86.R_ECX : emu->x86.R_CX);
7939 switch (size) {
7940 case 1:
7941 while (count--) {
7942 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
7943 (*emu->emu_inb) (emu, emu->x86.R_DX));
7944 emu->x86.R_DI += inc;
7945 }
7946 break;
7947
7948 case 2:
7949 while (count--) {
7950 store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
7951 (*emu->emu_inw) (emu, emu->x86.R_DX));
7952 emu->x86.R_DI += inc;
7953 }
7954 break;
7955 case 4:
7956 while (count--) {
7957 store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
7958 (*emu->emu_inl) (emu, emu->x86.R_DX));
7959 emu->x86.R_DI += inc;
7960 break;
7961 }
7962 }
7963 emu->x86.R_CX = 0;
7964 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
7965 emu->x86.R_ECX = 0;
7966 }
7967 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
7968 } else {
7969 switch (size) {
7970 case 1:
7971 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
7972 (*emu->emu_inb) (emu, emu->x86.R_DX));
7973 break;
7974 case 2:
7975 store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
7976 (*emu->emu_inw) (emu, emu->x86.R_DX));
7977 break;
7978 case 4:
7979 store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
7980 (*emu->emu_inl) (emu, emu->x86.R_DX));
7981 break;
7982 }
7983 emu->x86.R_DI += inc;
7984 }
7985 }
7986 /****************************************************************************
7987 REMARKS:
7988 Implements the OUT string instruction and side effects.
7989 ****************************************************************************/
7990 static void
7991 outs(struct X86EMU *emu, int size)
7992 {
7993 int inc = size;
7994
7995 if (ACCESS_FLAG(F_DF)) {
7996 inc = -size;
7997 }
7998 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
7999 /* dont care whether REPE or REPNE */
8000 /* out until CX is ZERO. */
8001 uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ?
8002 emu->x86.R_ECX : emu->x86.R_CX);
8003 switch (size) {
8004 case 1:
8005 while (count--) {
8006 (*emu->emu_outb) (emu, emu->x86.R_DX,
8007 fetch_byte(emu, emu->x86.R_ES, emu->x86.R_SI));
8008 emu->x86.R_SI += inc;
8009 }
8010 break;
8011
8012 case 2:
8013 while (count--) {
8014 (*emu->emu_outw) (emu, emu->x86.R_DX,
8015 fetch_word(emu, emu->x86.R_ES, emu->x86.R_SI));
8016 emu->x86.R_SI += inc;
8017 }
8018 break;
8019 case 4:
8020 while (count--) {
8021 (*emu->emu_outl) (emu, emu->x86.R_DX,
8022 fetch_long(emu, emu->x86.R_ES, emu->x86.R_SI));
8023 emu->x86.R_SI += inc;
8024 break;
8025 }
8026 }
8027 emu->x86.R_CX = 0;
8028 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
8029 emu->x86.R_ECX = 0;
8030 }
8031 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
8032 } else {
8033 switch (size) {
8034 case 1:
8035 (*emu->emu_outb) (emu, emu->x86.R_DX,
8036 fetch_byte(emu, emu->x86.R_ES, emu->x86.R_SI));
8037 break;
8038 case 2:
8039 (*emu->emu_outw) (emu, emu->x86.R_DX,
8040 fetch_word(emu, emu->x86.R_ES, emu->x86.R_SI));
8041 break;
8042 case 4:
8043 (*emu->emu_outl) (emu, emu->x86.R_DX,
8044 fetch_long(emu, emu->x86.R_ES, emu->x86.R_SI));
8045 break;
8046 }
8047 emu->x86.R_SI += inc;
8048 }
8049 }
8050 /****************************************************************************
8051 REMARKS:
8052 Pushes a word onto the stack.
8053
8054 NOTE: Do not inline this, as (*emu->emu_wrX) is already inline!
8055 ****************************************************************************/
8056 static void
8057 push_word(struct X86EMU *emu, uint16_t w)
8058 {
8059 emu->x86.R_SP -= 2;
8060 store_word(emu, emu->x86.R_SS, emu->x86.R_SP, w);
8061 }
8062 /****************************************************************************
8063 REMARKS:
8064 Pushes a long onto the stack.
8065
8066 NOTE: Do not inline this, as (*emu->emu_wrX) is already inline!
8067 ****************************************************************************/
8068 static void
8069 push_long(struct X86EMU *emu, uint32_t w)
8070 {
8071 emu->x86.R_SP -= 4;
8072 store_long(emu, emu->x86.R_SS, emu->x86.R_SP, w);
8073 }
8074 /****************************************************************************
8075 REMARKS:
8076 Pops a word from the stack.
8077
8078 NOTE: Do not inline this, as (*emu->emu_rdX) is already inline!
8079 ****************************************************************************/
8080 static uint16_t
8081 pop_word(struct X86EMU *emu)
8082 {
8083 uint16_t res;
8084
8085 res = fetch_word(emu, emu->x86.R_SS, emu->x86.R_SP);
8086 emu->x86.R_SP += 2;
8087 return res;
8088 }
8089 /****************************************************************************
8090 REMARKS:
8091 Pops a long from the stack.
8092
8093 NOTE: Do not inline this, as (*emu->emu_rdX) is already inline!
8094 ****************************************************************************/
8095 static uint32_t
8096 pop_long(struct X86EMU *emu)
8097 {
8098 uint32_t res;
8099
8100 res = fetch_long(emu, emu->x86.R_SS, emu->x86.R_SP);
8101 emu->x86.R_SP += 4;
8102 return res;
8103 }
8104