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