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