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