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