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