1 /****************************************************************************
2 *
3 * Realmode X86 Emulator Library
4 *
5 * Copyright (C) 1991-2004 SciTech Software, Inc.
6 * Copyright (C) David Mosberger-Tang
7 * Copyright (C) 1999 Egbert Eich
8 *
9 * ========================================================================
10 *
11 * Permission to use, copy, modify, distribute, and sell this software and
12 * its documentation for any purpose is hereby granted without fee,
13 * provided that the above copyright notice appear in all copies and that
14 * both that copyright notice and this permission notice appear in
15 * supporting documentation, and that the name of the authors not be used
16 * in advertising or publicity pertaining to distribution of the software
17 * without specific, written prior permission. The authors makes no
18 * representations about the suitability of this software for any purpose.
19 * It is provided "as is" without express or implied warranty.
20 *
21 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
22 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
23 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
24 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
25 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
26 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
27 * PERFORMANCE OF THIS SOFTWARE.
28 *
29 * ========================================================================
30 *
31 * Language: ANSI C
32 * Environment: Any
33 * Developer: Kendall Bennett
34 *
35 * Description: This file contains the code to implement the primitive
36 * machine operations used by the emulation code in ops.c
37 *
38 * Carry Chain Calculation
39 *
40 * This represents a somewhat expensive calculation which is
41 * apparently required to emulate the setting of the OF343364 and AF flag.
42 * The latter is not so important, but the former is. The overflow
43 * flag is the XOR of the top two bits of the carry chain for an
44 * addition (similar for subtraction). Since we do not want to
45 * simulate the addition in a bitwise manner, we try to calculate the
46 * carry chain given the two operands and the result.
47 *
48 * So, given the following table, which represents the addition of two
49 * bits, we can derive a formula for the carry chain.
50 *
51 * a b cin r cout
52 * 0 0 0 0 0
53 * 0 0 1 1 0
54 * 0 1 0 1 0
55 * 0 1 1 0 1
56 * 1 0 0 1 0
57 * 1 0 1 0 1
58 * 1 1 0 0 1
59 * 1 1 1 1 1
60 *
61 * Construction of table for cout:
62 *
63 * ab
64 * r \ 00 01 11 10
65 * |------------------
66 * 0 | 0 1 1 1
67 * 1 | 0 0 1 0
68 *
69 * By inspection, one gets: cc = ab + r'(a + b)
70 *
71 * That represents alot of operations, but NO CHOICE....
72 *
73 * Borrow Chain Calculation.
74 *
75 * The following table represents the subtraction of two bits, from
76 * which we can derive a formula for the borrow chain.
77 *
78 * a b bin r bout
79 * 0 0 0 0 0
80 * 0 0 1 1 1
81 * 0 1 0 1 1
82 * 0 1 1 0 1
83 * 1 0 0 1 0
84 * 1 0 1 0 0
85 * 1 1 0 0 0
86 * 1 1 1 1 1
87 *
88 * Construction of table for cout:
89 *
90 * ab
91 * r \ 00 01 11 10
92 * |------------------
93 * 0 | 0 1 0 0
94 * 1 | 1 1 1 0
95 *
96 * By inspection, one gets: bc = a'b + r(a' + b)
97 *
98 ****************************************************************************/
99
100 #include <common.h>
101
102 #define PRIM_OPS_NO_REDEFINE_ASM
103 #include "x86emu/x86emui.h"
104
105 /*------------------------- Global Variables ------------------------------*/
106
107 static u32 x86emu_parity_tab[8] =
108 {
109 0x96696996,
110 0x69969669,
111 0x69969669,
112 0x96696996,
113 0x69969669,
114 0x96696996,
115 0x96696996,
116 0x69969669,
117 };
118
119 #define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
120 #define XOR2(x) (((x) ^ ((x)>>1)) & 0x1)
121 /*----------------------------- Implementation ----------------------------*/
abs(int v)122 int abs(int v)
123 {
124 return (v>0)?v:-v;
125 }
126
127 /*----------------------------- Implementation ----------------------------*/
128
129
130 /*--------- Side effects helper functions -------*/
131
132 /****************************************************************************
133 REMARKS:
134 implements side efects for byte operations that don't overflow
135 ****************************************************************************/
136
set_parity_flag(u32 res)137 static void set_parity_flag(u32 res)
138 {
139 CONDITIONAL_SET_FLAG(PARITY(res & 0xFF), F_PF);
140 }
141
set_szp_flags_8(u8 res)142 static void set_szp_flags_8(u8 res)
143 {
144 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
145 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
146 set_parity_flag(res);
147 }
148
set_szp_flags_16(u16 res)149 static void set_szp_flags_16(u16 res)
150 {
151 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
152 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
153 set_parity_flag(res);
154 }
155
set_szp_flags_32(u32 res)156 static void set_szp_flags_32(u32 res)
157 {
158 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
159 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
160 set_parity_flag(res);
161 }
162
no_carry_byte_side_eff(u8 res)163 static void no_carry_byte_side_eff(u8 res)
164 {
165 CLEAR_FLAG(F_OF);
166 CLEAR_FLAG(F_CF);
167 CLEAR_FLAG(F_AF);
168 set_szp_flags_8(res);
169 }
170
no_carry_word_side_eff(u16 res)171 static void no_carry_word_side_eff(u16 res)
172 {
173 CLEAR_FLAG(F_OF);
174 CLEAR_FLAG(F_CF);
175 CLEAR_FLAG(F_AF);
176 set_szp_flags_16(res);
177 }
178
no_carry_long_side_eff(u32 res)179 static void no_carry_long_side_eff(u32 res)
180 {
181 CLEAR_FLAG(F_OF);
182 CLEAR_FLAG(F_CF);
183 CLEAR_FLAG(F_AF);
184 set_szp_flags_32(res);
185 }
186
calc_carry_chain(int bits,u32 d,u32 s,u32 res,int set_carry)187 static void calc_carry_chain(int bits, u32 d, u32 s, u32 res, int set_carry)
188 {
189 u32 cc;
190
191 cc = (s & d) | ((~res) & (s | d));
192 CONDITIONAL_SET_FLAG(XOR2(cc >> (bits - 2)), F_OF);
193 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
194 if (set_carry) {
195 CONDITIONAL_SET_FLAG(res & (1 << bits), F_CF);
196 }
197 }
198
calc_borrow_chain(int bits,u32 d,u32 s,u32 res,int set_carry)199 static void calc_borrow_chain(int bits, u32 d, u32 s, u32 res, int set_carry)
200 {
201 u32 bc;
202
203 bc = (res & (~d | s)) | (~d & s);
204 CONDITIONAL_SET_FLAG(XOR2(bc >> (bits - 2)), F_OF);
205 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
206 if (set_carry) {
207 CONDITIONAL_SET_FLAG(bc & (1 << (bits - 1)), F_CF);
208 }
209 }
210
211 /****************************************************************************
212 REMARKS:
213 Implements the AAA instruction and side effects.
214 ****************************************************************************/
aaa_word(u16 d)215 u16 aaa_word(u16 d)
216 {
217 u16 res;
218 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
219 d += 0x6;
220 d += 0x100;
221 SET_FLAG(F_AF);
222 SET_FLAG(F_CF);
223 } else {
224 CLEAR_FLAG(F_CF);
225 CLEAR_FLAG(F_AF);
226 }
227 res = (u16)(d & 0xFF0F);
228 set_szp_flags_16(res);
229 return res;
230 }
231
232 /****************************************************************************
233 REMARKS:
234 Implements the AAA instruction and side effects.
235 ****************************************************************************/
aas_word(u16 d)236 u16 aas_word(u16 d)
237 {
238 u16 res;
239 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
240 d -= 0x6;
241 d -= 0x100;
242 SET_FLAG(F_AF);
243 SET_FLAG(F_CF);
244 } else {
245 CLEAR_FLAG(F_CF);
246 CLEAR_FLAG(F_AF);
247 }
248 res = (u16)(d & 0xFF0F);
249 set_szp_flags_16(res);
250 return res;
251 }
252
253 /****************************************************************************
254 REMARKS:
255 Implements the AAD instruction and side effects.
256 ****************************************************************************/
aad_word(u16 d)257 u16 aad_word(u16 d)
258 {
259 u16 l;
260 u8 hb, lb;
261
262 hb = (u8)((d >> 8) & 0xff);
263 lb = (u8)((d & 0xff));
264 l = (u16)((lb + 10 * hb) & 0xFF);
265
266 no_carry_byte_side_eff(l & 0xFF);
267 return l;
268 }
269
270 /****************************************************************************
271 REMARKS:
272 Implements the AAM instruction and side effects.
273 ****************************************************************************/
aam_word(u8 d)274 u16 aam_word(u8 d)
275 {
276 u16 h, l;
277
278 h = (u16)(d / 10);
279 l = (u16)(d % 10);
280 l |= (u16)(h << 8);
281
282 no_carry_byte_side_eff(l & 0xFF);
283 return l;
284 }
285
286 /****************************************************************************
287 REMARKS:
288 Implements the ADC instruction and side effects.
289 ****************************************************************************/
adc_byte(u8 d,u8 s)290 u8 adc_byte(u8 d, u8 s)
291 {
292 u32 res; /* all operands in native machine order */
293
294 res = d + s;
295 if (ACCESS_FLAG(F_CF)) res++;
296
297 set_szp_flags_8(res);
298 calc_carry_chain(8,s,d,res,1);
299
300 return (u8)res;
301 }
302
303 /****************************************************************************
304 REMARKS:
305 Implements the ADC instruction and side effects.
306 ****************************************************************************/
adc_word(u16 d,u16 s)307 u16 adc_word(u16 d, u16 s)
308 {
309 u32 res; /* all operands in native machine order */
310
311 res = d + s;
312 if (ACCESS_FLAG(F_CF))
313 res++;
314
315 set_szp_flags_16((u16)res);
316 calc_carry_chain(16,s,d,res,1);
317
318 return (u16)res;
319 }
320
321 /****************************************************************************
322 REMARKS:
323 Implements the ADC instruction and side effects.
324 ****************************************************************************/
adc_long(u32 d,u32 s)325 u32 adc_long(u32 d, u32 s)
326 {
327 u32 lo; /* all operands in native machine order */
328 u32 hi;
329 u32 res;
330
331 lo = (d & 0xFFFF) + (s & 0xFFFF);
332 res = d + s;
333
334 if (ACCESS_FLAG(F_CF)) {
335 lo++;
336 res++;
337 }
338
339 hi = (lo >> 16) + (d >> 16) + (s >> 16);
340
341 set_szp_flags_32(res);
342 calc_carry_chain(32,s,d,res,0);
343
344 CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
345
346 return res;
347 }
348
349 /****************************************************************************
350 REMARKS:
351 Implements the ADD instruction and side effects.
352 ****************************************************************************/
add_byte(u8 d,u8 s)353 u8 add_byte(u8 d, u8 s)
354 {
355 u32 res; /* all operands in native machine order */
356
357 res = d + s;
358 set_szp_flags_8((u8)res);
359 calc_carry_chain(8,s,d,res,1);
360
361 return (u8)res;
362 }
363
364 /****************************************************************************
365 REMARKS:
366 Implements the ADD instruction and side effects.
367 ****************************************************************************/
add_word(u16 d,u16 s)368 u16 add_word(u16 d, u16 s)
369 {
370 u32 res; /* all operands in native machine order */
371
372 res = d + s;
373 set_szp_flags_16((u16)res);
374 calc_carry_chain(16,s,d,res,1);
375
376 return (u16)res;
377 }
378
379 /****************************************************************************
380 REMARKS:
381 Implements the ADD instruction and side effects.
382 ****************************************************************************/
add_long(u32 d,u32 s)383 u32 add_long(u32 d, u32 s)
384 {
385 u32 res;
386
387 res = d + s;
388 set_szp_flags_32(res);
389 calc_carry_chain(32,s,d,res,0);
390
391 CONDITIONAL_SET_FLAG(res < d || res < s, F_CF);
392
393 return res;
394 }
395
396 /****************************************************************************
397 REMARKS:
398 Implements the AND instruction and side effects.
399 ****************************************************************************/
and_byte(u8 d,u8 s)400 u8 and_byte(u8 d, u8 s)
401 {
402 u8 res; /* all operands in native machine order */
403
404 res = d & s;
405
406 no_carry_byte_side_eff(res);
407 return res;
408 }
409
410 /****************************************************************************
411 REMARKS:
412 Implements the AND instruction and side effects.
413 ****************************************************************************/
and_word(u16 d,u16 s)414 u16 and_word(u16 d, u16 s)
415 {
416 u16 res; /* all operands in native machine order */
417
418 res = d & s;
419
420 no_carry_word_side_eff(res);
421 return res;
422 }
423
424 /****************************************************************************
425 REMARKS:
426 Implements the AND instruction and side effects.
427 ****************************************************************************/
and_long(u32 d,u32 s)428 u32 and_long(u32 d, u32 s)
429 {
430 u32 res; /* all operands in native machine order */
431
432 res = d & s;
433 no_carry_long_side_eff(res);
434 return res;
435 }
436
437 /****************************************************************************
438 REMARKS:
439 Implements the CMP instruction and side effects.
440 ****************************************************************************/
cmp_byte(u8 d,u8 s)441 u8 cmp_byte(u8 d, u8 s)
442 {
443 u32 res; /* all operands in native machine order */
444
445 res = d - s;
446 set_szp_flags_8((u8)res);
447 calc_borrow_chain(8, d, s, res, 1);
448
449 return d;
450 }
451
452 /****************************************************************************
453 REMARKS:
454 Implements the CMP instruction and side effects.
455 ****************************************************************************/
cmp_word(u16 d,u16 s)456 u16 cmp_word(u16 d, u16 s)
457 {
458 u32 res; /* all operands in native machine order */
459
460 res = d - s;
461 set_szp_flags_16((u16)res);
462 calc_borrow_chain(16, d, s, res, 1);
463
464 return d;
465 }
466
467 /****************************************************************************
468 REMARKS:
469 Implements the CMP instruction and side effects.
470 ****************************************************************************/
cmp_long(u32 d,u32 s)471 u32 cmp_long(u32 d, u32 s)
472 {
473 u32 res; /* all operands in native machine order */
474
475 res = d - s;
476 set_szp_flags_32(res);
477 calc_borrow_chain(32, d, s, res, 1);
478
479 return d;
480 }
481
482 /****************************************************************************
483 REMARKS:
484 Implements the DAA instruction and side effects.
485 ****************************************************************************/
daa_byte(u8 d)486 u8 daa_byte(u8 d)
487 {
488 u32 res = d;
489 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
490 res += 6;
491 SET_FLAG(F_AF);
492 }
493 if (res > 0x9F || ACCESS_FLAG(F_CF)) {
494 res += 0x60;
495 SET_FLAG(F_CF);
496 }
497 set_szp_flags_8((u8)res);
498 return (u8)res;
499 }
500
501 /****************************************************************************
502 REMARKS:
503 Implements the DAS instruction and side effects.
504 ****************************************************************************/
das_byte(u8 d)505 u8 das_byte(u8 d)
506 {
507 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
508 d -= 6;
509 SET_FLAG(F_AF);
510 }
511 if (d > 0x9F || ACCESS_FLAG(F_CF)) {
512 d -= 0x60;
513 SET_FLAG(F_CF);
514 }
515 set_szp_flags_8(d);
516 return d;
517 }
518
519 /****************************************************************************
520 REMARKS:
521 Implements the DEC instruction and side effects.
522 ****************************************************************************/
dec_byte(u8 d)523 u8 dec_byte(u8 d)
524 {
525 u32 res; /* all operands in native machine order */
526
527 res = d - 1;
528 set_szp_flags_8((u8)res);
529 calc_borrow_chain(8, d, 1, res, 0);
530
531 return (u8)res;
532 }
533
534 /****************************************************************************
535 REMARKS:
536 Implements the DEC instruction and side effects.
537 ****************************************************************************/
dec_word(u16 d)538 u16 dec_word(u16 d)
539 {
540 u32 res; /* all operands in native machine order */
541
542 res = d - 1;
543 set_szp_flags_16((u16)res);
544 calc_borrow_chain(16, d, 1, res, 0);
545
546 return (u16)res;
547 }
548
549 /****************************************************************************
550 REMARKS:
551 Implements the DEC instruction and side effects.
552 ****************************************************************************/
dec_long(u32 d)553 u32 dec_long(u32 d)
554 {
555 u32 res; /* all operands in native machine order */
556
557 res = d - 1;
558
559 set_szp_flags_32(res);
560 calc_borrow_chain(32, d, 1, res, 0);
561
562 return res;
563 }
564
565 /****************************************************************************
566 REMARKS:
567 Implements the INC instruction and side effects.
568 ****************************************************************************/
inc_byte(u8 d)569 u8 inc_byte(u8 d)
570 {
571 u32 res; /* all operands in native machine order */
572
573 res = d + 1;
574 set_szp_flags_8((u8)res);
575 calc_carry_chain(8, d, 1, res, 0);
576
577 return (u8)res;
578 }
579
580 /****************************************************************************
581 REMARKS:
582 Implements the INC instruction and side effects.
583 ****************************************************************************/
inc_word(u16 d)584 u16 inc_word(u16 d)
585 {
586 u32 res; /* all operands in native machine order */
587
588 res = d + 1;
589 set_szp_flags_16((u16)res);
590 calc_carry_chain(16, d, 1, res, 0);
591
592 return (u16)res;
593 }
594
595 /****************************************************************************
596 REMARKS:
597 Implements the INC instruction and side effects.
598 ****************************************************************************/
inc_long(u32 d)599 u32 inc_long(u32 d)
600 {
601 u32 res; /* all operands in native machine order */
602
603 res = d + 1;
604 set_szp_flags_32(res);
605 calc_carry_chain(32, d, 1, res, 0);
606
607 return res;
608 }
609
610 /****************************************************************************
611 REMARKS:
612 Implements the OR instruction and side effects.
613 ****************************************************************************/
or_byte(u8 d,u8 s)614 u8 or_byte(u8 d, u8 s)
615 {
616 u8 res; /* all operands in native machine order */
617
618 res = d | s;
619 no_carry_byte_side_eff(res);
620
621 return res;
622 }
623
624 /****************************************************************************
625 REMARKS:
626 Implements the OR instruction and side effects.
627 ****************************************************************************/
or_word(u16 d,u16 s)628 u16 or_word(u16 d, u16 s)
629 {
630 u16 res; /* all operands in native machine order */
631
632 res = d | s;
633 no_carry_word_side_eff(res);
634 return res;
635 }
636
637 /****************************************************************************
638 REMARKS:
639 Implements the OR instruction and side effects.
640 ****************************************************************************/
or_long(u32 d,u32 s)641 u32 or_long(u32 d, u32 s)
642 {
643 u32 res; /* all operands in native machine order */
644
645 res = d | s;
646 no_carry_long_side_eff(res);
647 return res;
648 }
649
650 /****************************************************************************
651 REMARKS:
652 Implements the OR instruction and side effects.
653 ****************************************************************************/
neg_byte(u8 s)654 u8 neg_byte(u8 s)
655 {
656 u8 res;
657
658 CONDITIONAL_SET_FLAG(s != 0, F_CF);
659 res = (u8)-s;
660 set_szp_flags_8(res);
661 calc_borrow_chain(8, 0, s, res, 0);
662
663 return res;
664 }
665
666 /****************************************************************************
667 REMARKS:
668 Implements the OR instruction and side effects.
669 ****************************************************************************/
neg_word(u16 s)670 u16 neg_word(u16 s)
671 {
672 u16 res;
673
674 CONDITIONAL_SET_FLAG(s != 0, F_CF);
675 res = (u16)-s;
676 set_szp_flags_16((u16)res);
677 calc_borrow_chain(16, 0, s, res, 0);
678
679 return res;
680 }
681
682 /****************************************************************************
683 REMARKS:
684 Implements the OR instruction and side effects.
685 ****************************************************************************/
neg_long(u32 s)686 u32 neg_long(u32 s)
687 {
688 u32 res;
689
690 CONDITIONAL_SET_FLAG(s != 0, F_CF);
691 res = (u32)-s;
692 set_szp_flags_32(res);
693 calc_borrow_chain(32, 0, s, res, 0);
694
695 return res;
696 }
697
698 /****************************************************************************
699 REMARKS:
700 Implements the NOT instruction and side effects.
701 ****************************************************************************/
not_byte(u8 s)702 u8 not_byte(u8 s)
703 {
704 return ~s;
705 }
706
707 /****************************************************************************
708 REMARKS:
709 Implements the NOT instruction and side effects.
710 ****************************************************************************/
not_word(u16 s)711 u16 not_word(u16 s)
712 {
713 return ~s;
714 }
715
716 /****************************************************************************
717 REMARKS:
718 Implements the NOT instruction and side effects.
719 ****************************************************************************/
not_long(u32 s)720 u32 not_long(u32 s)
721 {
722 return ~s;
723 }
724
725 /****************************************************************************
726 REMARKS:
727 Implements the RCL instruction and side effects.
728 ****************************************************************************/
rcl_byte(u8 d,u8 s)729 u8 rcl_byte(u8 d, u8 s)
730 {
731 unsigned int res, cnt, mask, cf;
732
733 /* s is the rotate distance. It varies from 0 - 8. */
734 /* have
735
736 CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
737
738 want to rotate through the carry by "s" bits. We could
739 loop, but that's inefficient. So the width is 9,
740 and we split into three parts:
741
742 The new carry flag (was B_n)
743 the stuff in B_n-1 .. B_0
744 the stuff in B_7 .. B_n+1
745
746 The new rotate is done mod 9, and given this,
747 for a rotation of n bits (mod 9) the new carry flag is
748 then located n bits from the MSB. The low part is
749 then shifted up cnt bits, and the high part is or'd
750 in. Using CAPS for new values, and lowercase for the
751 original values, this can be expressed as:
752
753 IF n > 0
754 1) CF <- b_(8-n)
755 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0
756 3) B_(n-1) <- cf
757 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1))
758 */
759 res = d;
760 if ((cnt = s % 9) != 0) {
761 /* extract the new CARRY FLAG. */
762 /* CF <- b_(8-n) */
763 cf = (d >> (8 - cnt)) & 0x1;
764
765 /* get the low stuff which rotated
766 into the range B_7 .. B_cnt */
767 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 */
768 /* note that the right hand side done by the mask */
769 res = (d << cnt) & 0xff;
770
771 /* now the high stuff which rotated around
772 into the positions B_cnt-2 .. B_0 */
773 /* B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */
774 /* shift it downward, 7-(n-2) = 9-n positions.
775 and mask off the result before or'ing in.
776 */
777 mask = (1 << (cnt - 1)) - 1;
778 res |= (d >> (9 - cnt)) & mask;
779
780 /* if the carry flag was set, or it in. */
781 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
782 /* B_(n-1) <- cf */
783 res |= 1 << (cnt - 1);
784 }
785 /* set the new carry flag, based on the variable "cf" */
786 CONDITIONAL_SET_FLAG(cf, F_CF);
787 /* OVERFLOW is set *IFF* cnt==1, then it is the
788 xor of CF and the most significant bit. Blecck. */
789 /* parenthesized this expression since it appears to
790 be causing OF to be misset */
791 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
792 F_OF);
793
794 }
795 return (u8)res;
796 }
797
798 /****************************************************************************
799 REMARKS:
800 Implements the RCL instruction and side effects.
801 ****************************************************************************/
rcl_word(u16 d,u8 s)802 u16 rcl_word(u16 d, u8 s)
803 {
804 unsigned int res, cnt, mask, cf;
805
806 res = d;
807 if ((cnt = s % 17) != 0) {
808 cf = (d >> (16 - cnt)) & 0x1;
809 res = (d << cnt) & 0xffff;
810 mask = (1 << (cnt - 1)) - 1;
811 res |= (d >> (17 - cnt)) & mask;
812 if (ACCESS_FLAG(F_CF)) {
813 res |= 1 << (cnt - 1);
814 }
815 CONDITIONAL_SET_FLAG(cf, F_CF);
816 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
817 F_OF);
818 }
819 return (u16)res;
820 }
821
822 /****************************************************************************
823 REMARKS:
824 Implements the RCL instruction and side effects.
825 ****************************************************************************/
rcl_long(u32 d,u8 s)826 u32 rcl_long(u32 d, u8 s)
827 {
828 u32 res, cnt, mask, cf;
829
830 res = d;
831 if ((cnt = s % 33) != 0) {
832 cf = (d >> (32 - cnt)) & 0x1;
833 res = (d << cnt) & 0xffffffff;
834 mask = (1 << (cnt - 1)) - 1;
835 res |= (d >> (33 - cnt)) & mask;
836 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
837 res |= 1 << (cnt - 1);
838 }
839 CONDITIONAL_SET_FLAG(cf, F_CF);
840 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
841 F_OF);
842 }
843 return res;
844 }
845
846 /****************************************************************************
847 REMARKS:
848 Implements the RCR instruction and side effects.
849 ****************************************************************************/
rcr_byte(u8 d,u8 s)850 u8 rcr_byte(u8 d, u8 s)
851 {
852 u32 res, cnt;
853 u32 mask, cf, ocf = 0;
854
855 /* rotate right through carry */
856 /*
857 s is the rotate distance. It varies from 0 - 8.
858 d is the byte object rotated.
859
860 have
861
862 CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
863
864 The new rotate is done mod 9, and given this,
865 for a rotation of n bits (mod 9) the new carry flag is
866 then located n bits from the LSB. The low part is
867 then shifted up cnt bits, and the high part is or'd
868 in. Using CAPS for new values, and lowercase for the
869 original values, this can be expressed as:
870
871 IF n > 0
872 1) CF <- b_(n-1)
873 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
874 3) B_(8-n) <- cf
875 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0)
876 */
877 res = d;
878 if ((cnt = s % 9) != 0) {
879 /* extract the new CARRY FLAG. */
880 /* CF <- b_(n-1) */
881 if (cnt == 1) {
882 cf = d & 0x1;
883 /* note hackery here. Access_flag(..) evaluates to either
884 0 if flag not set
885 non-zero if flag is set.
886 doing access_flag(..) != 0 casts that into either
887 0..1 in any representation of the flags register
888 (i.e. packed bit array or unpacked.)
889 */
890 ocf = ACCESS_FLAG(F_CF) != 0;
891 } else
892 cf = (d >> (cnt - 1)) & 0x1;
893
894 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */
895 /* note that the right hand side done by the mask
896 This is effectively done by shifting the
897 object to the right. The result must be masked,
898 in case the object came in and was treated
899 as a negative number. Needed??? */
900
901 mask = (1 << (8 - cnt)) - 1;
902 res = (d >> cnt) & mask;
903
904 /* now the high stuff which rotated around
905 into the positions B_cnt-2 .. B_0 */
906 /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */
907 /* shift it downward, 7-(n-2) = 9-n positions.
908 and mask off the result before or'ing in.
909 */
910 res |= (d << (9 - cnt));
911
912 /* if the carry flag was set, or it in. */
913 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
914 /* B_(8-n) <- cf */
915 res |= 1 << (8 - cnt);
916 }
917 /* set the new carry flag, based on the variable "cf" */
918 CONDITIONAL_SET_FLAG(cf, F_CF);
919 /* OVERFLOW is set *IFF* cnt==1, then it is the
920 xor of CF and the most significant bit. Blecck. */
921 /* parenthesized... */
922 if (cnt == 1) {
923 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
924 F_OF);
925 }
926 }
927 return (u8)res;
928 }
929
930 /****************************************************************************
931 REMARKS:
932 Implements the RCR instruction and side effects.
933 ****************************************************************************/
rcr_word(u16 d,u8 s)934 u16 rcr_word(u16 d, u8 s)
935 {
936 u32 res, cnt;
937 u32 mask, cf, ocf = 0;
938
939 /* rotate right through carry */
940 res = d;
941 if ((cnt = s % 17) != 0) {
942 if (cnt == 1) {
943 cf = d & 0x1;
944 ocf = ACCESS_FLAG(F_CF) != 0;
945 } else
946 cf = (d >> (cnt - 1)) & 0x1;
947 mask = (1 << (16 - cnt)) - 1;
948 res = (d >> cnt) & mask;
949 res |= (d << (17 - cnt));
950 if (ACCESS_FLAG(F_CF)) {
951 res |= 1 << (16 - cnt);
952 }
953 CONDITIONAL_SET_FLAG(cf, F_CF);
954 if (cnt == 1) {
955 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
956 F_OF);
957 }
958 }
959 return (u16)res;
960 }
961
962 /****************************************************************************
963 REMARKS:
964 Implements the RCR instruction and side effects.
965 ****************************************************************************/
rcr_long(u32 d,u8 s)966 u32 rcr_long(u32 d, u8 s)
967 {
968 u32 res, cnt;
969 u32 mask, cf, ocf = 0;
970
971 /* rotate right through carry */
972 res = d;
973 if ((cnt = s % 33) != 0) {
974 if (cnt == 1) {
975 cf = d & 0x1;
976 ocf = ACCESS_FLAG(F_CF) != 0;
977 } else
978 cf = (d >> (cnt - 1)) & 0x1;
979 mask = (1 << (32 - cnt)) - 1;
980 res = (d >> cnt) & mask;
981 if (cnt != 1)
982 res |= (d << (33 - cnt));
983 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
984 res |= 1 << (32 - cnt);
985 }
986 CONDITIONAL_SET_FLAG(cf, F_CF);
987 if (cnt == 1) {
988 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
989 F_OF);
990 }
991 }
992 return res;
993 }
994
995 /****************************************************************************
996 REMARKS:
997 Implements the ROL instruction and side effects.
998 ****************************************************************************/
rol_byte(u8 d,u8 s)999 u8 rol_byte(u8 d, u8 s)
1000 {
1001 unsigned int res, cnt, mask;
1002
1003 /* rotate left */
1004 /*
1005 s is the rotate distance. It varies from 0 - 8.
1006 d is the byte object rotated.
1007
1008 have
1009
1010 CF B_7 ... B_0
1011
1012 The new rotate is done mod 8.
1013 Much simpler than the "rcl" or "rcr" operations.
1014
1015 IF n > 0
1016 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0)
1017 2) B_(n-1) .. B_(0) <- b_(7) .. b_(8-n)
1018 */
1019 res = d;
1020 if ((cnt = s % 8) != 0) {
1021 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */
1022 res = (d << cnt);
1023
1024 /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */
1025 mask = (1 << cnt) - 1;
1026 res |= (d >> (8 - cnt)) & mask;
1027
1028 /* set the new carry flag, Note that it is the low order
1029 bit of the result!!! */
1030 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1031 /* OVERFLOW is set *IFF* s==1, then it is the
1032 xor of CF and the most significant bit. Blecck. */
1033 CONDITIONAL_SET_FLAG(s == 1 &&
1034 XOR2((res & 0x1) + ((res >> 6) & 0x2)),
1035 F_OF);
1036 } if (s != 0) {
1037 /* set the new carry flag, Note that it is the low order
1038 bit of the result!!! */
1039 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1040 }
1041 return (u8)res;
1042 }
1043
1044 /****************************************************************************
1045 REMARKS:
1046 Implements the ROL instruction and side effects.
1047 ****************************************************************************/
rol_word(u16 d,u8 s)1048 u16 rol_word(u16 d, u8 s)
1049 {
1050 unsigned int res, cnt, mask;
1051
1052 res = d;
1053 if ((cnt = s % 16) != 0) {
1054 res = (d << cnt);
1055 mask = (1 << cnt) - 1;
1056 res |= (d >> (16 - cnt)) & mask;
1057 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1058 CONDITIONAL_SET_FLAG(s == 1 &&
1059 XOR2((res & 0x1) + ((res >> 14) & 0x2)),
1060 F_OF);
1061 } if (s != 0) {
1062 /* set the new carry flag, Note that it is the low order
1063 bit of the result!!! */
1064 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1065 }
1066 return (u16)res;
1067 }
1068
1069 /****************************************************************************
1070 REMARKS:
1071 Implements the ROL instruction and side effects.
1072 ****************************************************************************/
rol_long(u32 d,u8 s)1073 u32 rol_long(u32 d, u8 s)
1074 {
1075 u32 res, cnt, mask;
1076
1077 res = d;
1078 if ((cnt = s % 32) != 0) {
1079 res = (d << cnt);
1080 mask = (1 << cnt) - 1;
1081 res |= (d >> (32 - cnt)) & mask;
1082 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1083 CONDITIONAL_SET_FLAG(s == 1 &&
1084 XOR2((res & 0x1) + ((res >> 30) & 0x2)),
1085 F_OF);
1086 } if (s != 0) {
1087 /* set the new carry flag, Note that it is the low order
1088 bit of the result!!! */
1089 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1090 }
1091 return res;
1092 }
1093
1094 /****************************************************************************
1095 REMARKS:
1096 Implements the ROR instruction and side effects.
1097 ****************************************************************************/
ror_byte(u8 d,u8 s)1098 u8 ror_byte(u8 d, u8 s)
1099 {
1100 unsigned int res, cnt, mask;
1101
1102 /* rotate right */
1103 /*
1104 s is the rotate distance. It varies from 0 - 8.
1105 d is the byte object rotated.
1106
1107 have
1108
1109 B_7 ... B_0
1110
1111 The rotate is done mod 8.
1112
1113 IF n > 0
1114 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
1115 2) B_(7) .. B_(8-n) <- b_(n-1) .. b_(0)
1116 */
1117 res = d;
1118 if ((cnt = s % 8) != 0) { /* not a typo, do nada if cnt==0 */
1119 /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */
1120 res = (d << (8 - cnt));
1121
1122 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */
1123 mask = (1 << (8 - cnt)) - 1;
1124 res |= (d >> (cnt)) & mask;
1125
1126 /* set the new carry flag, Note that it is the low order
1127 bit of the result!!! */
1128 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
1129 /* OVERFLOW is set *IFF* s==1, then it is the
1130 xor of the two most significant bits. Blecck. */
1131 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
1132 } else if (s != 0) {
1133 /* set the new carry flag, Note that it is the low order
1134 bit of the result!!! */
1135 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
1136 }
1137 return (u8)res;
1138 }
1139
1140 /****************************************************************************
1141 REMARKS:
1142 Implements the ROR instruction and side effects.
1143 ****************************************************************************/
ror_word(u16 d,u8 s)1144 u16 ror_word(u16 d, u8 s)
1145 {
1146 unsigned int res, cnt, mask;
1147
1148 res = d;
1149 if ((cnt = s % 16) != 0) {
1150 res = (d << (16 - cnt));
1151 mask = (1 << (16 - cnt)) - 1;
1152 res |= (d >> (cnt)) & mask;
1153 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
1154 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
1155 } else if (s != 0) {
1156 /* set the new carry flag, Note that it is the low order
1157 bit of the result!!! */
1158 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
1159 }
1160 return (u16)res;
1161 }
1162
1163 /****************************************************************************
1164 REMARKS:
1165 Implements the ROR instruction and side effects.
1166 ****************************************************************************/
ror_long(u32 d,u8 s)1167 u32 ror_long(u32 d, u8 s)
1168 {
1169 u32 res, cnt, mask;
1170
1171 res = d;
1172 if ((cnt = s % 32) != 0) {
1173 res = (d << (32 - cnt));
1174 mask = (1 << (32 - cnt)) - 1;
1175 res |= (d >> (cnt)) & mask;
1176 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
1177 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
1178 } else if (s != 0) {
1179 /* set the new carry flag, Note that it is the low order
1180 bit of the result!!! */
1181 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
1182 }
1183 return res;
1184 }
1185
1186 /****************************************************************************
1187 REMARKS:
1188 Implements the SHL instruction and side effects.
1189 ****************************************************************************/
shl_byte(u8 d,u8 s)1190 u8 shl_byte(u8 d, u8 s)
1191 {
1192 unsigned int cnt, res, cf;
1193
1194 if (s < 8) {
1195 cnt = s % 8;
1196
1197 /* last bit shifted out goes into carry flag */
1198 if (cnt > 0) {
1199 res = d << cnt;
1200 cf = d & (1 << (8 - cnt));
1201 CONDITIONAL_SET_FLAG(cf, F_CF);
1202 set_szp_flags_8((u8)res);
1203 } else {
1204 res = (u8) d;
1205 }
1206
1207 if (cnt == 1) {
1208 /* Needs simplification. */
1209 CONDITIONAL_SET_FLAG(
1210 (((res & 0x80) == 0x80) ^
1211 (ACCESS_FLAG(F_CF) != 0)),
1212 /* was (M.x86.R_FLG&F_CF)==F_CF)), */
1213 F_OF);
1214 } else {
1215 CLEAR_FLAG(F_OF);
1216 }
1217 } else {
1218 res = 0;
1219 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80, F_CF);
1220 CLEAR_FLAG(F_OF);
1221 CLEAR_FLAG(F_SF);
1222 SET_FLAG(F_PF);
1223 SET_FLAG(F_ZF);
1224 }
1225 return (u8)res;
1226 }
1227
1228 /****************************************************************************
1229 REMARKS:
1230 Implements the SHL instruction and side effects.
1231 ****************************************************************************/
shl_word(u16 d,u8 s)1232 u16 shl_word(u16 d, u8 s)
1233 {
1234 unsigned int cnt, res, cf;
1235
1236 if (s < 16) {
1237 cnt = s % 16;
1238 if (cnt > 0) {
1239 res = d << cnt;
1240 cf = d & (1 << (16 - cnt));
1241 CONDITIONAL_SET_FLAG(cf, F_CF);
1242 set_szp_flags_16((u16)res);
1243 } else {
1244 res = (u16) d;
1245 }
1246
1247 if (cnt == 1) {
1248 CONDITIONAL_SET_FLAG(
1249 (((res & 0x8000) == 0x8000) ^
1250 (ACCESS_FLAG(F_CF) != 0)),
1251 F_OF);
1252 } else {
1253 CLEAR_FLAG(F_OF);
1254 }
1255 } else {
1256 res = 0;
1257 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
1258 CLEAR_FLAG(F_OF);
1259 CLEAR_FLAG(F_SF);
1260 SET_FLAG(F_PF);
1261 SET_FLAG(F_ZF);
1262 }
1263 return (u16)res;
1264 }
1265
1266 /****************************************************************************
1267 REMARKS:
1268 Implements the SHL instruction and side effects.
1269 ****************************************************************************/
shl_long(u32 d,u8 s)1270 u32 shl_long(u32 d, u8 s)
1271 {
1272 unsigned int cnt, res, cf;
1273
1274 if (s < 32) {
1275 cnt = s % 32;
1276 if (cnt > 0) {
1277 res = d << cnt;
1278 cf = d & (1 << (32 - cnt));
1279 CONDITIONAL_SET_FLAG(cf, F_CF);
1280 set_szp_flags_32((u32)res);
1281 } else {
1282 res = d;
1283 }
1284 if (cnt == 1) {
1285 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
1286 (ACCESS_FLAG(F_CF) != 0)), F_OF);
1287 } else {
1288 CLEAR_FLAG(F_OF);
1289 }
1290 } else {
1291 res = 0;
1292 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
1293 CLEAR_FLAG(F_OF);
1294 CLEAR_FLAG(F_SF);
1295 SET_FLAG(F_PF);
1296 SET_FLAG(F_ZF);
1297 }
1298 return res;
1299 }
1300
1301 /****************************************************************************
1302 REMARKS:
1303 Implements the SHR instruction and side effects.
1304 ****************************************************************************/
shr_byte(u8 d,u8 s)1305 u8 shr_byte(u8 d, u8 s)
1306 {
1307 unsigned int cnt, res, cf;
1308
1309 if (s < 8) {
1310 cnt = s % 8;
1311 if (cnt > 0) {
1312 cf = d & (1 << (cnt - 1));
1313 res = d >> cnt;
1314 CONDITIONAL_SET_FLAG(cf, F_CF);
1315 set_szp_flags_8((u8)res);
1316 } else {
1317 res = (u8) d;
1318 }
1319
1320 if (cnt == 1) {
1321 CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
1322 } else {
1323 CLEAR_FLAG(F_OF);
1324 }
1325 } else {
1326 res = 0;
1327 CONDITIONAL_SET_FLAG((d >> (s-1)) & 0x1, F_CF);
1328 CLEAR_FLAG(F_OF);
1329 CLEAR_FLAG(F_SF);
1330 SET_FLAG(F_PF);
1331 SET_FLAG(F_ZF);
1332 }
1333 return (u8)res;
1334 }
1335
1336 /****************************************************************************
1337 REMARKS:
1338 Implements the SHR instruction and side effects.
1339 ****************************************************************************/
shr_word(u16 d,u8 s)1340 u16 shr_word(u16 d, u8 s)
1341 {
1342 unsigned int cnt, res, cf;
1343
1344 if (s < 16) {
1345 cnt = s % 16;
1346 if (cnt > 0) {
1347 cf = d & (1 << (cnt - 1));
1348 res = d >> cnt;
1349 CONDITIONAL_SET_FLAG(cf, F_CF);
1350 set_szp_flags_16((u16)res);
1351 } else {
1352 res = d;
1353 }
1354
1355 if (cnt == 1) {
1356 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1357 } else {
1358 CLEAR_FLAG(F_OF);
1359 }
1360 } else {
1361 res = 0;
1362 CLEAR_FLAG(F_CF);
1363 CLEAR_FLAG(F_OF);
1364 SET_FLAG(F_ZF);
1365 CLEAR_FLAG(F_SF);
1366 CLEAR_FLAG(F_PF);
1367 }
1368 return (u16)res;
1369 }
1370
1371 /****************************************************************************
1372 REMARKS:
1373 Implements the SHR instruction and side effects.
1374 ****************************************************************************/
shr_long(u32 d,u8 s)1375 u32 shr_long(u32 d, u8 s)
1376 {
1377 unsigned int cnt, res, cf;
1378
1379 if (s < 32) {
1380 cnt = s % 32;
1381 if (cnt > 0) {
1382 cf = d & (1 << (cnt - 1));
1383 res = d >> cnt;
1384 CONDITIONAL_SET_FLAG(cf, F_CF);
1385 set_szp_flags_32((u32)res);
1386 } else {
1387 res = d;
1388 }
1389 if (cnt == 1) {
1390 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1391 } else {
1392 CLEAR_FLAG(F_OF);
1393 }
1394 } else {
1395 res = 0;
1396 CLEAR_FLAG(F_CF);
1397 CLEAR_FLAG(F_OF);
1398 SET_FLAG(F_ZF);
1399 CLEAR_FLAG(F_SF);
1400 CLEAR_FLAG(F_PF);
1401 }
1402 return res;
1403 }
1404
1405 /****************************************************************************
1406 REMARKS:
1407 Implements the SAR instruction and side effects.
1408 ****************************************************************************/
sar_byte(u8 d,u8 s)1409 u8 sar_byte(u8 d, u8 s)
1410 {
1411 unsigned int cnt, res, cf, mask, sf;
1412
1413 res = d;
1414 sf = d & 0x80;
1415 cnt = s % 8;
1416 if (cnt > 0 && cnt < 8) {
1417 mask = (1 << (8 - cnt)) - 1;
1418 cf = d & (1 << (cnt - 1));
1419 res = (d >> cnt) & mask;
1420 CONDITIONAL_SET_FLAG(cf, F_CF);
1421 if (sf) {
1422 res |= ~mask;
1423 }
1424 set_szp_flags_8((u8)res);
1425 } else if (cnt >= 8) {
1426 if (sf) {
1427 res = 0xff;
1428 SET_FLAG(F_CF);
1429 CLEAR_FLAG(F_ZF);
1430 SET_FLAG(F_SF);
1431 SET_FLAG(F_PF);
1432 } else {
1433 res = 0;
1434 CLEAR_FLAG(F_CF);
1435 SET_FLAG(F_ZF);
1436 CLEAR_FLAG(F_SF);
1437 CLEAR_FLAG(F_PF);
1438 }
1439 }
1440 return (u8)res;
1441 }
1442
1443 /****************************************************************************
1444 REMARKS:
1445 Implements the SAR instruction and side effects.
1446 ****************************************************************************/
sar_word(u16 d,u8 s)1447 u16 sar_word(u16 d, u8 s)
1448 {
1449 unsigned int cnt, res, cf, mask, sf;
1450
1451 sf = d & 0x8000;
1452 cnt = s % 16;
1453 res = d;
1454 if (cnt > 0 && cnt < 16) {
1455 mask = (1 << (16 - cnt)) - 1;
1456 cf = d & (1 << (cnt - 1));
1457 res = (d >> cnt) & mask;
1458 CONDITIONAL_SET_FLAG(cf, F_CF);
1459 if (sf) {
1460 res |= ~mask;
1461 }
1462 set_szp_flags_16((u16)res);
1463 } else if (cnt >= 16) {
1464 if (sf) {
1465 res = 0xffff;
1466 SET_FLAG(F_CF);
1467 CLEAR_FLAG(F_ZF);
1468 SET_FLAG(F_SF);
1469 SET_FLAG(F_PF);
1470 } else {
1471 res = 0;
1472 CLEAR_FLAG(F_CF);
1473 SET_FLAG(F_ZF);
1474 CLEAR_FLAG(F_SF);
1475 CLEAR_FLAG(F_PF);
1476 }
1477 }
1478 return (u16)res;
1479 }
1480
1481 /****************************************************************************
1482 REMARKS:
1483 Implements the SAR instruction and side effects.
1484 ****************************************************************************/
sar_long(u32 d,u8 s)1485 u32 sar_long(u32 d, u8 s)
1486 {
1487 u32 cnt, res, cf, mask, sf;
1488
1489 sf = d & 0x80000000;
1490 cnt = s % 32;
1491 res = d;
1492 if (cnt > 0 && cnt < 32) {
1493 mask = (1 << (32 - cnt)) - 1;
1494 cf = d & (1 << (cnt - 1));
1495 res = (d >> cnt) & mask;
1496 CONDITIONAL_SET_FLAG(cf, F_CF);
1497 if (sf) {
1498 res |= ~mask;
1499 }
1500 set_szp_flags_32(res);
1501 } else if (cnt >= 32) {
1502 if (sf) {
1503 res = 0xffffffff;
1504 SET_FLAG(F_CF);
1505 CLEAR_FLAG(F_ZF);
1506 SET_FLAG(F_SF);
1507 SET_FLAG(F_PF);
1508 } else {
1509 res = 0;
1510 CLEAR_FLAG(F_CF);
1511 SET_FLAG(F_ZF);
1512 CLEAR_FLAG(F_SF);
1513 CLEAR_FLAG(F_PF);
1514 }
1515 }
1516 return res;
1517 }
1518
1519 /****************************************************************************
1520 REMARKS:
1521 Implements the SHLD instruction and side effects.
1522 ****************************************************************************/
shld_word(u16 d,u16 fill,u8 s)1523 u16 shld_word (u16 d, u16 fill, u8 s)
1524 {
1525 unsigned int cnt, res, cf;
1526
1527 if (s < 16) {
1528 cnt = s % 16;
1529 if (cnt > 0) {
1530 res = (d << cnt) | (fill >> (16-cnt));
1531 cf = d & (1 << (16 - cnt));
1532 CONDITIONAL_SET_FLAG(cf, F_CF);
1533 set_szp_flags_16((u16)res);
1534 } else {
1535 res = d;
1536 }
1537 if (cnt == 1) {
1538 CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
1539 (ACCESS_FLAG(F_CF) != 0)), F_OF);
1540 } else {
1541 CLEAR_FLAG(F_OF);
1542 }
1543 } else {
1544 res = 0;
1545 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
1546 CLEAR_FLAG(F_OF);
1547 CLEAR_FLAG(F_SF);
1548 SET_FLAG(F_PF);
1549 SET_FLAG(F_ZF);
1550 }
1551 return (u16)res;
1552 }
1553
1554 /****************************************************************************
1555 REMARKS:
1556 Implements the SHLD instruction and side effects.
1557 ****************************************************************************/
shld_long(u32 d,u32 fill,u8 s)1558 u32 shld_long (u32 d, u32 fill, u8 s)
1559 {
1560 unsigned int cnt, res, cf;
1561
1562 if (s < 32) {
1563 cnt = s % 32;
1564 if (cnt > 0) {
1565 res = (d << cnt) | (fill >> (32-cnt));
1566 cf = d & (1 << (32 - cnt));
1567 CONDITIONAL_SET_FLAG(cf, F_CF);
1568 set_szp_flags_32((u32)res);
1569 } else {
1570 res = d;
1571 }
1572 if (cnt == 1) {
1573 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
1574 (ACCESS_FLAG(F_CF) != 0)), F_OF);
1575 } else {
1576 CLEAR_FLAG(F_OF);
1577 }
1578 } else {
1579 res = 0;
1580 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
1581 CLEAR_FLAG(F_OF);
1582 CLEAR_FLAG(F_SF);
1583 SET_FLAG(F_PF);
1584 SET_FLAG(F_ZF);
1585 }
1586 return res;
1587 }
1588
1589 /****************************************************************************
1590 REMARKS:
1591 Implements the SHRD instruction and side effects.
1592 ****************************************************************************/
shrd_word(u16 d,u16 fill,u8 s)1593 u16 shrd_word (u16 d, u16 fill, u8 s)
1594 {
1595 unsigned int cnt, res, cf;
1596
1597 if (s < 16) {
1598 cnt = s % 16;
1599 if (cnt > 0) {
1600 cf = d & (1 << (cnt - 1));
1601 res = (d >> cnt) | (fill << (16 - cnt));
1602 CONDITIONAL_SET_FLAG(cf, F_CF);
1603 set_szp_flags_16((u16)res);
1604 } else {
1605 res = d;
1606 }
1607
1608 if (cnt == 1) {
1609 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1610 } else {
1611 CLEAR_FLAG(F_OF);
1612 }
1613 } else {
1614 res = 0;
1615 CLEAR_FLAG(F_CF);
1616 CLEAR_FLAG(F_OF);
1617 SET_FLAG(F_ZF);
1618 CLEAR_FLAG(F_SF);
1619 CLEAR_FLAG(F_PF);
1620 }
1621 return (u16)res;
1622 }
1623
1624 /****************************************************************************
1625 REMARKS:
1626 Implements the SHRD instruction and side effects.
1627 ****************************************************************************/
shrd_long(u32 d,u32 fill,u8 s)1628 u32 shrd_long (u32 d, u32 fill, u8 s)
1629 {
1630 unsigned int cnt, res, cf;
1631
1632 if (s < 32) {
1633 cnt = s % 32;
1634 if (cnt > 0) {
1635 cf = d & (1 << (cnt - 1));
1636 res = (d >> cnt) | (fill << (32 - cnt));
1637 CONDITIONAL_SET_FLAG(cf, F_CF);
1638 set_szp_flags_32((u32)res);
1639 } else {
1640 res = d;
1641 }
1642 if (cnt == 1) {
1643 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1644 } else {
1645 CLEAR_FLAG(F_OF);
1646 }
1647 } else {
1648 res = 0;
1649 CLEAR_FLAG(F_CF);
1650 CLEAR_FLAG(F_OF);
1651 SET_FLAG(F_ZF);
1652 CLEAR_FLAG(F_SF);
1653 CLEAR_FLAG(F_PF);
1654 }
1655 return res;
1656 }
1657
1658 /****************************************************************************
1659 REMARKS:
1660 Implements the SBB instruction and side effects.
1661 ****************************************************************************/
sbb_byte(u8 d,u8 s)1662 u8 sbb_byte(u8 d, u8 s)
1663 {
1664 u32 res; /* all operands in native machine order */
1665 u32 bc;
1666
1667 if (ACCESS_FLAG(F_CF))
1668 res = d - s - 1;
1669 else
1670 res = d - s;
1671 set_szp_flags_8((u8)res);
1672
1673 /* calculate the borrow chain. See note at top */
1674 bc = (res & (~d | s)) | (~d & s);
1675 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
1676 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
1677 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1678 return (u8)res;
1679 }
1680
1681 /****************************************************************************
1682 REMARKS:
1683 Implements the SBB instruction and side effects.
1684 ****************************************************************************/
sbb_word(u16 d,u16 s)1685 u16 sbb_word(u16 d, u16 s)
1686 {
1687 u32 res; /* all operands in native machine order */
1688 u32 bc;
1689
1690 if (ACCESS_FLAG(F_CF))
1691 res = d - s - 1;
1692 else
1693 res = d - s;
1694 set_szp_flags_16((u16)res);
1695
1696 /* calculate the borrow chain. See note at top */
1697 bc = (res & (~d | s)) | (~d & s);
1698 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
1699 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
1700 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1701 return (u16)res;
1702 }
1703
1704 /****************************************************************************
1705 REMARKS:
1706 Implements the SBB instruction and side effects.
1707 ****************************************************************************/
sbb_long(u32 d,u32 s)1708 u32 sbb_long(u32 d, u32 s)
1709 {
1710 u32 res; /* all operands in native machine order */
1711 u32 bc;
1712
1713 if (ACCESS_FLAG(F_CF))
1714 res = d - s - 1;
1715 else
1716 res = d - s;
1717
1718 set_szp_flags_32(res);
1719
1720 /* calculate the borrow chain. See note at top */
1721 bc = (res & (~d | s)) | (~d & s);
1722 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
1723 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
1724 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1725 return res;
1726 }
1727
1728 /****************************************************************************
1729 REMARKS:
1730 Implements the SUB instruction and side effects.
1731 ****************************************************************************/
sub_byte(u8 d,u8 s)1732 u8 sub_byte(u8 d, u8 s)
1733 {
1734 u32 res; /* all operands in native machine order */
1735 u32 bc;
1736
1737 res = d - s;
1738 set_szp_flags_8((u8)res);
1739
1740 /* calculate the borrow chain. See note at top */
1741 bc = (res & (~d | s)) | (~d & s);
1742 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
1743 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
1744 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1745 return (u8)res;
1746 }
1747
1748 /****************************************************************************
1749 REMARKS:
1750 Implements the SUB instruction and side effects.
1751 ****************************************************************************/
sub_word(u16 d,u16 s)1752 u16 sub_word(u16 d, u16 s)
1753 {
1754 u32 res; /* all operands in native machine order */
1755 u32 bc;
1756
1757 res = d - s;
1758 set_szp_flags_16((u16)res);
1759
1760 /* calculate the borrow chain. See note at top */
1761 bc = (res & (~d | s)) | (~d & s);
1762 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
1763 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
1764 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1765 return (u16)res;
1766 }
1767
1768 /****************************************************************************
1769 REMARKS:
1770 Implements the SUB instruction and side effects.
1771 ****************************************************************************/
sub_long(u32 d,u32 s)1772 u32 sub_long(u32 d, u32 s)
1773 {
1774 u32 res; /* all operands in native machine order */
1775 u32 bc;
1776
1777 res = d - s;
1778 set_szp_flags_32(res);
1779
1780 /* calculate the borrow chain. See note at top */
1781 bc = (res & (~d | s)) | (~d & s);
1782 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
1783 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
1784 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1785 return res;
1786 }
1787
1788 /****************************************************************************
1789 REMARKS:
1790 Implements the TEST instruction and side effects.
1791 ****************************************************************************/
test_byte(u8 d,u8 s)1792 void test_byte(u8 d, u8 s)
1793 {
1794 u32 res; /* all operands in native machine order */
1795
1796 res = d & s;
1797
1798 CLEAR_FLAG(F_OF);
1799 set_szp_flags_8((u8)res);
1800 /* AF == dont care */
1801 CLEAR_FLAG(F_CF);
1802 }
1803
1804 /****************************************************************************
1805 REMARKS:
1806 Implements the TEST instruction and side effects.
1807 ****************************************************************************/
test_word(u16 d,u16 s)1808 void test_word(u16 d, u16 s)
1809 {
1810 u32 res; /* all operands in native machine order */
1811
1812 res = d & s;
1813
1814 CLEAR_FLAG(F_OF);
1815 set_szp_flags_16((u16)res);
1816 /* AF == dont care */
1817 CLEAR_FLAG(F_CF);
1818 }
1819
1820 /****************************************************************************
1821 REMARKS:
1822 Implements the TEST instruction and side effects.
1823 ****************************************************************************/
test_long(u32 d,u32 s)1824 void test_long(u32 d, u32 s)
1825 {
1826 u32 res; /* all operands in native machine order */
1827
1828 res = d & s;
1829
1830 CLEAR_FLAG(F_OF);
1831 set_szp_flags_32(res);
1832 /* AF == dont care */
1833 CLEAR_FLAG(F_CF);
1834 }
1835
1836 /****************************************************************************
1837 REMARKS:
1838 Implements the XOR instruction and side effects.
1839 ****************************************************************************/
xor_byte(u8 d,u8 s)1840 u8 xor_byte(u8 d, u8 s)
1841 {
1842 u8 res; /* all operands in native machine order */
1843
1844 res = d ^ s;
1845 no_carry_byte_side_eff(res);
1846 return res;
1847 }
1848
1849 /****************************************************************************
1850 REMARKS:
1851 Implements the XOR instruction and side effects.
1852 ****************************************************************************/
xor_word(u16 d,u16 s)1853 u16 xor_word(u16 d, u16 s)
1854 {
1855 u16 res; /* all operands in native machine order */
1856
1857 res = d ^ s;
1858 no_carry_word_side_eff(res);
1859 return res;
1860 }
1861
1862 /****************************************************************************
1863 REMARKS:
1864 Implements the XOR instruction and side effects.
1865 ****************************************************************************/
xor_long(u32 d,u32 s)1866 u32 xor_long(u32 d, u32 s)
1867 {
1868 u32 res; /* all operands in native machine order */
1869
1870 res = d ^ s;
1871 no_carry_long_side_eff(res);
1872 return res;
1873 }
1874
1875 /****************************************************************************
1876 REMARKS:
1877 Implements the IMUL instruction and side effects.
1878 ****************************************************************************/
imul_byte(u8 s)1879 void imul_byte(u8 s)
1880 {
1881 s16 res = (s16)((s8)M.x86.R_AL * (s8)s);
1882
1883 M.x86.R_AX = res;
1884 if (((M.x86.R_AL & 0x80) == 0 && M.x86.R_AH == 0x00) ||
1885 ((M.x86.R_AL & 0x80) != 0 && M.x86.R_AH == 0xFF)) {
1886 CLEAR_FLAG(F_CF);
1887 CLEAR_FLAG(F_OF);
1888 } else {
1889 SET_FLAG(F_CF);
1890 SET_FLAG(F_OF);
1891 }
1892 }
1893
1894 /****************************************************************************
1895 REMARKS:
1896 Implements the IMUL instruction and side effects.
1897 ****************************************************************************/
imul_word(u16 s)1898 void imul_word(u16 s)
1899 {
1900 s32 res = (s16)M.x86.R_AX * (s16)s;
1901
1902 M.x86.R_AX = (u16)res;
1903 M.x86.R_DX = (u16)(res >> 16);
1904 if (((M.x86.R_AX & 0x8000) == 0 && M.x86.R_DX == 0x0000) ||
1905 ((M.x86.R_AX & 0x8000) != 0 && M.x86.R_DX == 0xFFFF)) {
1906 CLEAR_FLAG(F_CF);
1907 CLEAR_FLAG(F_OF);
1908 } else {
1909 SET_FLAG(F_CF);
1910 SET_FLAG(F_OF);
1911 }
1912 }
1913
1914 /****************************************************************************
1915 REMARKS:
1916 Implements the IMUL instruction and side effects.
1917 ****************************************************************************/
imul_long_direct(u32 * res_lo,u32 * res_hi,u32 d,u32 s)1918 void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s)
1919 {
1920 #ifdef __HAS_LONG_LONG__
1921 s64 res = (s32)d * (s32)s;
1922
1923 *res_lo = (u32)res;
1924 *res_hi = (u32)(res >> 32);
1925 #else
1926 u32 d_lo,d_hi,d_sign;
1927 u32 s_lo,s_hi,s_sign;
1928 u32 rlo_lo,rlo_hi,rhi_lo;
1929
1930 if ((d_sign = d & 0x80000000) != 0)
1931 d = -d;
1932 d_lo = d & 0xFFFF;
1933 d_hi = d >> 16;
1934 if ((s_sign = s & 0x80000000) != 0)
1935 s = -s;
1936 s_lo = s & 0xFFFF;
1937 s_hi = s >> 16;
1938 rlo_lo = d_lo * s_lo;
1939 rlo_hi = (d_hi * s_lo + d_lo * s_hi) + (rlo_lo >> 16);
1940 rhi_lo = d_hi * s_hi + (rlo_hi >> 16);
1941 *res_lo = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
1942 *res_hi = rhi_lo;
1943 if (d_sign != s_sign) {
1944 d = ~*res_lo;
1945 s = (((d & 0xFFFF) + 1) >> 16) + (d >> 16);
1946 *res_lo = ~*res_lo+1;
1947 *res_hi = ~*res_hi+(s >> 16);
1948 }
1949 #endif
1950 }
1951
1952 /****************************************************************************
1953 REMARKS:
1954 Implements the IMUL instruction and side effects.
1955 ****************************************************************************/
imul_long(u32 s)1956 void imul_long(u32 s)
1957 {
1958 imul_long_direct(&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s);
1959 if (((M.x86.R_EAX & 0x80000000) == 0 && M.x86.R_EDX == 0x00000000) ||
1960 ((M.x86.R_EAX & 0x80000000) != 0 && M.x86.R_EDX == 0xFFFFFFFF)) {
1961 CLEAR_FLAG(F_CF);
1962 CLEAR_FLAG(F_OF);
1963 } else {
1964 SET_FLAG(F_CF);
1965 SET_FLAG(F_OF);
1966 }
1967 }
1968
1969 /****************************************************************************
1970 REMARKS:
1971 Implements the MUL instruction and side effects.
1972 ****************************************************************************/
mul_byte(u8 s)1973 void mul_byte(u8 s)
1974 {
1975 u16 res = (u16)(M.x86.R_AL * s);
1976
1977 M.x86.R_AX = res;
1978 if (M.x86.R_AH == 0) {
1979 CLEAR_FLAG(F_CF);
1980 CLEAR_FLAG(F_OF);
1981 } else {
1982 SET_FLAG(F_CF);
1983 SET_FLAG(F_OF);
1984 }
1985 }
1986
1987 /****************************************************************************
1988 REMARKS:
1989 Implements the MUL instruction and side effects.
1990 ****************************************************************************/
mul_word(u16 s)1991 void mul_word(u16 s)
1992 {
1993 u32 res = M.x86.R_AX * s;
1994
1995 M.x86.R_AX = (u16)res;
1996 M.x86.R_DX = (u16)(res >> 16);
1997 if (M.x86.R_DX == 0) {
1998 CLEAR_FLAG(F_CF);
1999 CLEAR_FLAG(F_OF);
2000 } else {
2001 SET_FLAG(F_CF);
2002 SET_FLAG(F_OF);
2003 }
2004 }
2005
2006 /****************************************************************************
2007 REMARKS:
2008 Implements the MUL instruction and side effects.
2009 ****************************************************************************/
mul_long(u32 s)2010 void mul_long(u32 s)
2011 {
2012 #ifdef __HAS_LONG_LONG__
2013 u64 res = (u32)M.x86.R_EAX * (u32)s;
2014
2015 M.x86.R_EAX = (u32)res;
2016 M.x86.R_EDX = (u32)(res >> 32);
2017 #else
2018 u32 a,a_lo,a_hi;
2019 u32 s_lo,s_hi;
2020 u32 rlo_lo,rlo_hi,rhi_lo;
2021
2022 a = M.x86.R_EAX;
2023 a_lo = a & 0xFFFF;
2024 a_hi = a >> 16;
2025 s_lo = s & 0xFFFF;
2026 s_hi = s >> 16;
2027 rlo_lo = a_lo * s_lo;
2028 rlo_hi = (a_hi * s_lo + a_lo * s_hi) + (rlo_lo >> 16);
2029 rhi_lo = a_hi * s_hi + (rlo_hi >> 16);
2030 M.x86.R_EAX = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
2031 M.x86.R_EDX = rhi_lo;
2032 #endif
2033 if (M.x86.R_EDX == 0) {
2034 CLEAR_FLAG(F_CF);
2035 CLEAR_FLAG(F_OF);
2036 } else {
2037 SET_FLAG(F_CF);
2038 SET_FLAG(F_OF);
2039 }
2040 }
2041
2042 /****************************************************************************
2043 REMARKS:
2044 Implements the IDIV instruction and side effects.
2045 ****************************************************************************/
idiv_byte(u8 s)2046 void idiv_byte(u8 s)
2047 {
2048 s32 dvd, div, mod;
2049
2050 dvd = (s16)M.x86.R_AX;
2051 if (s == 0) {
2052 x86emu_intr_raise(0);
2053 return;
2054 }
2055 div = dvd / (s8)s;
2056 mod = dvd % (s8)s;
2057 if (abs(div) > 0x7f) {
2058 x86emu_intr_raise(0);
2059 return;
2060 }
2061 M.x86.R_AL = (s8) div;
2062 M.x86.R_AH = (s8) mod;
2063 }
2064
2065 /****************************************************************************
2066 REMARKS:
2067 Implements the IDIV instruction and side effects.
2068 ****************************************************************************/
idiv_word(u16 s)2069 void idiv_word(u16 s)
2070 {
2071 s32 dvd, div, mod;
2072
2073 dvd = (((s32)M.x86.R_DX) << 16) | M.x86.R_AX;
2074 if (s == 0) {
2075 x86emu_intr_raise(0);
2076 return;
2077 }
2078 div = dvd / (s16)s;
2079 mod = dvd % (s16)s;
2080 if (abs(div) > 0x7fff) {
2081 x86emu_intr_raise(0);
2082 return;
2083 }
2084 CLEAR_FLAG(F_CF);
2085 CLEAR_FLAG(F_SF);
2086 CONDITIONAL_SET_FLAG(div == 0, F_ZF);
2087 set_parity_flag(mod);
2088
2089 M.x86.R_AX = (u16)div;
2090 M.x86.R_DX = (u16)mod;
2091 }
2092
2093 /****************************************************************************
2094 REMARKS:
2095 Implements the IDIV instruction and side effects.
2096 ****************************************************************************/
idiv_long(u32 s)2097 void idiv_long(u32 s)
2098 {
2099 #ifdef __HAS_LONG_LONG__
2100 s64 dvd, div, mod;
2101
2102 dvd = (((s64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
2103 if (s == 0) {
2104 x86emu_intr_raise(0);
2105 return;
2106 }
2107 div = dvd / (s32)s;
2108 mod = dvd % (s32)s;
2109 if (abs(div) > 0x7fffffff) {
2110 x86emu_intr_raise(0);
2111 return;
2112 }
2113 #else
2114 s32 div = 0, mod;
2115 s32 h_dvd = M.x86.R_EDX;
2116 u32 l_dvd = M.x86.R_EAX;
2117 u32 abs_s = s & 0x7FFFFFFF;
2118 u32 abs_h_dvd = h_dvd & 0x7FFFFFFF;
2119 u32 h_s = abs_s >> 1;
2120 u32 l_s = abs_s << 31;
2121 int counter = 31;
2122 int carry;
2123
2124 if (s == 0) {
2125 x86emu_intr_raise(0);
2126 return;
2127 }
2128 do {
2129 div <<= 1;
2130 carry = (l_dvd >= l_s) ? 0 : 1;
2131
2132 if (abs_h_dvd < (h_s + carry)) {
2133 h_s >>= 1;
2134 l_s = abs_s << (--counter);
2135 continue;
2136 } else {
2137 abs_h_dvd -= (h_s + carry);
2138 l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
2139 : (l_dvd - l_s);
2140 h_s >>= 1;
2141 l_s = abs_s << (--counter);
2142 div |= 1;
2143 continue;
2144 }
2145
2146 } while (counter > -1);
2147 /* overflow */
2148 if (abs_h_dvd || (l_dvd > abs_s)) {
2149 x86emu_intr_raise(0);
2150 return;
2151 }
2152 /* sign */
2153 div |= ((h_dvd & 0x10000000) ^ (s & 0x10000000));
2154 mod = l_dvd;
2155
2156 #endif
2157 CLEAR_FLAG(F_CF);
2158 CLEAR_FLAG(F_AF);
2159 CLEAR_FLAG(F_SF);
2160 SET_FLAG(F_ZF);
2161 set_parity_flag(mod);
2162
2163 M.x86.R_EAX = (u32)div;
2164 M.x86.R_EDX = (u32)mod;
2165 }
2166
2167 /****************************************************************************
2168 REMARKS:
2169 Implements the DIV instruction and side effects.
2170 ****************************************************************************/
div_byte(u8 s)2171 void div_byte(u8 s)
2172 {
2173 u32 dvd, div, mod;
2174
2175 dvd = M.x86.R_AX;
2176 if (s == 0) {
2177 x86emu_intr_raise(0);
2178 return;
2179 }
2180 div = dvd / (u8)s;
2181 mod = dvd % (u8)s;
2182 if (abs(div) > 0xff) {
2183 x86emu_intr_raise(0);
2184 return;
2185 }
2186 M.x86.R_AL = (u8)div;
2187 M.x86.R_AH = (u8)mod;
2188 }
2189
2190 /****************************************************************************
2191 REMARKS:
2192 Implements the DIV instruction and side effects.
2193 ****************************************************************************/
div_word(u16 s)2194 void div_word(u16 s)
2195 {
2196 u32 dvd, div, mod;
2197
2198 dvd = (((u32)M.x86.R_DX) << 16) | M.x86.R_AX;
2199 if (s == 0) {
2200 x86emu_intr_raise(0);
2201 return;
2202 }
2203 div = dvd / (u16)s;
2204 mod = dvd % (u16)s;
2205 if (abs(div) > 0xffff) {
2206 x86emu_intr_raise(0);
2207 return;
2208 }
2209 CLEAR_FLAG(F_CF);
2210 CLEAR_FLAG(F_SF);
2211 CONDITIONAL_SET_FLAG(div == 0, F_ZF);
2212 set_parity_flag(mod);
2213
2214 M.x86.R_AX = (u16)div;
2215 M.x86.R_DX = (u16)mod;
2216 }
2217
2218 /****************************************************************************
2219 REMARKS:
2220 Implements the DIV instruction and side effects.
2221 ****************************************************************************/
div_long(u32 s)2222 void div_long(u32 s)
2223 {
2224 #ifdef __HAS_LONG_LONG__
2225 u64 dvd, div, mod;
2226
2227 dvd = (((u64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
2228 if (s == 0) {
2229 x86emu_intr_raise(0);
2230 return;
2231 }
2232 div = dvd / (u32)s;
2233 mod = dvd % (u32)s;
2234 if (abs(div) > 0xffffffff) {
2235 x86emu_intr_raise(0);
2236 return;
2237 }
2238 #else
2239 s32 div = 0, mod;
2240 s32 h_dvd = M.x86.R_EDX;
2241 u32 l_dvd = M.x86.R_EAX;
2242
2243 u32 h_s = s;
2244 u32 l_s = 0;
2245 int counter = 32;
2246 int carry;
2247
2248 if (s == 0) {
2249 x86emu_intr_raise(0);
2250 return;
2251 }
2252 do {
2253 div <<= 1;
2254 carry = (l_dvd >= l_s) ? 0 : 1;
2255
2256 if (h_dvd < (h_s + carry)) {
2257 h_s >>= 1;
2258 l_s = s << (--counter);
2259 continue;
2260 } else {
2261 h_dvd -= (h_s + carry);
2262 l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
2263 : (l_dvd - l_s);
2264 h_s >>= 1;
2265 l_s = s << (--counter);
2266 div |= 1;
2267 continue;
2268 }
2269
2270 } while (counter > -1);
2271 /* overflow */
2272 if (h_dvd || (l_dvd > s)) {
2273 x86emu_intr_raise(0);
2274 return;
2275 }
2276 mod = l_dvd;
2277 #endif
2278 CLEAR_FLAG(F_CF);
2279 CLEAR_FLAG(F_AF);
2280 CLEAR_FLAG(F_SF);
2281 SET_FLAG(F_ZF);
2282 set_parity_flag(mod);
2283
2284 M.x86.R_EAX = (u32)div;
2285 M.x86.R_EDX = (u32)mod;
2286 }
2287
2288 /****************************************************************************
2289 REMARKS:
2290 Implements the IN string instruction and side effects.
2291 ****************************************************************************/
2292
single_in(int size)2293 static void single_in(int size)
2294 {
2295 if(size == 1)
2296 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inb)(M.x86.R_DX));
2297 else if (size == 2)
2298 store_data_word_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inw)(M.x86.R_DX));
2299 else
2300 store_data_long_abs(M.x86.R_ES, M.x86.R_DI,(*sys_inl)(M.x86.R_DX));
2301 }
2302
ins(int size)2303 void ins(int size)
2304 {
2305 int inc = size;
2306
2307 if (ACCESS_FLAG(F_DF)) {
2308 inc = -size;
2309 }
2310 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2311 /* dont care whether REPE or REPNE */
2312 /* in until CX is ZERO. */
2313 u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
2314 M.x86.R_ECX : M.x86.R_CX);
2315
2316 while (count--) {
2317 single_in(size);
2318 M.x86.R_DI += inc;
2319 }
2320 M.x86.R_CX = 0;
2321 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2322 M.x86.R_ECX = 0;
2323 }
2324 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2325 } else {
2326 single_in(size);
2327 M.x86.R_DI += inc;
2328 }
2329 }
2330
2331 /****************************************************************************
2332 REMARKS:
2333 Implements the OUT string instruction and side effects.
2334 ****************************************************************************/
2335
single_out(int size)2336 static void single_out(int size)
2337 {
2338 if(size == 1)
2339 (*sys_outb)(M.x86.R_DX,fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
2340 else if (size == 2)
2341 (*sys_outw)(M.x86.R_DX,fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
2342 else
2343 (*sys_outl)(M.x86.R_DX,fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
2344 }
2345
outs(int size)2346 void outs(int size)
2347 {
2348 int inc = size;
2349
2350 if (ACCESS_FLAG(F_DF)) {
2351 inc = -size;
2352 }
2353 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2354 /* dont care whether REPE or REPNE */
2355 /* out until CX is ZERO. */
2356 u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
2357 M.x86.R_ECX : M.x86.R_CX);
2358 while (count--) {
2359 single_out(size);
2360 M.x86.R_SI += inc;
2361 }
2362 M.x86.R_CX = 0;
2363 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2364 M.x86.R_ECX = 0;
2365 }
2366 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2367 } else {
2368 single_out(size);
2369 M.x86.R_SI += inc;
2370 }
2371 }
2372
2373 /****************************************************************************
2374 PARAMETERS:
2375 addr - Address to fetch word from
2376
2377 REMARKS:
2378 Fetches a word from emulator memory using an absolute address.
2379 ****************************************************************************/
mem_access_word(int addr)2380 u16 mem_access_word(int addr)
2381 {
2382 DB( if (CHECK_MEM_ACCESS())
2383 x86emu_check_mem_access(addr);)
2384 return (*sys_rdw)(addr);
2385 }
2386
2387 /****************************************************************************
2388 REMARKS:
2389 Pushes a word onto the stack.
2390
2391 NOTE: Do not inline this, as (*sys_wrX) is already inline!
2392 ****************************************************************************/
push_word(u16 w)2393 void push_word(u16 w)
2394 {
2395 DB( if (CHECK_SP_ACCESS())
2396 x86emu_check_sp_access();)
2397 M.x86.R_SP -= 2;
2398 (*sys_wrw)(((u32)M.x86.R_SS << 4) + M.x86.R_SP, w);
2399 }
2400
2401 /****************************************************************************
2402 REMARKS:
2403 Pushes a long onto the stack.
2404
2405 NOTE: Do not inline this, as (*sys_wrX) is already inline!
2406 ****************************************************************************/
push_long(u32 w)2407 void push_long(u32 w)
2408 {
2409 DB( if (CHECK_SP_ACCESS())
2410 x86emu_check_sp_access();)
2411 M.x86.R_SP -= 4;
2412 (*sys_wrl)(((u32)M.x86.R_SS << 4) + M.x86.R_SP, w);
2413 }
2414
2415 /****************************************************************************
2416 REMARKS:
2417 Pops a word from the stack.
2418
2419 NOTE: Do not inline this, as (*sys_rdX) is already inline!
2420 ****************************************************************************/
pop_word(void)2421 u16 pop_word(void)
2422 {
2423 u16 res;
2424
2425 DB( if (CHECK_SP_ACCESS())
2426 x86emu_check_sp_access();)
2427 res = (*sys_rdw)(((u32)M.x86.R_SS << 4) + M.x86.R_SP);
2428 M.x86.R_SP += 2;
2429 return res;
2430 }
2431
2432 /****************************************************************************
2433 REMARKS:
2434 Pops a long from the stack.
2435
2436 NOTE: Do not inline this, as (*sys_rdX) is already inline!
2437 ****************************************************************************/
pop_long(void)2438 u32 pop_long(void)
2439 {
2440 u32 res;
2441
2442 DB( if (CHECK_SP_ACCESS())
2443 x86emu_check_sp_access();)
2444 res = (*sys_rdl)(((u32)M.x86.R_SS << 4) + M.x86.R_SP);
2445 M.x86.R_SP += 4;
2446 return res;
2447 }
2448