File: x86asm.asm

package info (click to toggle)
polyml 5.6-8
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 31,892 kB
  • ctags: 34,453
  • sloc: cpp: 44,983; ansic: 24,520; asm: 14,850; sh: 11,730; makefile: 551; exp: 484; python: 253; awk: 91; sed: 9
file content (3563 lines) | stat: -rw-r--r-- 107,043 bytes parent folder | download
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
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
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
;#
;#  Title:  Assembly code routines for the poly system.
;#  Author:    David Matthews
;#  Copyright (c) Cambridge University Technical Services Limited 2000
;#  Further development David C. J. Matthews 2000-2015
;#
;#  This library is free software; you can redistribute it and/or
;#  modify it under the terms of the GNU Lesser General Public
;#  License version 2.1 as published by the Free Software Foundation.
;#  
;#  This library is distributed in the hope that it will be useful,
;#  but WITHOUT ANY WARRANTY; without even the implied warranty of
;#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;#  Lesser General Public License for more details.
;#  
;#  You should have received a copy of the GNU Lesser General Public
;#  License along with this library; if not, write to the Free Software
;#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
;#
;#
;#
;#
;# *********************************************************************
;# * IMPORTANT                                                         *
;# * This file is used directly by MASM but is also converted          *
;# * for use by gas on Unix.  For reasons best known to the respective *
;# * developers the assembly language accepted by gas is different     *
;# * from that used by MASM.  This file uses a sort of half-way house  *
;# * between the two versions in that the gas instruction ordering is  *
;# * used i.e. the first argument is the source and the second the     *
;# * destination, but the MASM format of addresses is used.            * 
;# * After making any changes to this file ensure that it can be       *
;# * successfully converted and compiled under both MASM and gas.      *
;# * DCJM January 2000                                                 *
;# *********************************************************************

;#
;# Registers used :-
;#
;#  %Reax: First argument to function.  Result of function call.
;#  %Rebx: Second argument to function.
;#  %Recx: General register
;#  %Redx: Closure pointer in call.
;#  %Rebp: Points to memory used for extra registers
;#  %Resi: General register.
;#  %Redi: General register.
;#  %Resp: Stack pointer.
;#  X86_64 Additional registers
;#  %R8:   Third argument to function
;#  %R9:   Fourth argument to function
;#  %R10:  Fifth argument to function
;#  %R11:  General register
;#  %R12:  General register
;#  %R13:  General register
;#  %R14:  General register
;#  %R15:  Memory allocation pointer

IFDEF WINDOWS
IFNDEF HOSTARCHITECTURE_X86_64
.486

    .model  flat,c
ENDIF

;# No name munging needed in MASM
EXTNAME     TEXTEQU <>

;# CALLMACRO is used to indicate to the converter that we have a macro
;# since macros have to be converted into C preprocessor macros.
CALLMACRO       TEXTEQU <>

IFNDEF HOSTARCHITECTURE_X86_64
Reax        TEXTEQU <eax>
Rebx        TEXTEQU <ebx>
Recx        TEXTEQU <ecx>
Redx        TEXTEQU <edx>
Resi        TEXTEQU <esi>
Redi        TEXTEQU <edi>
Resp        TEXTEQU <esp>
Rebp        TEXTEQU <ebp>
ELSE
Reax        TEXTEQU <rax>
Rebx        TEXTEQU <rbx>
Recx        TEXTEQU <rcx>
Redx        TEXTEQU <rdx>
Resi        TEXTEQU <rsi>
Redi        TEXTEQU <rdi>
Resp        TEXTEQU <rsp>
Rebp        TEXTEQU <rbp>
ENDIF
R_cl        TEXTEQU <cl>
R_bl        TEXTEQU <bl>
R_al        TEXTEQU <al>
R_ax        TEXTEQU <ax>

CONST       TEXTEQU <>

;#  gas-style instructions
;#  These are the reverse order from MASM.
MOVL        MACRO   f,t
            mov     t,f
            ENDM

MOVB        MACRO   f,t
            mov     t,f
            ENDM

ADDL        MACRO   f,t
            add     t,f
            ENDM

SUBL        MACRO   f,t
            sub     t,f
            ENDM

XORL        MACRO   f,t
            xor     t,f
            ENDM

ORL         MACRO   f,t
            or      t,f
            ENDM

ANDL        MACRO   f,t
            and     t,f
            ENDM

CMPL        MACRO   f,t
            cmp     t,f
            ENDM

CMPB        MACRO   f,t
            cmp     t,f
            ENDM

LEAL        MACRO   f,t
            lea     t,f
            ENDM

SHRL        MACRO   f,t
            shr     t,f
            ENDM

SARL        MACRO   f,t
            sar     t,f
            ENDM

SHLL        MACRO   f,t
            shl     t,f
            ENDM

TESTL       MACRO   f,t
            test    t,f
            ENDM

IMULL       MACRO   f,t
            imul    t,f
            ENDM

LOCKXADDL   MACRO   f,t
            lock xadd t,f
            ENDM

MULL         TEXTEQU <mul>

NEGL         TEXTEQU <neg>
PUSHL        TEXTEQU <push>
POPL         TEXTEQU <pop>

IFDEF HOSTARCHITECTURE_X86_64
POPFL        TEXTEQU <popfq>
PUSHFL       TEXTEQU <pushfq>
PUSHAL       TEXTEQU <pushaq>
POPAL        TEXTEQU <popaq>
FULLWORD     TEXTEQU <qword>

;#  Return instructions - all in registers in x86-64
RET0         TEXTEQU <ret>
RET1         TEXTEQU <ret>
RET2         TEXTEQU <ret>
RET3         TEXTEQU <ret>
RET4         TEXTEQU <ret>
RET5         TEXTEQU <ret>
ELSE
POPFL        TEXTEQU <popfd>
PUSHFL       TEXTEQU <pushfd>
PUSHAL       TEXTEQU <pushad>
POPAL        TEXTEQU <popad>
FULLWORD     TEXTEQU <dword>

;# Return instructions - First two values in registers, remainder on the stack
RET0         TEXTEQU <ret>
RET1         TEXTEQU <ret>
RET2         TEXTEQU <ret>
RET3         TEXTEQU <ret 4>
RET4         TEXTEQU <ret 8>
RET5         TEXTEQU <ret 12>
ENDIF
INCL         TEXTEQU <inc>

ELSE
#include "config.h"
#if defined __MINGW64__
#  if defined POLY_LINKAGE_PREFIX
#    define EXTNAME(x) POLY_LINKAGE_PREFIX ## x
#  else
#    define EXTNAME(x) x
#  endif    
;# External names in older versions of FreeBSD have a leading underscore.
#elif ! defined(__ELF__)
#define EXTNAME(x)  _##x
#else
#define EXTNAME(x)  x
#endif

IFNDEF HOSTARCHITECTURE_X86_64
#define Reax        %eax
#define Rebx        %ebx
#define Recx        %ecx
#define Redx        %edx
#define Resi        %esi
#define Redi        %edi
#define Resp        %esp
#define Rebp        %ebp
ELSE
#define Reax        %rax
#define Rebx        %rbx
#define Recx        %rcx
#define Redx        %rdx
#define Resi        %rsi
#define Redi        %rdi
#define Resp        %rsp
#define Rebp        %rbp
ENDIF
#define R_al        %al
#define R_cl        %cl
#define R_bl        %bl
#define R_ax        %ax
IFDEF HOSTARCHITECTURE_X86_64
#define R8          %r8
#define R9          %r9
#define R10         %r10
#define R11         %r11
#define R12         %r12
#define R13         %r13
#define R14         %r14
#define R15         %r15
ENDIF

#define CONST       $

#define END

IFDEF HOSTARCHITECTURE_X86_64
#define MOVL         movq
#define MOVB         movb
#define ADDL         addq
#define SUBL         subq
#define XORL         xorq
#define ORL          orq
#define ANDL         andq
#define CMPL         cmpq
#define CMPB         cmpb
#define LEAL         leaq
#define SHRL         shrq
#define SARL         sarq
#define SHLL         shlq
#define TESTL        testq
#define IMULL        imulq
#define MULL         mulq
#define DIVL         divl
#define NEGL         negq
#define PUSHL        pushq
#define POPL         popq
#define POPFL        popfq
#define PUSHFL       pushfq
#define PUSHAL       pushaq
#define POPAL        popaq
#define LOCKXADDL    lock xaddq

;# Return instructions for n arguments.  All these are in registers
#define RET0         ret
#define RET1         ret
#define RET2         ret
#define RET3         ret
#define RET4         ret
#define RET5         ret

ELSE
#define MOVL         movl
#define MOVB         movb
#define ADDL         addl
#define SUBL         subl
#define XORL         xorl
#define ORL          orl
#define ANDL         andl
#define CMPL         cmpl
#define CMPB         cmpb
#define LEAL         leal
#define SHRL         shrl
#define SARL         sarl
#define SHLL         shll
#define TESTL        testl
#define IMULL        imull
#define MULL         mull
#define DIVL         divl
#define NEGL         negl
#define PUSHL        pushl
#define POPL         popl
#define POPFL        popfl
#define PUSHFL       pushfl
#define PUSHAL       pushal
#define POPAL        popal
;# Older versions of GCC require a semicolon here.
#define LOCKXADDL    lock; xaddl

;# Return instructions for n arguments.
#define RET0         ret
#define RET1         ret
#define RET2         ret
#define RET3         ret $4
#define RET4         ret $8
#define RET5         ret $12

ENDIF

ENDIF

;# Register mask entries - must match coding used in I386CODECONS.ML
IFDEF WINDOWS
M_Reax      EQU     000001H
M_Recx      EQU     000002H
M_Redx      EQU     000004H
M_Rebx      EQU     000008H
M_Resi      EQU     000010H
M_Redi      EQU     000020H

IFDEF HOSTARCHITECTURE_X86_64
M_R8        EQU     64
M_R9        EQU     128
M_R10       EQU     256
M_R11       EQU     512
M_R12       EQU     1024
M_R13       EQU     2048
M_R14       EQU     4096
ENDIF

M_FP0       EQU     002000H
M_FP1       EQU     004000H
M_FP2       EQU     008000H
M_FP3       EQU     010000H
M_FP4       EQU     020000H
M_FP5       EQU     040000H
M_FP6       EQU     080000H
M_FP7       EQU     100000H

Mask_all    EQU     1FFFFFH

;# Set the register mask entry
RegMask     MACRO   name,mask
Mname       TEXTEQU <Mask_&name&>
%Mname      EQU     mask
            ENDM

ELSE
;# Register mask entries - must match coding used in I386CODECONS.ML
#define     M_Reax  0x000001
#define     M_Recx  0x000002
#define     M_Redx  0x000004
#define     M_Rebx  0x000008
#define     M_Resi  0x000010
#define     M_Redi  0x000020

IFDEF HOSTARCHITECTURE_X86_64
#define     M_R8         64
#define     M_R9        128
#define     M_R10       256
#define     M_R11       512
#define     M_R12      1024
#define     M_R13      2048
#define     M_R14      4096
ENDIF
            ;# Floating point registers.
#define     M_FP0   0x002000
#define     M_FP1   0x004000
#define     M_FP2   0x008000
#define     M_FP3   0x010000
#define     M_FP4   0x020000
#define     M_FP5   0x040000
#define     M_FP6   0x080000
#define     M_FP7   0x100000

#define     Mask_all 0x1FFFFF

#define     RegMask(name,mask) \
.set        Mask_##name,    mask

#define     OR  |

ENDIF

;#
;# Macro to begin the hand-coded functions
;#
IFDEF WINDOWS
INLINE_ROUTINE  MACRO   id
PUBLIC  id
id:
ENDM

ELSE

IFDEF MACOSX
#define GLOBAL .globl
ELSE
#define GLOBAL .global
ENDIF

#define INLINE_ROUTINE(id) \
GLOBAL EXTNAME(id); \
EXTNAME(id):

ENDIF


IFDEF WINDOWS

;#
;# Tagged values.   A few operations, such as shift assume that the tag bit
;# is the bottom bit.
;#


TAG         EQU 1
TAGSHIFT    EQU 1
TAGMULT     EQU 2

TAGGED      MACRO   i
            LOCAL   t
            t   TEXTEQU <i*2+1>
            EXITM   %t
ENDM

MAKETAGGED  MACRO   f,t
            lea     t,1[f*2]
ENDM

IFDEF HOSTARCHITECTURE_X86_64
POLYWORDSIZE    EQU 8
ELSE
POLYWORDSIZE    EQU 4
ENDIF

ELSE

.set    TAG,        1
.set    TAGSHIFT,   1
.set    TAGMULT,    (1 << TAGSHIFT)

#define TAGGED(i) ((i << TAGSHIFT) | TAG)
#define MAKETAGGED(from,to)     LEAL    TAG(,from,2),to


IFDEF HOSTARCHITECTURE_X86_64
.set    POLYWORDSIZE,   8
ELSE
.set    POLYWORDSIZE,   4
ENDIF

ENDIF


IFDEF WINDOWS

NIL         TEXTEQU     TAGGED(0)
UNIT        TEXTEQU     TAGGED(0)
ZERO        TEXTEQU     TAGGED(0)
FALSE       TEXTEQU     TAGGED(0)
TRUE        TEXTEQU     TAGGED(1)
MINUS1      TEXTEQU     TAGGED(0-1)
B_bytes     EQU         01h
B_mutablebytes  EQU     41h
B_mutable   EQU         40h
IFNDEF HOSTARCHITECTURE_X86_64
Max_Length  EQU         00ffffffh
ELSE
Max_Length  EQU         00ffffffffffffffh
ENDIF

ELSE

.set    NIL,        TAGGED(0)
.set    UNIT,       TAGGED(0)
.set    ZERO,       TAGGED(0)
.set    FALSE,      TAGGED(0)
.set    TRUE,       TAGGED(1)
.set    MINUS1,     TAGGED(0-1)
.set    B_bytes,    0x01
.set    B_mutable,  0x40
.set    B_mutablebytes, 0x41
IFNDEF HOSTARCHITECTURE_X86_64
.set    Max_Length, 0x00ffffff
ELSE
.set    Max_Length, 0x00ffffffffffffff
ENDIF

ENDIF

;# The "memory registers" are pointed to by Rebp within the ML code
;# The first few offsets are built into the compiled code.
;# All the offsets are built into x86_dep.c .

IFDEF WINDOWS
LocalMpointer       EQU     0

IFNDEF HOSTARCHITECTURE_X86_64
HandlerRegister     EQU     4
LocalMbottom        EQU     8
RequestCode         EQU     20  ;# Byte: Io function to call.
InRTS               EQU     21  ;# Byte: Set when in the RTS
ReturnReason        EQU     22  ;# Byte: Reason for returning from ML.
FullRestore         EQU     23  ;# Byte: Full/partial restore
PolyStack           EQU     24  ;# Current stack base
SavedSp             EQU     28  ;# Saved stack pointer
IOEntryPoint        EQU     48  ;# IO call
RaiseDiv            EQU     52  ;# Call to raise the Div exception
ArbEmulation        EQU     56  ;# Arbitrary precision emulation
ThreadId            EQU     60  ;# My thread id
RealTemp            EQU     64 ;# Space for int-real conversions

ELSE
HandlerRegister     EQU     8
LocalMbottom        EQU     16
StackLimit          EQU     24  ;# Lower limit of stack
RequestCode         EQU     40  ;# Byte: Io function to call.
InRTS               EQU     41  ;# Byte: Set when in the RTS
ReturnReason        EQU     42  ;# Byte: Reason for returning from ML.
FullRestore         EQU     43  ;# Byte: Full/partial restore
PolyStack           EQU     48  ;# Current stack base
SavedSp             EQU     56  ;# Saved stack pointer
HeapOverflow        EQU     64  ;# Heap overflow code
StackOverflow       EQU     72  ;# Stack overflow code
StackOverflowEx     EQU     80  ;# Stack overflow code (for EDI)
RaiseExEntry        EQU     88  ;# Raise exception
IOEntryPoint        EQU     96  ;# IO call
RaiseDiv            EQU     104  ;# Exception trace
ArbEmulation        EQU     112  ;# Arbitrary precision emulation
ThreadId            EQU     120 ;# My thread id
RealTemp            EQU     128 ;# Space for int-real conversions
ENDIF

ELSE
.set    LocalMpointer,0
IFNDEF HOSTARCHITECTURE_X86_64
.set    HandlerRegister,4
.set    LocalMbottom,8
.set    RequestCode,20
.set    InRTS,21
.set    ReturnReason,22
.set    FullRestore,23
.set    PolyStack,24
.set    SavedSp,28
.set    IOEntryPoint,48
.set    RaiseDiv,52
.set    ArbEmulation,56
.set    ThreadId,60
.set    RealTemp,64
ELSE
.set    HandlerRegister,8
.set    LocalMbottom,16
.set    StackLimit,24
.set    RequestCode,40
.set    InRTS,41
.set    ReturnReason,42
.set    FullRestore,43
.set    PolyStack,48
.set    SavedSp,56
.set    HeapOverflow,64
.set    StackOverflow,72
.set    StackOverflowEx,80
.set    RaiseExEntry,88
.set    IOEntryPoint,96
.set    RaiseDiv,104
.set    ArbEmulation,112
.set    ThreadId,120
.set    RealTemp,128
ENDIF

ENDIF

;# IO function numbers.  These are functions that are called
;# to handle special cases in this code

IFDEF WINDOWS
POLY_SYS_exit                EQU 1
POLY_SYS_chdir               EQU 9
POLY_SYS_alloc_store         EQU 11
POLY_SYS_get_flags           EQU 17
POLY_SYS_exception_trace_fn  EQU 32
POLY_SYS_give_ex_trace_fn    EQU 33
POLY_SYS_network             EQU 51
POLY_SYS_os_specific         EQU 52
POLY_SYS_io_dispatch         EQU 61
POLY_SYS_signal_handler      EQU 62
POLY_SYS_thread_dispatch     EQU 73
POLY_SYS_plus_longword       EQU 74
POLY_SYS_minus_longword      EQU 75
POLY_SYS_mul_longword        EQU 76
POLY_SYS_div_longword        EQU 77
POLY_SYS_mod_longword        EQU 78
POLY_SYS_andb_longword       EQU 79
POLY_SYS_orb_longword        EQU 80
POLY_SYS_xorb_longword       EQU 81
POLY_SYS_kill_self           EQU 84
POLY_SYS_shift_left_longword        EQU  85
POLY_SYS_shift_right_longword       EQU 86
POLY_SYS_shift_right_arith_longword EQU 87
POLY_SYS_profiler            EQU 88
POLY_SYS_signed_to_longword   EQU 90
POLY_SYS_unsigned_to_longword EQU 91
POLY_SYS_full_gc             EQU 92
POLY_SYS_stack_trace         EQU 93
POLY_SYS_timing_dispatch     EQU 94
POLY_SYS_objsize             EQU 99
POLY_SYS_showsize            EQU 100
POLY_SYS_quotrem             EQU 104
POLY_SYS_aplus               EQU 106
POLY_SYS_aminus              EQU 107
POLY_SYS_amul                EQU 108
POLY_SYS_adiv                EQU 109
POLY_SYS_amod                EQU 110
POLY_SYS_aneg                EQU 111
POLY_SYS_xora                EQU 112
POLY_SYS_equala              EQU 113
POLY_SYS_ora                 EQU 114
POLY_SYS_anda                EQU 115
POLY_SYS_Real_str            EQU 117
POLY_SYS_Real_geq            EQU 118
POLY_SYS_Real_leq            EQU 119
POLY_SYS_Real_gtr            EQU 120
POLY_SYS_Real_lss            EQU 121
POLY_SYS_Real_eq             EQU 122
POLY_SYS_Real_neq            EQU 123
POLY_SYS_Real_Dispatch       EQU 124
POLY_SYS_Add_real            EQU 125
POLY_SYS_Sub_real            EQU 126
POLY_SYS_Mul_real            EQU 127
POLY_SYS_Div_real            EQU 128
POLY_SYS_Abs_real            EQU 129
POLY_SYS_Neg_real            EQU 130
POLY_SYS_conv_real           EQU 133
POLY_SYS_real_to_int         EQU 134
POLY_SYS_int_to_real         EQU 135
POLY_SYS_sqrt_real           EQU 136
POLY_SYS_sin_real            EQU 137
POLY_SYS_cos_real            EQU 138
POLY_SYS_arctan_real         EQU 139
POLY_SYS_exp_real            EQU 140
POLY_SYS_ln_real             EQU 141
POLY_SYS_process_env         EQU 150
POLY_SYS_poly_specific       EQU 153
;# Define these for the moment.
POLY_SYS_cmem_load_32        EQU 162
POLY_SYS_cmem_load_64        EQU 163
POLY_SYS_cmem_load_float     EQU 164
POLY_SYS_cmem_load_double    EQU 165
POLY_SYS_cmem_store_32       EQU 168
POLY_SYS_cmem_store_64       EQU 169
POLY_SYS_cmem_store_float    EQU 170
POLY_SYS_cmem_store_double   EQU 171
POLY_SYS_io_operation        EQU 189
POLY_SYS_ffi                 EQU 190
POLY_SYS_set_code_constant   EQU 194
POLY_SYS_code_flags          EQU 200
POLY_SYS_shrink_stack        EQU 201
POLY_SYS_callcode_tupled     EQU 204
POLY_SYS_foreign_dispatch    EQU 205
POLY_SYS_XWindows            EQU 209
POLY_SYS_int_geq             EQU 231
POLY_SYS_int_leq             EQU 232
POLY_SYS_int_gtr             EQU 233
POLY_SYS_int_lss             EQU 234


RETURN_HEAP_OVERFLOW        EQU 1
RETURN_STACK_OVERFLOW       EQU 2
RETURN_STACK_OVERFLOWEX     EQU 3
RETURN_RAISE_DIV            EQU 4
RETURN_ARB_EMULATION        EQU 5
RETURN_CALLBACK_RETURN      EQU 6
RETURN_CALLBACK_EXCEPTION   EQU 7

ELSE
#include "sys.h"

#define RETURN_HEAP_OVERFLOW        1
#define RETURN_STACK_OVERFLOW       2
#define RETURN_STACK_OVERFLOWEX     3
#define RETURN_RAISE_DIV            4
#define RETURN_ARB_EMULATION        5
#define RETURN_CALLBACK_RETURN      6
#define RETURN_CALLBACK_EXCEPTION   7


ENDIF

;#
;# Stack format from objects.h is:
;#  typedef struct
;#  {                byte offset of start
;#    word  p_space ;            0 -- Now unused - remove
;#    byte *p_pc ;               4
;#    word *p_sp ;               8 -- Now unused - remove
;#    word *p_hr ;              12
;#    word  p_nreg ;            16  -- Now unused - remove
;#    word  p_reg[1] ;          20
;#  } StackObject ;
;#
 
;#
;# Starting offsets

IFDEF WINDOWS

IFNDEF HOSTARCHITECTURE_X86_64
PC_OFF      EQU     4
SP_OFF      EQU     8
EAX_OFF     EQU     20
EBX_OFF     EQU     24
ECX_OFF     EQU     28
EDX_OFF     EQU     32
ESI_OFF     EQU     36
EDI_OFF     EQU     40
FLAGS_OFF   EQU     48
FPREGS_OFF  EQU     52
ELSE
PC_OFF      EQU     8
SP_OFF      EQU     16
EAX_OFF     EQU     40
EBX_OFF     EQU     48
ECX_OFF     EQU     56
EDX_OFF     EQU     64
ESI_OFF     EQU     72
EDI_OFF     EQU     80
R8_OFF      EQU     88
R9_OFF      EQU     96
R10_OFF     EQU     104
R11_OFF     EQU     112
R12_OFF     EQU     120
R13_OFF     EQU     128
R14_OFF     EQU     136
FLAGS_OFF   EQU     152
FPREGS_OFF  EQU     160
ENDIF

ELSE

;#.set    SPACE_OFF,  0
IFNDEF HOSTARCHITECTURE_X86_64
.set    PC_OFF,     4
.set    SP_OFF,     8
.set    EAX_OFF,    20
.set    EBX_OFF,    24
.set    ECX_OFF,    28
.set    EDX_OFF,    32
.set    ESI_OFF,    36
.set    EDI_OFF,    40
.set    FLAGS_OFF,  48
.set    FPREGS_OFF, 52
ELSE
.set    PC_OFF,     8
.set    SP_OFF,     16
;# 32 is the count of the number of checked registers
.set    EAX_OFF,    40
.set    EBX_OFF,    48
.set    ECX_OFF,    56
.set    EDX_OFF,    64
.set    ESI_OFF,    72
.set    EDI_OFF,    80
.set    R8_OFF,     88
.set    R9_OFF,     96
.set    R10_OFF,    104
.set    R11_OFF,    112
.set    R12_OFF,    120
.set    R13_OFF,    128
.set    R14_OFF,    136
;# 144 is the count of the number of unchecked registers
.set    FLAGS_OFF,  152
.set    FPREGS_OFF, 160
ENDIF

ENDIF

;# Mark the stack as non-executable when supported
IFDEF HAVE_GNU_STACK
.section .note.GNU-stack, "", @progbits
ENDIF

;#
;# CODE STARTS HERE
;#
IFDEF WINDOWS
    .CODE
ELSE
    .text
ENDIF

;# Define standard call macro. CALL_IO ioCallNo  where ioCallNo is the io function to call.
;# We need to include M_Redx in the register sets.  MD_set_for_retry may modify it
;# if the function was called directly and not via the closure register.

IFDEF WINDOWS

CALL_IO    MACRO   index
        mov     byte ptr [RequestCode+Rebp],index
        jmp     SaveStateAndReturnLocal
ENDM

CALL_EXTRA  MACRO   index
    mov     byte ptr [ReturnReason+Rebp],index
    jmp     SaveFullState
    ENDM

ELSE

#define CALL_IO(index) \
        MOVB  $index,RequestCode[Rebp]; \
        jmp   SaveStateAndReturnLocal;

#define CALL_EXTRA(index) \
        MOVB  $index,ReturnReason[Rebp]; \
        jmp   SaveFullState;
ENDIF

;# Load the registers from the ML stack and jump to the code.
;# This is used to start ML code.
;# The argument is the address of the MemRegisters struct and goes into %rbp.
CALLMACRO INLINE_ROUTINE X86AsmSwitchToPoly
IFNDEF HOSTARCHITECTURE_X86_64
    MOVL    4[Resp],Recx                    ;# Argument - address of MemRegisters - goes into Rebp
    PUSHAL                                  ;# Save all the registers just to be safe
    MOVL    Resp,SavedSp[Recx]              ;# savedSp:=%Resp - Save the system stack pointer.

    MOVL    Recx,Rebp                       ;# Put address of MemRegisters where it belongs
ELSE
IFDEF WINDOWS
;# The argument to the function is passed in Recx
    
ELSE
IFDEF _WIN32
;# The argument to the function is passed in Recx
ELSE
;# The argument to the function is passed in Redi
    MOVL    Redi,Recx
ENDIF
ENDIF
    PUSHL   Rebp                             ;# Save callee--save registers
    PUSHL   Rebx
    PUSHL   R12
    PUSHL   R13
    PUSHL   R14
    PUSHL   R15
    PUSHL   Redi                            ;# Callee save in Windows
    PUSHL   Resi
    MOVL    Resp,SavedSp[Recx]              ;# savedSp:=%Resp - Save the system stack pointer.
    MOVL    Recx,Rebp                       ;# Put address of MemRegisters where it belongs
ENDIF
    MOVL    PolyStack[Rebp],Reax
IFDEF HOSTARCHITECTURE_X86_64
    MOVL    LocalMpointer[Rebp],R15         ;# Set the heap pointer register
ENDIF
    MOVL    SP_OFF[Reax],Resp               ;# Set the new stack ptr
    PUSHL   PC_OFF[Reax]                    ;# Push the code address
IFDEF WINDOWS
    test    byte ptr [Rebp+FullRestore],1   ;# Should we restore or clear the regs?
ELSE
    testb   CONST 1,FullRestore[Rebp]       ;# Should we restore or clear the regs?
ENDIF
    jnz     sw2polyfull
;# We're returning from an RTS call.  We need to clear the registers we're
;# not restoring so that they are valid if we GC.  We restore EDX and the
;# argument regs because this may have been CallCode
    MOVL    EBX_OFF[Reax],Rebx
    MOVL    CONST ZERO,Recx
    MOVL    EDX_OFF[Reax],Redx
    MOVL    CONST ZERO,Resi
    MOVL    CONST ZERO,Redi
IFDEF HOSTARCHITECTURE_X86_64
    MOVL    R8_OFF[Reax],R8
    MOVL    R9_OFF[Reax],R9
    MOVL    R10_OFF[Reax],R10
    MOVL    CONST ZERO,R11
    MOVL    CONST ZERO,R12
    MOVL    CONST ZERO,R13
    MOVL    CONST ZERO,R14
ENDIF
    MOVL    EAX_OFF[Reax],Reax
    cld                                     ;# Clear this just in case

IFDEF WINDOWS
    mov     byte ptr [InRTS+Rebp],0
ELSE
    MOVB    CONST 0,InRTS[Rebp]             ;# inRTS:=0 (stack now kosher)
ENDIF
    ret                                     ;# Jump to code address

sw2polyfull:
    PUSHL   FLAGS_OFF[Reax]                 ;# Push the flags
    FRSTOR  FPREGS_OFF[Reax]
    MOVL    EBX_OFF[Reax],Rebx              ;# Load the registers
    MOVL    ECX_OFF[Reax],Recx
    MOVL    EDX_OFF[Reax],Redx
    MOVL    ESI_OFF[Reax],Resi
    MOVL    EDI_OFF[Reax],Redi
IFDEF HOSTARCHITECTURE_X86_64
    MOVL    R8_OFF[Reax],R8
    MOVL    R9_OFF[Reax],R9
    MOVL    R10_OFF[Reax],R10
    MOVL    R11_OFF[Reax],R11
    MOVL    R12_OFF[Reax],R12
    MOVL    R13_OFF[Reax],R13
    MOVL    R14_OFF[Reax],R14
ENDIF
    cld                                     ;# Clear this just in case
    MOVL    EAX_OFF[Reax],Reax
    POPFL                                   ;# reset flags
IFDEF WINDOWS
    mov     byte ptr [InRTS+Rebp],0
ELSE
    MOVB    CONST 0,InRTS[Rebp]             ;# inRTS:=0 (stack now kosher)
ENDIF
    ret                                     ;# Jump to code address


;# Code to save the state and switch to C
;# This saves the full register state.
SaveFullState:
    PUSHFL                      ;# Save flags
    PUSHL   Reax                ;# Save eax
    MOVL    PolyStack[Rebp],Reax
    MOVL    Rebx,EBX_OFF[Reax]
    MOVL    Recx,ECX_OFF[Reax]
    MOVL    Redx,EDX_OFF[Reax]
    MOVL    Resi,ESI_OFF[Reax]
    MOVL    Redi,EDI_OFF[Reax]
    FNSAVE  FPREGS_OFF[Reax]          ;# Save FP state.  Also resets the state so...
    FLDCW   FPREGS_OFF[Reax]          ;# ...load because we need the same rounding mode in the RTS
IFDEF HOSTARCHITECTURE_X86_64
    MOVL    R8,R8_OFF[Reax]
    MOVL    R9,R9_OFF[Reax]
    MOVL    R10,R10_OFF[Reax]
    MOVL    R11,R11_OFF[Reax]
    MOVL    R12,R12_OFF[Reax]
    MOVL    R13,R13_OFF[Reax]
    MOVL    R14,R14_OFF[Reax]
    MOVL    R15,LocalMpointer[Rebp]  ;# Save the heap pointer
ENDIF
    POPL    Rebx                ;# Get old eax value
    MOVL    Rebx,EAX_OFF[Reax]
    POPL    Rebx
    MOVL    Rebx,FLAGS_OFF[Reax]
    MOVL    Resp,SP_OFF[Reax]
IFDEF WINDOWS
    mov     byte ptr [InRTS+Rebp],1
ELSE
    MOVB    CONST 1,InRTS[Rebp]             ;# inRTS:=0 (stack now kosher)
ENDIF
    MOVL    SavedSp[Rebp],Resp
IFNDEF HOSTARCHITECTURE_X86_64
    POPAL
ELSE
    POPL    Resi
    POPL    Redi
    POPL    R15                            ;# Restore callee-save registers
    POPL    R14
    POPL    R13
    POPL    R12
    POPL    Rebx
    POPL    Rebp
ENDIF
    ret

;# As X86AsmSaveFullState but only save what is necessary for an RTS call.
CALLMACRO INLINE_ROUTINE X86AsmSaveStateAndReturn
SaveStateAndReturnLocal: ;# This is necessary so that the jmps use a PC-relative address

    PUSHL   Reax                ;# Save eax
    MOVL    PolyStack[Rebp],Reax
    MOVL    Rebx,EBX_OFF[Reax]
    MOVL    Redx,EDX_OFF[Reax]
    FSTCW   FPREGS_OFF[Reax]
    FNINIT                     ;# Reset the FP state.
    FLDCW   FPREGS_OFF[Reax]   ;# But reload the rounding mode
IFDEF HOSTARCHITECTURE_X86_64
    MOVL    R8,R8_OFF[Reax]
    MOVL    R9,R9_OFF[Reax]
    MOVL    R10,R10_OFF[Reax]
    MOVL    R15,LocalMpointer[Rebp]  ;# Save the heap pointer
ENDIF
    POPL    Rebx                ;# Get old eax value
    MOVL    Rebx,EAX_OFF[Reax]
    MOVL    Resp,SP_OFF[Reax]
IFDEF WINDOWS
    mov     byte ptr [InRTS+Rebp],1
ELSE
    MOVB    CONST 1,InRTS[Rebp]             ;# inRTS:=0 (stack now kosher)
ENDIF
    MOVL    SavedSp[Rebp],Resp
IFNDEF HOSTARCHITECTURE_X86_64
    POPAL
ELSE
    POPL    Resi
    POPL    Redi
    POPL    R15                            ;# Restore callee-save registers
    POPL    R14
    POPL    R13
    POPL    R12
    POPL    Rebx
    POPL    Rebp
ENDIF
    ret

;#
;# A number of functions implemented in Assembly for efficiency reasons
;#

CALLMACRO INLINE_ROUTINE int_to_word
 ;# Extract the low order bits from a word.
    TESTL   CONST TAG,Reax
    jz      get_first_long_word_a1
    ret                 ;# Return the argument
CALLMACRO   RegMask int_to_word,(M_Reax)

 ;# This is now used in conjunction with isShort in Word.fromInt.
CALLMACRO INLINE_ROUTINE get_first_long_word_a
get_first_long_word_a1:
IFDEF WINDOWS
    test    byte ptr [Reax-1],CONST 16  ;# 16 is the "negative" bit
ELSE
    testb   CONST 16,(-1)[Reax]     ;# 16 is the "negative" bit
ENDIF
    MOVL    [Reax],Reax     ;# Extract the word which is already little-endian
    jz      gfw1
    NEGL    Reax            ;# We can ignore overflow
gfw1:
CALLMACRO   MAKETAGGED  Reax,Reax
    ret
CALLMACRO   RegMask get_first_long_word,(M_Reax)



CALLMACRO INLINE_ROUTINE move_bytes
 ;# Move a segment of memory from one location to another.
 ;# Must deal with the case of overlapping segments correctly.
 ;# (source, sourc_offset, destination, dest_offset, length)

 ;# Assume that the offsets and length are all short integers.
IFNDEF HOSTARCHITECTURE_X86_64
    MOVL    12[Resp],Redi               ;# Destination address
    MOVL    8[Resp],Recx                ;# Destination offset, untagged
ELSE
    MOVL    R8,Redi               ;# Destination address
    MOVL    R9,Recx                ;# Destination offset, untagged
ENDIF
    SHRL    CONST TAGSHIFT,Recx
    ADDL    Recx,Redi
    MOVL    Reax,Resi                   ;# Source address
    SHRL    CONST TAGSHIFT,Rebx
    ADDL    Rebx,Resi
IFNDEF HOSTARCHITECTURE_X86_64
    MOVL    4[Resp],Recx                ;# Get the length to move
ELSE
    MOVL    R10,Recx                ;# Get the length to move
ENDIF
    SHRL    CONST TAGSHIFT,Recx
    cld                             ;# Default to increment Redi,Resi
    CMPL    Redi,Resi                   ;# Check for potential overlap
 ;# If dest > src then use decrementing moves else
 ;# use incrementing moves.
    ja      mvb1
    std                             ;# Decrement Redi,Resi
    LEAL    (-1)[Resi+Recx],Resi
    LEAL    (-1)[Redi+Recx],Redi
mvb1:
IFDEF WINDOWS
    rep movsb                       ;# Copy the bytes
ELSE
    rep
    movsb                           ;# Copy the bytes
ENDIF
    MOVL    CONST UNIT,Reax             ;# The function returns unit
    MOVL    Reax,Rebx               ;# Clobber bad value in %rbx
    MOVL    Reax,Recx               ;# and %Recx
    MOVL    Reax,Redi
    MOVL    Reax,Resi
 ;# Visual Studio 5 C++ seems to assume that the direction flag
 ;# is cleared.  I think that`s a bug but we have to go along with it.
    cld
IFNDEF HOSTARCHITECTURE_X86_64
    ret     CONST 12
ELSE
    ret
ENDIF

CALLMACRO   RegMask move_bytes,Mask_all


CALLMACRO INLINE_ROUTINE move_words
 ;# Move a segment of memory from one location to another.
 ;# Must deal with the case of overlapping segments correctly.
 ;# (source, source_offset, destination, dest_offset, length)
 ;# Assume that the offsets and length are all short integers.
IFNDEF HOSTARCHITECTURE_X86_64
    MOVL    12[Resp],Redi               ;# Destination address
    MOVL    8[Resp],Recx                ;# Destination offset
    LEAL    (-2)[Redi+Recx*2],Redi      ;# Destination address plus offset
    LEAL    (-2)[Reax+Rebx*2],Resi      ;# Source address plus offset
    MOVL    4[Resp],Recx                ;# Get the length to move (words)
ELSE
    MOVL    R8,Redi               ;# Destination address
    MOVL    R9,Recx                ;# Destination offset
    LEAL    (-4)[Redi+Recx*4],Redi      ;# Destination address plus offset
    LEAL    (-4)[Reax+Rebx*4],Resi      ;# Source address plus offset
    MOVL    R10,Recx                ;# Get the length to move (words)
ENDIF
    SHRL    CONST TAGSHIFT,Recx
    cld                             ;# Default to increment Redi,Resi
    CMPL    Redi,Resi                   ;# Check for potential overlap
 ;# If dest > src then use decrementing moves else
 ;# use incrementing moves.
    ja      mvw1
    std                             ;# Decrement Redi,Resi

    LEAL    (-POLYWORDSIZE)[Resi+Recx*POLYWORDSIZE],Resi
    LEAL    (-POLYWORDSIZE)[Redi+Recx*POLYWORDSIZE],Redi

mvw1:
IFDEF WINDOWS
IFNDEF HOSTARCHITECTURE_X86_64
    rep movsd                       ;# Copy the words
ELSE
    rep movsq                       ;# Copy the words
ENDIF
ELSE
    rep
IFNDEF HOSTARCHITECTURE_X86_64
    movsl                           ;# Copy the words
ELSE
    movsq                           ;# Copy the words
ENDIF
ENDIF
    MOVL    CONST UNIT,Reax             ;# The function returns unit
    MOVL    Reax,Recx               ;# Clobber bad values
    MOVL    Reax,Redi
    MOVL    Reax,Resi
 ;# Visual Studio 5 C++ seems to assume that the direction flag
 ;# is cleared.  I think that`s a bug but we have to go along with it.
    cld
IFNDEF HOSTARCHITECTURE_X86_64
    ret     CONST 12
ELSE
    ret
ENDIF

CALLMACRO   RegMask move_words,Mask_all
;#

RetFalse:
    MOVL    CONST FALSE,Reax
    ret

RetTrue:
    MOVL    CONST TRUE,Reax
    ret

CALLMACRO INLINE_ROUTINE not_bool
    XORL    CONST (TRUE-TAG),Reax   ;# Change the value but leave the tag
    ret
CALLMACRO   RegMask not_bool,(M_Reax)

 ;# or, and, xor shift etc. assume the values are tagged integers
CALLMACRO INLINE_ROUTINE or_word
    ORL     Rebx,Reax
    ret
CALLMACRO   RegMask or_word,(M_Reax)

CALLMACRO INLINE_ROUTINE and_word
    ANDL    Rebx,Reax
    ret
CALLMACRO   RegMask and_word,(M_Reax)

CALLMACRO INLINE_ROUTINE xor_word
    XORL    Rebx,Reax
    ORL     CONST TAG,Reax  ;# restore the tag
    ret
CALLMACRO   RegMask xor_word,(M_Reax)

CALLMACRO INLINE_ROUTINE shift_left_word
 ;# Assume that both args are tagged integers
 ;# Word.<<(a,b) is defined to return 0 if b > Word.wordSize
IFNDEF HOSTARCHITECTURE_X86_64
    CMPL    CONST TAGGED(31),Rebx
ELSE
    CMPL    CONST TAGGED(63),Rebx
ENDIF
    jb      slw1
    MOVL    CONST ZERO,Reax
    ret
slw1:
    MOVL    Rebx,Recx
    SHRL    CONST TAGSHIFT,Recx ;# remove tag
    SUBL    CONST TAG,Reax
    SHLL    R_cl,Reax
    ORL     CONST TAG,Reax  ;# restore the tag
    MOVL    Reax,Recx       ;# clobber %Recx
    ret
CALLMACRO   RegMask shift_left_word,(M_Reax OR M_Recx)

CALLMACRO INLINE_ROUTINE shift_right_word
 ;# Word.>>(a,b) is defined to return 0 if b > Word.wordSize
IFNDEF HOSTARCHITECTURE_X86_64
    CMPL    CONST TAGGED(31),Rebx
ELSE
    CMPL    CONST TAGGED(63),Rebx
ENDIF
    jb      srw1
    MOVL    CONST ZERO,Reax
    ret
srw1:
    MOVL    Rebx,Recx
    SHRL    CONST TAGSHIFT,Recx ;# remove tag
    SHRL    R_cl,Reax
    ORL     CONST TAG,Reax  ;# restore the tag
    MOVL    Reax,Recx       ;# clobber %Recx
    ret
CALLMACRO   RegMask shift_right_word,(M_Reax OR M_Recx)

CALLMACRO INLINE_ROUTINE shift_right_arith_word
 ;# Word.~>>(a,b) is defined to return 0 or ~1 if b > Word.wordSize
 ;# The easiest way to do that is to set the shift to 31.
IFNDEF HOSTARCHITECTURE_X86_64
    CMPL    CONST TAGGED(31),Rebx
ELSE
    CMPL    CONST TAGGED(63),Rebx
ENDIF
    jb      sra1
IFNDEF HOSTARCHITECTURE_X86_64
    MOVL    CONST TAGGED(31),Rebx
ELSE
    MOVL    CONST TAGGED(63),Rebx
ENDIF
sra1:
    MOVL    Rebx,Recx
    SHRL    CONST TAGSHIFT,Recx ;# remove tag
    SARL    R_cl,Reax
    ORL     CONST TAG,Reax  ;# restore the tag
    MOVL    Reax,Recx       ;# clobber %Recx
    ret
CALLMACRO   RegMask shift_right_arith_word,(M_Reax OR M_Recx)

;# Clears the "mutable" bit on a segment
CALLMACRO INLINE_ROUTINE locksega
IFDEF WINDOWS
    and     byte ptr    [Reax-1],CONST(0ffh-B_mutable)
ELSE
    andb    CONST(0xff-B_mutable),-1[Reax]
ENDIF
    MOVL     CONST TAGGED(0),Reax   ;# Return Unit,
    ret
CALLMACRO   RegMask lockseg,M_Reax

CALLMACRO INLINE_ROUTINE get_length_a
    MOVL    (-POLYWORDSIZE)[Reax],Reax
    SHLL    CONST 8,Reax            ;# Clear top byte
    SHRL    CONST(8-TAGSHIFT),Reax  ;# Make it a tagged integer
    ORL CONST TAG,Reax
    ret
CALLMACRO   RegMask get_length,(M_Reax)


CALLMACRO INLINE_ROUTINE is_shorta
;# Returns true if the argument is tagged
    ANDL    CONST TAG,Reax
    jz      RetFalse
    jmp     RetTrue
CALLMACRO   RegMask is_short,(M_Reax)

CALLMACRO INLINE_ROUTINE string_length
    TESTL   CONST TAG,Reax  ;# Single char strings are represented by the
    jnz     RetOne      ;# character.
    MOVL    [Reax],Reax ;# Get length field
CALLMACRO   MAKETAGGED  Reax,Reax
    ret
RetOne: MOVL    CONST TAGGED(1),Reax
    ret
CALLMACRO   RegMask string_length,(M_Reax)

 ;# Store the length of a string in the first word.
CALLMACRO INLINE_ROUTINE set_string_length_a
    SHRL    CONST TAGSHIFT,Rebx ;# Untag the length
    MOVL    Rebx,[Reax]
    MOVL    CONST UNIT,Reax     ;# Return unit
    MOVL    Reax,Rebx           ;# Clobber untagged value
    ret
CALLMACRO   RegMask set_string_length,(M_Reax OR M_Rebx)

;# raisex (formerly raisexn) is used by compiled code.
CALLMACRO INLINE_ROUTINE raisex
    MOVL    HandlerRegister[Rebp],Recx    ;# Get next handler into %rcx

IFDEF WINDOWS
    jmp     FULLWORD ptr [Recx]
ELSE
    jmp     *[Recx]
ENDIF

CALLMACRO INLINE_ROUTINE load_byte
    MOVL    Rebx,Redi
    SHRL    CONST TAGSHIFT,Redi
IFDEF WINDOWS
    movzx   Redi, byte ptr [Reax][Redi]
ELSE
IFNDEF HOSTARCHITECTURE_X86_64
    movzbl  (Reax,Redi,1),Redi
ELSE
    movzbq  (Reax,Redi,1),Redi
ENDIF
ENDIF
CALLMACRO   MAKETAGGED  Redi,Reax
    MOVL    Reax,Redi       ;# Clobber bad value in %Redi
    ret
CALLMACRO   RegMask load_byte,(M_Reax OR M_Redi)

CALLMACRO INLINE_ROUTINE load_word
IFNDEF HOSTARCHITECTURE_X86_64
    MOVL    (-2)[Reax+Rebx*2],Reax
ELSE
    MOVL    (-4)[Reax+Rebx*4],Reax
ENDIF
    MOVL    Reax,Rebx
    ret
CALLMACRO   RegMask load_word,(M_Reax)

CALLMACRO INLINE_ROUTINE assign_byte
;# We can assume that the data value will not overflow 30 bits (it is only 1 byte!)
IFNDEF HOSTARCHITECTURE_X86_64
    MOVL    4[Resp],Recx
ELSE
    MOVL    R8,Recx
ENDIF
    SHRL    CONST TAGSHIFT,Recx       ;# Remove tags from data value

;# We can assume that the index will not overflow 30 bits i.e. it is a tagged short
    SHRL    CONST TAGSHIFT,Rebx     ;# Remove tags from offset
    MOVB    R_cl,[Reax+Rebx]

    MOVL    CONST UNIT,Reax             ;# The function returns unit
    MOVL    Reax,Rebx                   ;# Clobber bad value in %Rebx
    MOVL    Reax,Recx                   ;# and %Recx
IFNDEF HOSTARCHITECTURE_X86_64
    ret     CONST 4
ELSE
    ret
ENDIF
CALLMACRO   RegMask assign_byte,(M_Reax OR M_Rebx OR M_Recx)


CALLMACRO INLINE_ROUTINE assign_word
IFNDEF HOSTARCHITECTURE_X86_64
    MOVL    4[Resp],Recx
    MOVL    Recx,(-2)[Reax+Rebx*2]
ELSE
    MOVL    R8,(-4)[Reax+Rebx*4]      ;# The offset is tagged already
ENDIF
    MOVL    CONST UNIT,Reax           ;# The function returns unit
IFNDEF HOSTARCHITECTURE_X86_64
    ret     CONST 4
CALLMACRO   RegMask assign_word,(M_Reax OR M_Recx)
ELSE
    ret
CALLMACRO   RegMask assign_word,(M_Reax)
ENDIF

;# Allocate a piece of memory that does not need to be initialised.
;# We can't actually risk leaving word objects uninitialised so for the
;# moment we always initialise.
CALLMACRO INLINE_ROUTINE alloc_uninit
IFDEF HOSTARCHITECTURE_X86_64
    MOVL    CONST ZERO,R8
ELSE
    POP     Recx         ;# Get the return address
    PUSHL   CONST ZERO   ;# Push the initial value - zero
    PUSHL   Recx         ;# Restore the return address
ENDIF
;# Drop through into alloc_store

IFNDEF HOSTARCHITECTURE_X86_64
CALLMACRO   RegMask alloc_uninit,Mask_all ;# All, because we may call RTS
ELSE
CALLMACRO   RegMask alloc_uninit,Mask_all ;# All, because we may call RTS
ENDIF

;# alloc(size, flags, initial).  Allocates a segment of a given size and
;# initialises it.
;#
;# This is primarily used for arrays and for strings.  Refs are
;# allocated using inline code.
CALLMACRO INLINE_ROUTINE alloc_store
allsts:
 ;# alloc(size, flags, initial).  Allocates a segment of a given size and
 ;# initialises it.
 ;# First check that the length is acceptable
    TESTL   CONST TAG,Reax
    jz      alloc_in_rts            ;# Get the RTS to raise an exception
    MOVL    Reax,Redi
    SHRL    CONST TAGSHIFT,Redi     ;# Remove tag
    jnz     allst0                  ;# (test for 0) Make zero sized objects 1
    MOVL    CONST 1,Redi            ;# because they mess up the g.c.
    jmp     alloc_in_rts
allst0:
IFNDEF HOSTARCHITECTURE_X86_64
    CMPL    CONST Max_Length,Redi   ;# Length field must fit in 24 bits
ELSE
    MOVL    CONST Max_Length,Redx   ;# Length field must fit in 56 bits
    CMPL    Redx,Redi
ENDIF
    ja      alloc_in_rts            ;# Get the RTS to raise an exception
IFNDEF HOSTARCHITECTURE_X86_64
    INCL    Redi                    ;# Add 1 word
    SHLL    CONST 2,Redi            ;# Get length in bytes
    MOVL    LocalMpointer[Rebp],Redx
ELSE
    ADDL    CONST 1,Redi            ;# Add 1 word
    SHLL    CONST 3,Redi            ;# Get length in bytes
    MOVL    R15,Redx
ENDIF
    SUBL    Redi,Redx               ;# Allocate the space
    MOVL    Reax,Redi               ;# Clobber bad value in Redi
    CMPL    LocalMbottom[Rebp],Redx            ;# Check for free space
    jb      alloc_in_rts
;# Normally the above test is sufficient but if LocalMpointer is near the bottom of
;# memory and the store requested is very large the value in Redx can be negative
;# which is greater, unsigned, than LocalMbottom.  We have to check it is less
;# than, unsigned, the allocation pointer.
IFNDEF HOSTARCHITECTURE_X86_64
    CMPL    LocalMpointer[Rebp],Redx
    jnb     alloc_in_rts
    MOVL    Redx,LocalMpointer[Rebp]             ;# Put back in the heap ptr
ELSE
    CMPL    R15,Redx
    jnb     alloc_in_rts
    MOVL    Redx,R15                 ;# Put back in the heap ptr
ENDIF
    SHRL    CONST TAGSHIFT,Reax
IFNDEF HOSTARCHITECTURE_X86_64
    MOVL    Reax,(-4)[Redx]         ;# Put in length
ELSE
    MOVL    Reax,(-8)[Redx]         ;# Put in length
ENDIF
    SHRL    CONST TAGSHIFT,Rebx     ;# remove tag from flag
    ORL     CONST B_mutable,Rebx    ;# set mutable bit
    MOVB    R_bl,(-1)[Redx]         ;# and put it in.
 ;# Initialise the store.
    MOVL    Reax,Recx               ;# Get back the no. of words.
IFNDEF HOSTARCHITECTURE_X86_64
    MOVL    4[Resp],Reax            ;# Get initial value.
ELSE
    MOVL    R8,Reax                 ;# Get initial value.
ENDIF
    CMPL    CONST B_mutablebytes,Rebx
    jne     allst2

 ;# If this is a byte seg
    SHRL    CONST TAGSHIFT,Reax ;# untag the initialiser
IFNDEF HOSTARCHITECTURE_X86_64
    SHLL    CONST 2,Recx        ;# Convert to bytes
ELSE
    SHLL    CONST 3,Recx        ;# Convert to bytes
ENDIF
    MOVL    Redx,Redi
IFDEF WINDOWS
    rep stosb
ELSE
    rep
    stosb
ENDIF
    jmp     allst3

 ;# If this is a word segment
allst2:
    MOVL    Redx,Redi
IFDEF WINDOWS
IFNDEF HOSTARCHITECTURE_X86_64
    rep stosd
ELSE
    rep stosq
ENDIF
ELSE
    rep
IFNDEF HOSTARCHITECTURE_X86_64
    stosl
ELSE
    stosq
ENDIF
ENDIF

allst3:
    MOVL    Redx,Reax

    MOVL    Reax,Recx       ;# Clobber these
    MOVL    Reax,Redx
    MOVL    Reax,Rebx
    MOVL    Reax,Redi
IFNDEF HOSTARCHITECTURE_X86_64
    ret     CONST 4
ELSE
    ret
ENDIF
CALLMACRO   RegMask alloc_store,Mask_all ;# All, because we may use RTS call

;# This is used if we have reached the store limit and need to garbage-collect.
alloc_in_rts:
    MOVL    Reax,Redx       ;# Clobber these first
    MOVL    Reax,Redi
CALLMACRO   CALL_IO    POLY_SYS_alloc_store

CALLMACRO INLINE_ROUTINE touch_final
;# This is really a pseudo-op
    MOVL    CONST UNIT,Reax
CALLMACRO   RegMask touch_final,(M_Reax)

CALLMACRO INLINE_ROUTINE add_long
    MOVL    Reax,Redi
    ANDL    Rebx,Redi
    ANDL    CONST TAG,Redi
    jz      add_really_long
    LEAL    (-TAG)[Reax],Redi
    ADDL    Rebx,Redi
    jo      add_really_long
    MOVL    Redi,Reax
    ret
add_really_long:
    MOVL    Reax,Redi
CALLMACRO   CALL_IO    POLY_SYS_aplus
CALLMACRO   RegMask aplus,(M_Reax OR M_Redi OR Mask_all)

CALLMACRO INLINE_ROUTINE sub_long
    MOVL    Reax,Redi
    ANDL    Rebx,Redi
    ANDL    CONST TAG,Redi
    jz      sub_really_long
    MOVL    Reax,Redi
    SUBL    Rebx,Redi
    jo      sub_really_long
    LEAL    TAG[Redi],Reax      ;# Put back the tag
    MOVL    Reax,Redi
    ret
sub_really_long:
    MOVL    Reax,Redi
CALLMACRO   CALL_IO    POLY_SYS_aminus
CALLMACRO   RegMask aminus,(M_Reax OR M_Redi OR Mask_all)

CALLMACRO INLINE_ROUTINE mult_long
    MOVL    Reax,Redi
    ANDL    Rebx,Redi
    ANDL    CONST TAG,Redi
    jz      mul_really_long
    MOVL    Rebx,Redi
    SARL    CONST TAGSHIFT,Redi ;# Shift multiplicand
    MOVL    Reax,Resi
    SUBL    CONST TAG,Resi          ;# Just subtract off the tag off multiplier
    IMULL   Redi,Resi
    jo      mul_really_long
    ADDL    CONST TAG,Resi
    MOVL    Resi,Reax
    MOVL    Reax,Redi
    ret
mul_really_long:
    MOVL    Reax,Resi       ;# Clobber this
    MOVL    Reax,Redi
CALLMACRO   CALL_IO    POLY_SYS_amul
CALLMACRO   RegMask amul,(M_Reax OR M_Redi OR M_Resi OR Mask_all)

CALLMACRO INLINE_ROUTINE div_long
    MOVL    Reax,Redi
    ANDL    Rebx,Redi
    ANDL    CONST TAG,Redi          ;# %Redi now contains $0 or $1 (both legal!)
    jz      div_really_long
    CMPL    CONST TAGGED(0),Rebx    ;# Check that it's non-zero
    jz      div_really_long         ;# We don't want a trap.
 ;# The only case of overflow is dividing the smallest negative number by -1
    CMPL    CONST TAGGED((-1)),Rebx
    jz      div_really_long
    SARL    CONST TAGSHIFT,Reax
    MOVL    Rebx,Redi
    SARL    CONST TAGSHIFT,Redi
IFNDEF HOSTARCHITECTURE_X86_64
    cdq
ELSE
    cqo
ENDIF
    idiv    Redi
CALLMACRO   MAKETAGGED  Reax,Reax
    MOVL    Reax,Redx
    MOVL    Reax,Redi
    ret
div_really_long:
    MOVL    Reax,Redi
CALLMACRO   CALL_IO    POLY_SYS_adiv
CALLMACRO   RegMask adiv,(M_Reax OR M_Redi OR M_Redx OR Mask_all)

CALLMACRO INLINE_ROUTINE rem_long
    MOVL    Reax,Redi
    ANDL    Rebx,Redi
    ANDL    CONST TAG,Redi      ;# %Redi now contains $0 or $1 (both legal!
    jz      rem_really_long
    CMPL    CONST TAGGED(0),Rebx    ;# Check that it's non-zero
    jz      rem_really_long         ;# We don't want a trap.
 ;# The only case of overflow is dividing the smallest negative number by -1
    CMPL    CONST TAGGED((-1)),Rebx
    jz      rem_really_long
    SARL    CONST TAGSHIFT,Reax
    MOVL    Rebx,Redi
    SARL    CONST TAGSHIFT,Redi
IFNDEF HOSTARCHITECTURE_X86_64
    cdq
ELSE
    cqo
ENDIF
    idiv    Redi
CALLMACRO   MAKETAGGED  Redx,Reax
    MOVL    Reax,Redx
    MOVL    Reax,Redi
    ret
rem_really_long:
    MOVL    Reax,Redi
CALLMACRO   CALL_IO    POLY_SYS_amod
CALLMACRO   RegMask amod,(M_Reax OR M_Redi OR M_Redx OR Mask_all)

 ;# Combined quotient and remainder.  We have to use the long form
 ;# if the arguments are long or there's an overflow.  The first two
 ;# arguments are the values to be divided.  The third argument is the
 ;# address where the results should be placed. 
CALLMACRO INLINE_ROUTINE quotrem_long
    MOVL    Reax,Redi
    ANDL    Rebx,Redi
    ANDL    CONST TAG,Redi
    jz      quotrem_really_long
    CMPL    CONST TAGGED(0),Rebx
    jz      quotrem_really_long
 ;# The only case of overflow is dividing the smallest negative number by -1
    CMPL    CONST TAGGED((-1)),Rebx
    jz      quotrem_really_long

 ;# Get the address for the result.
IFNDEF HOSTARCHITECTURE_X86_64
    MOVL    4[Resp],Recx
ELSE
    MOVL    R8,Recx
ENDIF
;# Do the division
    SARL    CONST TAGSHIFT,Reax
    MOVL    Rebx,Redi
    SARL    CONST TAGSHIFT,Redi
IFNDEF HOSTARCHITECTURE_X86_64
    cdq
ELSE
    cqo
ENDIF
    idiv    Redi
CALLMACRO   MAKETAGGED  Reax,Reax
CALLMACRO   MAKETAGGED  Redx,Redx
    MOVL    Reax,Redi
    MOVL    Reax,[Recx]
    MOVL    Redx,POLYWORDSIZE[Recx]
    MOVL    Recx,Reax
IFNDEF HOSTARCHITECTURE_X86_64
    ret     CONST 4
ELSE
    ret
ENDIF

mem_for_remquot1:  ;# Not enough store: clobber bad value in ecx.
    MOVL   CONST 1,Recx

quotrem_really_long:
    MOVL    Reax,Redi
CALLMACRO   CALL_IO    POLY_SYS_quotrem
CALLMACRO   RegMask quotrem,(M_Reax OR M_Redi OR M_Redx OR Mask_all)

CALLMACRO INLINE_ROUTINE equal_long
    CMPL    Reax,Rebx
    je      RetTrue
    MOVL    Reax,Recx   ;# If either is short
    ORL     Rebx,Reax   ;# the result is false
    ANDL    CONST TAG,Reax
    jnz     RetFalse
    MOVL    Recx,Reax
CALLMACRO   CALL_IO    POLY_SYS_equala
CALLMACRO   RegMask equala,(M_Reax OR M_Recx OR Mask_all)


CALLMACRO INLINE_ROUTINE or_long
IFDEF NOTATTHEMOMENT
    MOVL    Reax,Redi
    ANDL    Rebx,Redi
    ANDL    CONST TAG,Redi
    jz      or_really_long
    ORL     Rebx,Reax
    MOVL    Reax,Redi
    ret
or_really_long:
ENDIF
CALLMACRO   CALL_IO    POLY_SYS_ora
CALLMACRO   RegMask ora,(M_Reax OR M_Redi OR Mask_all)

CALLMACRO INLINE_ROUTINE xor_long
IFDEF NOTATTHEMOMENT
    MOVL    Reax,Redi
    ANDL    Rebx,Redi
    ANDL    CONST TAG,Redi
    jz      xor_really_long
    XORL    Rebx,Reax
    ORL     CONST TAG,Reax  ;# restore the tag
    MOVL    Reax,Redi
    ret
xor_really_long:
ENDIF
CALLMACRO   CALL_IO    POLY_SYS_xora
CALLMACRO   RegMask xora,(M_Reax OR M_Redi OR Mask_all)

CALLMACRO INLINE_ROUTINE and_long
IFDEF NOTATTHEMOMENT
    MOVL    Reax,Redi
    ANDL    Rebx,Redi
    ANDL    CONST TAG,Redi
    jz      and_really_long
    ANDL    Rebx,Reax
    MOVL    Reax,Redi
    ret
and_really_long:
ENDIF
CALLMACRO   CALL_IO    POLY_SYS_anda
CALLMACRO   RegMask anda,(M_Reax OR M_Redi OR Mask_all)

CALLMACRO INLINE_ROUTINE neg_long
    TESTL   CONST TAG,Reax
    jz      neg_really_long
    MOVL    CONST (TAGGED(0)+TAG),Redi
    SUBL    Reax,Redi
    jo      neg_really_long
    MOVL    Redi,Reax
    ret
neg_really_long:
    MOVL    Reax,Redi
CALLMACRO   CALL_IO    POLY_SYS_aneg
CALLMACRO   RegMask aneg,(M_Reax OR M_Redi OR Mask_all)

CALLMACRO INLINE_ROUTINE int_geq
    TESTL   CONST TAG,Reax ;# Is first arg short?
    jz      igeq2
    TESTL   CONST TAG,Rebx ;# Is second arg short?
    jz      igeq1
    CMPL    Rebx,Reax
    jge     RetTrue
    jmp     RetFalse
igeq1:
 ;# First arg is short, second isn't
IFDEF WINDOWS
    test    byte ptr [Rebx-1],CONST 16  ;# 16 is the "negative" bit
ELSE
    testb   CONST 16,(-1)[Rebx]     ;# 16 is the "negative" bit
ENDIF
    jnz     RetTrue     ;# Negative - always less
    jmp     RetFalse

igeq2:
 ;# First arg is long
    TESTL   CONST TAG,Rebx ;# Is second arg short?
    jz      igeq3
 ;# First arg is long, second is short
IFDEF WINDOWS
    test    byte ptr [Reax-1],CONST 16  ;# 16 is the "negative" bit
ELSE
    testb   CONST 16,(-1)[Reax]     ;# 16 is the "negative" bit
ENDIF
    jz      RetTrue    ;# Positive - always greater
    jmp     RetFalse

igeq3:
 ;# Both long
CALLMACRO   CALL_IO    POLY_SYS_int_geq
CALLMACRO   RegMask int_geq,(M_Reax OR Mask_all)


CALLMACRO INLINE_ROUTINE int_leq
    TESTL   CONST TAG,Reax ;# Is first arg short?
    jz      ileq2
    TESTL   CONST TAG,Rebx ;# Is second arg short?
    jz      ileq1
    CMPL    Rebx,Reax
    jle     RetTrue
    jmp     RetFalse
ileq1:
 ;# First arg is short, second isn't
IFDEF WINDOWS
    test    byte ptr [Rebx-1],CONST 16  ;# 16 is the "negative" bit
ELSE
    testb   CONST 16,(-1)[Rebx]     ;# 16 is the "negative" bit
ENDIF
    jz      RetTrue     ;# Negative - always less
    jmp     RetFalse

ileq2:
 ;# First arg is long
    TESTL   CONST TAG,Rebx ;# Is second arg short?
    jz      ileq3
 ;# First arg is long, second is short
IFDEF WINDOWS
    test    byte ptr [Reax-1],CONST 16  ;# 16 is the "negative" bit
ELSE
    testb   CONST 16,(-1)[Reax]     ;# 16 is the "negative" bit
ENDIF
    jnz     RetTrue    ;# Positive - always greater
    jmp     RetFalse

ileq3:
CALLMACRO   CALL_IO    POLY_SYS_int_leq
CALLMACRO   RegMask int_leq,(M_Reax OR M_Recx OR Mask_all)


CALLMACRO INLINE_ROUTINE int_gtr
    TESTL   CONST TAG,Reax ;# Is first arg short?
    jz      igtr2
    TESTL   CONST TAG,Rebx ;# Is second arg short?
    jz      igtr1
    CMPL    Rebx,Reax
    jg      RetTrue
    jmp     RetFalse
igtr1:
 ;# First arg is short, second isn't
IFDEF WINDOWS
    test    byte ptr [Rebx-1],CONST 16  ;# 16 is the "negative" bit
ELSE
    testb   CONST 16,(-1)[Rebx]     ;# 16 is the "negative" bit
ENDIF
    jnz     RetTrue     ;# Negative - always less
    jmp     RetFalse

igtr2:
 ;# First arg is long
    TESTL   CONST TAG,Rebx ;# Is second arg short?
    jz      igtr3
 ;# First arg is long, second is short
IFDEF WINDOWS
    test    byte ptr [Reax-1],CONST 16  ;# 16 is the "negative" bit
ELSE
    testb   CONST 16,(-1)[Reax]     ;# 16 is the "negative" bit
ENDIF
    jz      RetTrue    ;# Positive - always greater
    jmp     RetFalse

igtr3:
CALLMACRO   CALL_IO    POLY_SYS_int_gtr
CALLMACRO   RegMask int_gtr,(M_Reax OR M_Recx OR Mask_all)


CALLMACRO INLINE_ROUTINE int_lss
    TESTL   CONST TAG,Reax ;# Is first arg short?
    jz      ilss2
    TESTL   CONST TAG,Rebx ;# Is second arg short?
    jz      ilss1
    CMPL    Rebx,Reax
    jl      RetTrue
    jmp     RetFalse
ilss1:
 ;# First arg is short, second isn't
IFDEF WINDOWS
    test    byte ptr [Rebx-1],CONST 16  ;# 16 is the "negative" bit
ELSE
    testb   CONST 16,(-1)[Rebx]     ;# 16 is the "negative" bit
ENDIF
    jz      RetTrue     ;# Negative - always less
    jmp     RetFalse

ilss2:
 ;# First arg is long
    TESTL   CONST TAG,Rebx ;# Is second arg short?
    jz      ilss3
 ;# First arg is long, second is short
IFDEF WINDOWS
    test    byte ptr [Reax-1],CONST 16  ;# 16 is the "negative" bit
ELSE
    testb   CONST 16,(-1)[Reax]     ;# 16 is the "negative" bit
ENDIF
    jnz     RetTrue    ;# Positive - always greater
    jmp     RetFalse

ilss3:
CALLMACRO   CALL_IO    POLY_SYS_int_lss
CALLMACRO   RegMask int_lss,(M_Reax OR M_Recx OR Mask_all)

CALLMACRO INLINE_ROUTINE offset_address
 ;# This is needed in the code generator, but is a very risky thing to do.
    SHRL    CONST TAGSHIFT,Rebx     ;# Untag
    ADDL    Rebx,Reax       ;# and add in
    MOVL    Reax,Rebx
    ret
CALLMACRO   RegMask offset_address,(M_Reax OR M_Rebx)

;# General test routine.  Returns with the condition codes set
;# appropriately.

teststr:
    TESTL   CONST TAG,Reax     ;# Is arg1 short
    jz      tststr1
    TESTL   CONST TAG,Rebx     ;# Yes: is arg2 also short?
    jz      tststr0a
    ;# Both are short - just compare the characters
    CMPL    Rebx,Reax
    ret

tststr0a:
    MOVL    CONST 1,Redi        ;# Is arg2 the null string ?
    CMPL    [Rebx],Redi
    jg      tststr4            ;# Return with "gtr" set if it is
    SHRL    CONST TAGSHIFT,Reax
    CMPB    POLYWORDSIZE[Rebx],R_al
    jne     tststr4            ;# If they're not equal that's the result
    CMPL    CONST 256,Reax     ;# But if they're equal set "less" because A is less than B
    jmp     tststr4

tststr1: ;# arg2 is not short.  Is arg1 ?
    TESTL   CONST TAG,Rebx
    jz      tststr2
    MOVL    [Reax],Redi        ;# Is arg1 the null string
    CMPL    CONST 1,Redi
    jl      tststr4            ;# Return with "less" set if it is
    SHRL    CONST TAGSHIFT,Rebx
    MOVB    POLYWORDSIZE[Reax],R_cl
    CMPB    R_bl,R_cl
    jne     tststr4            ;# If they're not equal that's the result
    CMPL    CONST 0,Redi      ;# But if they're equal set "greater" because A is greater than B
    jmp     tststr4

tststr2:
    MOVL    [Reax],Redi     ;# Get length.
    MOVL    [Rebx],Recx     ;# 
    CMPL    Recx,Redi       ;# Find shorter length
    jge     tststr3
    MOVL    Redi,Recx
tststr3:
    LEAL    POLYWORDSIZE[Reax],Resi    ;# Load ptrs for cmpsb
    LEAL    POLYWORDSIZE[Rebx],Redi
    cld                 ;# Make sure we increment
    CMPL    Reax,Reax       ;# Set the Zero bit
IFDEF WINDOWS
    repe cmpsb          ;# Compare while equal and Recx > 0
ELSE
    repe    
IFNDEF HOSTARCHITECTURE_X86_64
    cmpsb           ;# Compare while equal and %ecx > 0
ELSE
    cmpsb           ;# Compare while equal and %rcx > 0
ENDIF
ENDIF
    jnz     tststr4
 ;# Strings are equal as far as the shorter of the two.  Have to compare
 ;# the lengths.
    MOVL    [Reax],Redi
    CMPL    [Rebx],Redi
tststr4:
    MOVL    CONST 1,Reax      ;# Clobber these
    MOVL    Reax,Rebx       
    MOVL    Reax,Recx       
    MOVL    Reax,Resi
    MOVL    Reax,Redi
    ret

 ;# These functions compare strings for lexical ordering.  This version, at
 ;# any rate, assumes that they are UNSIGNED bytes.

CALLMACRO INLINE_ROUTINE str_compare
    call    teststr
    ja      RetTrue         ;# Return TAGGED(1) if it's greater
    je      RetFalse        ;# Return TAGGED(0) if it's equal
    MOVL    CONST MINUS1,Reax   ;# Return TAGGED(-1) if it's less.
    ret
CALLMACRO   RegMask str_compare,(M_Reax OR M_Recx OR M_Redi OR M_Resi)


CALLMACRO INLINE_ROUTINE teststrgeq
    call    teststr
    jnb     RetTrue
    jmp     RetFalse
CALLMACRO   RegMask teststrgeq,(M_Reax OR M_Recx OR M_Redi OR M_Resi)

CALLMACRO INLINE_ROUTINE teststrleq
    call    teststr
    jna     RetTrue
    jmp     RetFalse
CALLMACRO   RegMask teststrleq,(M_Reax OR M_Recx OR M_Redi OR M_Resi)

CALLMACRO INLINE_ROUTINE teststrlss
    call    teststr
    jb      RetTrue
    jmp     RetFalse
CALLMACRO   RegMask teststrlss,(M_Reax OR M_Recx OR M_Redi OR M_Resi)

CALLMACRO INLINE_ROUTINE teststrgtr
    call    teststr
    ja      RetTrue
    jmp     RetFalse
CALLMACRO   RegMask teststrgtr,(M_Reax OR M_Recx OR M_Redi OR M_Resi)


CALLMACRO INLINE_ROUTINE bytevec_eq
 ;# Compare arrays of bytes.  The arguments are the same as move_bytes.
 ;# (source, sourc_offset, destination, dest_offset, length)

 ;# Assume that the offsets and length are all short integers.
IFNDEF HOSTARCHITECTURE_X86_64
    MOVL    12[Resp],Redi               ;# Destination address
    MOVL    8[Resp],Recx                ;# Destination offset, untagged
ELSE
    MOVL    R8,Redi                     ;# Destination address
    MOVL    R9,Recx                     ;# Destination offset, untagged
ENDIF
    SHRL    CONST TAGSHIFT,Recx
    ADDL    Recx,Redi
    MOVL    Reax,Resi                   ;# Source address
    SHRL    CONST TAGSHIFT,Rebx
    ADDL    Rebx,Resi
IFNDEF HOSTARCHITECTURE_X86_64
    MOVL    4[Resp],Recx                ;# Get the length to move
ELSE
    MOVL    R10,Recx                    ;# Get the length to move
ENDIF
    SHRL    CONST TAGSHIFT,Recx

    cld                     ;# Make sure we increment
    CMPL    Reax,Reax       ;# Set the Zero bit
IFDEF WINDOWS
    repe    cmpsb
ELSE
    repe    
    cmpsb
ENDIF
    MOVL    Reax,Resi       ;# Make these valid
    MOVL    Reax,Recx
    MOVL    Reax,Redi
    jz      bvTrue
    MOVL    CONST FALSE,Reax
    jmp     bvRet
bvTrue:
    MOVL    CONST TRUE,Reax
bvRet:
IFNDEF HOSTARCHITECTURE_X86_64
    ret     CONST 12
ELSE
    ret
ENDIF
CALLMACRO   RegMask bytevec_eq,(M_Reax OR M_Recx OR M_Redi OR M_Resi)


CALLMACRO INLINE_ROUTINE is_big_endian
    jmp     RetFalse    ;# I386/486 is little-endian
CALLMACRO   RegMask is_big_endian,(M_Reax)

CALLMACRO INLINE_ROUTINE bytes_per_word
    MOVL    CONST TAGGED(POLYWORDSIZE),Reax  ;# 4/8 bytes per word
    ret
CALLMACRO   RegMask bytes_per_word,(M_Reax)

 ;# Word functions.  These are all unsigned and do not raise Overflow
 
CALLMACRO INLINE_ROUTINE mul_word
    SHRL    CONST TAGSHIFT,Rebx ;# Untag the multiplier
    SUBL    CONST TAG,Reax      ;# Remove the tag from the multiplicand
    MULL    Rebx                ;# unsigned multiplication
    ADDL    CONST TAG,Reax      ;# Add back the tag, but don`t shift
    MOVL    Reax,Redx           ;# clobber this which has the high-end result
    MOVL    Reax,Rebx           ;# and the other bad result.
    ret
CALLMACRO   RegMask mul_word,(M_Reax OR M_Rebx OR M_Redx)

CALLMACRO INLINE_ROUTINE plus_word
    LEAL    (-TAG)[Reax+Rebx],Reax  ;# Add the values and subtract a tag
    ret
CALLMACRO   RegMask plus_word,(M_Reax)

CALLMACRO INLINE_ROUTINE minus_word
    SUBL    Rebx,Reax
    ADDL    CONST TAG,Reax          ;# Put back the tag
    ret
CALLMACRO   RegMask minus_word,(M_Reax)

CALLMACRO INLINE_ROUTINE div_word
    SHRL    CONST TAGSHIFT,Rebx
    jz      raise_div_ex
    SHRL    CONST TAGSHIFT,Reax
    MOVL    CONST 0,Redx
    div     Rebx
CALLMACRO   MAKETAGGED  Reax,Reax
    MOVL    Reax,Redx
    MOVL    Reax,Rebx
    ret
CALLMACRO   RegMask div_word,(M_Reax OR M_Rebx OR M_Redx)

CALLMACRO INLINE_ROUTINE mod_word
    SHRL    CONST TAGSHIFT,Rebx
    jz      raise_div_ex
    SHRL    CONST TAGSHIFT,Reax
    MOVL    CONST 0,Redx
    div     Rebx
CALLMACRO   MAKETAGGED  Redx,Reax
    MOVL    Reax,Redx
    MOVL    Reax,Rebx
    ret
CALLMACRO   RegMask mod_word,(M_Reax OR M_Rebx OR M_Redx)

raise_div_ex:
IFDEF WINDOWS
    jmp     FULLWORD ptr [RaiseDiv+Rebp]
ELSE
    jmp     *RaiseDiv[Rebp]
ENDIF

CALLMACRO INLINE_ROUTINE word_eq
    CMPL    Rebx,Reax
    jz      RetTrue         ;# True if they are equal.
    jmp     RetFalse
CALLMACRO   RegMask word_eq,(M_Reax)

CALLMACRO INLINE_ROUTINE word_neq
    CMPL    Rebx,Reax
    jz      RetFalse
    jmp     RetTrue
CALLMACRO   RegMask word_neq,(M_Reax)

CALLMACRO INLINE_ROUTINE word_geq
    CMPL    Rebx,Reax
    jnb     RetTrue
    jmp     RetFalse
CALLMACRO   RegMask word_geq,(M_Reax)

CALLMACRO INLINE_ROUTINE word_leq
    CMPL    Rebx,Reax
    jna     RetTrue
    jmp     RetFalse
CALLMACRO   RegMask word_leq,(M_Reax)

CALLMACRO INLINE_ROUTINE word_gtr
    CMPL    Rebx,Reax
    ja      RetTrue
    jmp     RetFalse
CALLMACRO   RegMask word_gtr,(M_Reax)

 CALLMACRO INLINE_ROUTINE word_lss
    CMPL    Rebx,Reax
    jb      RetTrue
    jmp     RetFalse
CALLMACRO   RegMask word_lss,(M_Reax)

;# Atomically increment the value at the address of the arg and return the
;# updated value.  Since the xadd instruction returns the original value
;# we have to increment it.
CALLMACRO INLINE_ROUTINE atomic_increment
atomic_incr:                    ;# Internal name in case "atomic_increment" is munged.
    MOVL    CONST 2,Rebx
    LOCKXADDL Rebx,[Reax]
    ADDL    CONST 2,Rebx
    MOVL    Rebx,Reax
    ret

CALLMACRO   RegMask atomic_incr,(M_Reax OR M_Rebx)

;# Atomically decrement the value at the address of the arg and return the
;# updated value.  Since the xadd instruction returns the original value
;# we have to decrement it.
CALLMACRO INLINE_ROUTINE atomic_decrement
atomic_decr:
    MOVL    CONST -2,Rebx
    LOCKXADDL Rebx,[Reax]
    MOVL    Rebx,Reax
    SUBL    CONST 2,Reax
    ret

CALLMACRO   RegMask atomic_decr,(M_Reax OR M_Rebx)

;# Reset a mutex to (tagged) one.  Because the increment and decrements
;# are atomic this doesn't have to do anything special.
CALLMACRO INLINE_ROUTINE atomic_reset
IFDEF WINDOWS
    mov     FULLWORD ptr [Reax],3 
ELSE
    MOVL    CONST 3,[Reax]
ENDIF
    MOVL    CONST UNIT,Reax  ;# The function returns unit
    ret

CALLMACRO   RegMask atomic_reset,M_Reax

;# Return the thread id object for the current thread
CALLMACRO INLINE_ROUTINE thread_self
    MOVL    ThreadId[Rebp],Reax
    ret
CALLMACRO   RegMask thread_self,(M_Reax)



;# Memory for LargeWord.word values.  This is the same as mem_for_real on
;# 64-bits but only a single word on 32-bits.
mem_for_largeword:
IFNDEF HOSTARCHITECTURE_X86_64
        MOVL    LocalMpointer[Rebp],Recx
        SUBL    CONST 8,Recx        ;# Length word (4 bytes) + 4 bytes
IFDEF TEST_ALLOC
;# Test case - this will always force a call into RTS.
        CMPL    LocalMpointer[Rebp],Recx
ELSE
        CMPL    LocalMbottom[Rebp],Recx
ENDIF
        jb      mem_for_real1
        MOVL    Recx,LocalMpointer[Rebp] ;# Updated allocation pointer
IFDEF WINDOWS
        mov     FULLWORD ptr (-4)[Recx],01000001h  ;# Length word:
ELSE
        MOVL    CONST 0x01000001,(-4)[Recx]     ;# Length word
ENDIF
        ret
ENDIF
;# Else if it is 64-bits just drop through

;# FLOATING POINT
;# If we have insufficient space for the result we call in to
;# main RTS to do the work.  The reason for this is that it is
;# not safe to make a call into memory allocator and then
;# continue with the rest of the floating point operation
;# because that would produce a return address pointing into the
;# assembly code itself.  It's possible that this is no longer
;# a problem.

mem_for_real:
;# Allocate memory for the result.
IFNDEF HOSTARCHITECTURE_X86_64
        MOVL    LocalMpointer[Rebp],Recx
        SUBL    CONST 12,Recx        ;# Length word (4 bytes) + 8 bytes
ELSE
        MOVL    R15,Recx
        SUBL    CONST 16,Recx        ;# Length word (8 bytes) + 8 bytes
ENDIF
IFDEF TEST_ALLOC
;# Test case - this will always force a call into RTS.
        CMPL    LocalMpointer[Rebp],Recx
ELSE
        CMPL    LocalMbottom[Rebp],Recx
ENDIF
        jb      mem_for_real1
IFNDEF HOSTARCHITECTURE_X86_64
        MOVL    Recx,LocalMpointer[Rebp] ;# Updated allocation pointer
IFDEF WINDOWS
        mov     FULLWORD ptr (-4)[Recx],01000002h  ;# Length word:
ELSE
        MOVL    CONST 0x01000002,(-4)[Recx]     ;# Two words plus tag
ENDIF
ELSE
        MOVL    Recx,R15                        ;# Updated allocation pointer
IFDEF WINDOWS
        mov    qword ptr (-8)[Recx],1   ;# One word
        mov    byte ptr (-1)[Recx],B_bytes  ;# Set the byte flag.
ELSE
        MOVL    CONST 1,(-8)[Recx]      ;# One word
        MOVB    CONST B_bytes,(-1)[Recx]    ;# Set the byte flag.
ENDIF
ENDIF
        ret
mem_for_real1:  ;# Not enough store: clobber bad value in ecx.
        MOVL   CONST 1,Recx
    ret


CALLMACRO INLINE_ROUTINE real_add
        call    mem_for_real
    jb      real_add_1     ;# Not enough space - call RTS.
;# Do the operation and put the result in the allocated
;# space.
IFDEF WINDOWS
    FLD     qword ptr [Reax]
    FADD    qword ptr [Rebx]
    FSTP    qword ptr [Recx]
ELSE
    FLDL    [Reax]
    FADDL   [Rebx]
    FSTPL   [Recx]
ENDIF
    MOVL    Recx,Reax
    ret

real_add_1:
    CALLMACRO   CALL_IO    POLY_SYS_Add_real
;# The mask includes FP7 rather than FP0 because this pushes a value which
;# overwrites the bottom of the stack.
CALLMACRO   RegMask real_add,(M_Reax OR M_Recx OR M_Redx OR M_FP7 OR Mask_all)



CALLMACRO INLINE_ROUTINE real_sub
        call    mem_for_real
    jb      real_sub_1     ;# Not enough space - call RTS.
;# Do the operation and put the result in the allocated
;# space.
IFDEF WINDOWS
    FLD     qword ptr [Reax]
    FSUB    qword ptr [Rebx]
    FSTP    qword ptr [Recx]
ELSE
    FLDL    [Reax]
    FSUBL   [Rebx]
    FSTPL   [Recx]
ENDIF
    MOVL    Recx,Reax
    ret

real_sub_1:
    CALLMACRO   CALL_IO    POLY_SYS_Sub_real

CALLMACRO   RegMask real_sub,(M_Reax OR M_Recx OR M_Redx OR M_FP7 OR Mask_all)


CALLMACRO INLINE_ROUTINE real_mul
        call    mem_for_real
    jb      real_mul_1     ;# Not enough space - call RTS.
;# Do the operation and put the result in the allocated
;# space.
IFDEF WINDOWS
    FLD     qword ptr [Reax]
    FMUL    qword ptr [Rebx]
    FSTP    qword ptr [Recx]
ELSE
    FLDL    [Reax]
    FMULL   [Rebx]
    FSTPL   [Recx]
ENDIF
    MOVL    Recx,Reax
    ret

real_mul_1:
    CALLMACRO   CALL_IO    POLY_SYS_Mul_real

CALLMACRO   RegMask real_mul,(M_Reax OR M_Recx OR M_Redx OR M_FP7 OR Mask_all)


CALLMACRO INLINE_ROUTINE real_div
        call    mem_for_real
    jb      real_div_1     ;# Not enough space - call RTS.
;# Do the operation and put the result in the allocated
;# space.
IFDEF WINDOWS
    FLD     qword ptr [Reax]
    FDIV    qword ptr [Rebx]
    FSTP    qword ptr [Recx]
ELSE
    FLDL    [Reax]
    FDIVL   [Rebx]
    FSTPL   [Recx]
ENDIF
    MOVL    Recx,Reax
    ret

real_div_1:
    CALLMACRO   CALL_IO    POLY_SYS_Div_real

CALLMACRO   RegMask real_div,(M_Reax OR M_Recx OR M_Redx OR M_FP7 OR Mask_all)


;# For all values except NaN it's possible to do this by a test such as
;# "if x < 0.0 then ~ x else x" but the test always fails for NaNs

CALLMACRO INLINE_ROUTINE real_abs
    call    mem_for_real
    jb      real_abs_1     ;# Not enough space - call RTS.
;# Do the operation and put the result in the allocated
;# space.
;# N.B. Real.~ X is not the same as 0.0 - X.  Real.~ 0.0 is ~0.0;
IFDEF WINDOWS
    FLD     qword ptr [Reax]
    FABS
    FSTP    qword ptr [Recx]
ELSE
    FLDL    [Reax]
    FABS
    FSTPL   [Recx]
ENDIF
    MOVL    Recx,Reax
    ret

real_abs_1:
    CALLMACRO   CALL_IO    POLY_SYS_Abs_real

CALLMACRO   RegMask real_abs,(M_Reax OR M_Recx OR M_Redx OR M_FP7 OR Mask_all)


CALLMACRO INLINE_ROUTINE real_neg
        call    mem_for_real
    jb      real_neg_1     ;# Not enough space - call RTS.
;# Do the operation and put the result in the allocated
;# space.
;# N.B. Real.~ X is not the same as 0.0 - X.  Real.~ 0.0 is ~0.0;
IFDEF WINDOWS
    FLD     qword ptr [Reax]
    FCHS
    FSTP    qword ptr [Recx]
ELSE
    FLDL    [Reax]
    FCHS
    FSTPL   [Recx]
ENDIF
    MOVL    Recx,Reax
    ret

real_neg_1:
    CALLMACRO   CALL_IO    POLY_SYS_Neg_real

CALLMACRO   RegMask real_neg,(M_Reax OR M_Recx OR M_Redx OR M_FP7 OR Mask_all)



CALLMACRO INLINE_ROUTINE real_eq
IFDEF WINDOWS
    FLD     qword ptr [Reax]
    FCOMP   qword ptr [Rebx]
ELSE
    FLDL    [Reax]
    FCOMPL  [Rebx]
ENDIF
        FNSTSW  R_ax
;# Not all 64-bit processors support SAHF.
;# The result is true if the zero flag is set and parity flag clear.  
        ANDL    CONST 17408,Reax ;# 0x4400
        CMPL    CONST 16384,Reax ;# 0x4000
    je      RetTrue
    jmp     RetFalse
CALLMACRO   RegMask real_eq,(M_Reax OR M_FP7)


CALLMACRO INLINE_ROUTINE real_neq
IFDEF WINDOWS
    FLD     qword ptr [Reax]
    FCOMP   qword ptr [Rebx]
ELSE
    FLDL    [Reax]
    FCOMPL  [Rebx]
ENDIF
        FNSTSW  R_ax
        ANDL    CONST 17408,Reax ;# 0x4400
        CMPL    CONST 16384,Reax ;# 0x4000
    jne     RetTrue
    jmp     RetFalse

CALLMACRO   RegMask real_neq,(M_Reax OR M_FP7)


CALLMACRO INLINE_ROUTINE real_lss
;# Compare Rebx > Reax
IFDEF WINDOWS
    FLD     qword ptr [Rebx]
    FCOMP   qword ptr [Reax]
ELSE
    FLDL    [Rebx]
    FCOMPL  [Reax]
ENDIF
        FNSTSW  R_ax

;# True if the carry flag (C0), zero flag (C3) and parity (C2) are all clear
        ANDL    CONST 17664,Reax ;# 0x4500

    je      RetTrue
    jmp     RetFalse

CALLMACRO   RegMask real_lss,(M_Reax OR M_FP7)


CALLMACRO INLINE_ROUTINE real_gtr
IFDEF WINDOWS
    FLD     qword ptr [Reax]
    FCOMP   qword ptr [Rebx]
ELSE
    FLDL    [Reax]
    FCOMPL  [Rebx]
ENDIF
        FNSTSW  R_ax

;# True if the carry flag (C0), zero flag (C3) and parity (C2) are all clear
        ANDL    CONST 17664,Reax ;# 0x4500

    je      RetTrue
    jmp     RetFalse

CALLMACRO   RegMask real_gtr,(M_Reax OR M_FP7)


CALLMACRO INLINE_ROUTINE real_leq
;# Compare Rebx > Reax
IFDEF WINDOWS
    FLD     qword ptr [Rebx]
    FCOMP   qword ptr [Reax]
ELSE
    FLDL    [Rebx]
    FCOMPL  [Reax]
ENDIF
        FNSTSW  R_ax
;# True if the carry flag (C0) and parity (C2) are both clear
        ANDL    CONST 1280,Reax ;# 0x500

    je      RetTrue
    jmp     RetFalse

CALLMACRO   RegMask real_leq,(M_Reax OR M_FP7)


CALLMACRO INLINE_ROUTINE real_geq
IFDEF WINDOWS
    FLD     qword ptr [Reax]
    FCOMP   qword ptr [Rebx]
ELSE
    FLDL    [Reax]
    FCOMPL  [Rebx]
ENDIF
        FNSTSW  R_ax
;# True if the carry flag (C0) and parity (C2) are both clear
        ANDL    CONST 1280,Reax ;# 0x500

    je      RetTrue
    jmp     RetFalse

CALLMACRO   RegMask real_geq,(M_Reax OR M_FP7)

CALLMACRO INLINE_ROUTINE real_from_int
    TESTL   CONST TAG,Reax   ;# Is it long ?
    jz      real_float_1
    call    mem_for_real
    jb      real_float_1     ;# Not enough space - call RTS.
    SARL    CONST TAGSHIFT,Reax ;# Untag the value
    MOVL    Reax,RealTemp[Rebp] ;# Save it in a temporary (N.B. It's now untagged)
IFDEF WINDOWS
    FILD    FULLWORD ptr RealTemp[Rebp]
    FSTP    qword ptr [Recx]
ELSE
IFDEF HOSTARCHITECTURE_X86_64
    FILDQ   RealTemp[Rebp]
ELSE
    FILDL   RealTemp[Rebp]
ENDIF
    FSTPL   [Recx]
ENDIF
    MOVL    Recx,Reax
    ret

real_float_1:
    CALLMACRO   CALL_IO    POLY_SYS_int_to_real

CALLMACRO   RegMask real_from_int,(M_Reax OR M_Recx OR M_Redx OR M_FP7 OR Mask_all)

;# Additional assembly code routines

;# This template code is copied into a newly allocated piece of memory which
;# is set up to look like an ML function.
;# The code itself is called if a function set up with exception_trace
;# returns normally.  It removes the handler.
CALLMACRO INLINE_ROUTINE X86AsmRestoreHandlerAfterExceptionTraceTemplate
    ADDL    CONST POLYWORDSIZE,Resp       ;# Remove handler
    POPL    HandlerRegister[Rebp]
    RET
    NOP                         ;# Add an extra byte so we have 8 bytes on both X86 and X86_64

;# This is template code and must be position independent.
;# The length of this code (9 bytes) is built into X86Dependent::BuildExceptionTrace.
CALLMACRO INLINE_ROUTINE X86AsmGiveExceptionTraceFnTemplate
    NOP                                 ;# Two NOPs - for alignment
    NOP
    ;# The exception packet is the first argument.
IFDEF WINDOWS
        mov     byte ptr [RequestCode+Rebp],POLY_SYS_give_ex_trace_fn
        jmp     FULLWORD ptr [IOEntryPoint+Rebp]
ELSE
        MOVB    CONST POLY_SYS_give_ex_trace_fn,RequestCode[Rebp]
        jmp     *IOEntryPoint[Rebp]
ENDIF

;# This is template code for an RTS call to kill the current thread. 
CALLMACRO INLINE_ROUTINE X86AsmKillSelfTemplate
IFDEF WINDOWS
        mov     byte ptr [RequestCode+Rebp],POLY_SYS_kill_self
        jmp     FULLWORD ptr [IOEntryPoint+Rebp]
ELSE
        MOVB    CONST POLY_SYS_kill_self,RequestCode[Rebp]
        jmp     *IOEntryPoint[Rebp]
ENDIF

CALLMACRO INLINE_ROUTINE X86AsmCallbackReturnTemplate
IFDEF WINDOWS
        mov     byte ptr [ReturnReason+Rebp],RETURN_CALLBACK_RETURN
        jmp     FULLWORD ptr [IOEntryPoint+Rebp]
ELSE
        MOVB    CONST RETURN_CALLBACK_RETURN,ReturnReason[Rebp]
        jmp     *IOEntryPoint[Rebp]
ENDIF

CALLMACRO INLINE_ROUTINE X86AsmCallbackExceptionTemplate
IFDEF WINDOWS
        mov     byte ptr [ReturnReason+Rebp],RETURN_CALLBACK_EXCEPTION
        jmp     FULLWORD ptr [IOEntryPoint+Rebp]
ELSE
        MOVB    CONST RETURN_CALLBACK_EXCEPTION,ReturnReason[Rebp]
        jmp     *IOEntryPoint[Rebp]
ENDIF

;# This implements atomic addition in the same way as atomic_increment
CALLMACRO INLINE_ROUTINE X86AsmAtomicIncrement
IFNDEF HOSTARCHITECTURE_X86_64
    MOVL    4[Resp],Reax
ELSE
IFDEF WINDOWS
    MOVL    Recx,Reax   ;# The argument to the function is passed in Recx
ELSE
IFDEF _WIN32
    MOVL    Recx,Reax   ;# The argument to the function is passed in Recx
ELSE
    MOVL    Redi,Reax   ;# On X86_64 the argument is passed in Redi
ENDIF
ENDIF
ENDIF
;# Use Recx and Reax because they are volatile (unlike Rebx on X86/64/Unix)
    MOVL    CONST 2,Recx
    LOCKXADDL Recx,[Reax]
    ADDL    CONST 2,Recx
    MOVL    Recx,Reax
    ret


;# This implements atomic subtraction in the same way as atomic_decrement
CALLMACRO INLINE_ROUTINE X86AsmAtomicDecrement
IFNDEF HOSTARCHITECTURE_X86_64
    MOVL    4[Resp],Reax
ELSE
    MOVL    Redi,Reax            ;# On X86_64 the argument is passed in Redi
ENDIF
    MOVL    CONST -2,Recx
    LOCKXADDL Recx,[Reax]
    MOVL    Recx,Reax
    SUBL    CONST 2,Reax
    ret

;# LargeWord.word operations.  These are 32 or 64-bit values in a single-word byte
;# memory cell.
CALLMACRO INLINE_ROUTINE eq_longword
    MOVL    [Reax],Reax
    CMPL    [Rebx],Reax
    jz      RetTrue         ;# True if they are equal.
    jmp     RetFalse
CALLMACRO   RegMask eq_longword,(M_Reax)

CALLMACRO INLINE_ROUTINE neq_longword
    MOVL    [Reax],Reax
    CMPL    [Rebx],Reax
    jz      RetFalse
    jmp     RetTrue
CALLMACRO   RegMask neq_longword,(M_Reax)

CALLMACRO INLINE_ROUTINE geq_longword
    MOVL    [Reax],Reax
    CMPL    [Rebx],Reax
    jnb     RetTrue
    jmp     RetFalse
CALLMACRO   RegMask geq_longword,(M_Reax)

CALLMACRO INLINE_ROUTINE leq_longword
    MOVL    [Reax],Reax
    CMPL    [Rebx],Reax
    jna     RetTrue
    jmp     RetFalse
CALLMACRO   RegMask leq_longword,(M_Reax)

CALLMACRO INLINE_ROUTINE gt_longword
    MOVL    [Reax],Reax
    CMPL    [Rebx],Reax
    ja      RetTrue
    jmp     RetFalse
CALLMACRO   RegMask gt_longword,(M_Reax)

CALLMACRO INLINE_ROUTINE lt_longword
    MOVL    [Reax],Reax
    CMPL    [Rebx],Reax
    jb      RetTrue
    jmp     RetFalse
CALLMACRO   RegMask lt_longword,(M_Reax)

CALLMACRO INLINE_ROUTINE longword_to_tagged
;# Load the value and tag it, discarding the top bit
    MOVL    [Reax],Reax
    CALLMACRO   MAKETAGGED  Reax,Reax
    ret
CALLMACRO   RegMask longword_to_tagged,(M_Reax)

CALLMACRO INLINE_ROUTINE signed_to_longword
;# Shift the value to remove the tag and store it.
    call    mem_for_largeword
    jb      signed_to_longword1
    SARL    CONST TAGSHIFT,Reax         ;# Arithmetic shift, preserve sign
    MOVL    Reax,[Recx]
    MOVL    Recx,Reax
    ret
signed_to_longword1:
    CALLMACRO   CALL_IO POLY_SYS_signed_to_longword
CALLMACRO   RegMask signed_to_longword,(M_Reax OR M_Recx OR Mask_all)

CALLMACRO INLINE_ROUTINE unsigned_to_longword
;# Shift the value to remove the tag and store it.
    call    mem_for_largeword
    jb      unsigned_to_longword1
    SHRL    CONST TAGSHIFT,Reax         ;# Logical shift, zero top bit
    MOVL    Reax,[Recx]
    MOVL    Recx,Reax
    ret
unsigned_to_longword1:
    CALLMACRO   CALL_IO POLY_SYS_unsigned_to_longword
CALLMACRO   RegMask unsigned_to_longword,(M_Reax OR M_Recx OR Mask_all)

CALLMACRO INLINE_ROUTINE plus_longword
    call    mem_for_largeword
    jb      plus_longword1
    MOVL    [Reax],Reax
    ADDL    [Rebx],Reax
    MOVL    Reax,[Recx]
    MOVL    Recx,Reax
    ret
plus_longword1:
    CALLMACRO   CALL_IO POLY_SYS_plus_longword
CALLMACRO   RegMask plus_longword,(M_Reax OR M_Recx OR Mask_all)

CALLMACRO INLINE_ROUTINE minus_longword
    call    mem_for_largeword
    jb      minus_longword1
    MOVL    [Reax],Reax
    SUBL    [Rebx],Reax
    MOVL    Reax,[Recx]
    MOVL    Recx,Reax
    ret
minus_longword1:
    CALLMACRO   CALL_IO POLY_SYS_minus_longword
CALLMACRO   RegMask minus_longword,(M_Reax OR M_Recx OR Mask_all)

CALLMACRO INLINE_ROUTINE mul_longword
    call    mem_for_largeword
    jb      mul_longword1
    MOVL    [Reax],Reax
IFDEF WINDOWS
    mul     FULLWORD ptr [Rebx]
ELSE
    MULL    [Rebx]
ENDIF
    MOVL    Reax,[Recx]
    MOVL    Recx,Reax
    MOVL    Reax,Redx           ;# clobber this which has the high-end result
    ret
mul_longword1:
    CALLMACRO   CALL_IO POLY_SYS_mul_longword
CALLMACRO   RegMask mul_longword,(M_Reax OR M_Recx OR M_Redx OR Mask_all)

CALLMACRO INLINE_ROUTINE div_longword
IFDEF WINDOWS
    cmp     FULLWORD ptr [Rebx],0
ELSE
    CMPL    CONST 0,[Rebx]
ENDIF
    jz      raise_div_ex
    call    mem_for_largeword
    jb      div_longword1
    MOVL    [Reax],Reax
    MOVL    CONST 0,Redx
IFDEF WINDOWS
    div     FULLWORD ptr [Rebx]
ELSE
    DIVL    [Rebx]
ENDIF
    MOVL    Reax,[Recx]         ;# Store the quotient
    MOVL    Recx,Reax
    MOVL    Reax,Redx           ;# clobber this which has the remainder
    ret
div_longword1:
    CALLMACRO   CALL_IO POLY_SYS_div_longword
CALLMACRO   RegMask div_longword,(M_Reax OR M_Recx OR M_Redx OR Mask_all)

CALLMACRO INLINE_ROUTINE mod_longword
IFDEF WINDOWS
    cmp     FULLWORD ptr [Rebx],0
ELSE
    CMPL    CONST 0,[Rebx]
ENDIF
    jz      raise_div_ex
    call    mem_for_largeword
    jb      mod_longword1
    MOVL    [Reax],Reax
    MOVL    CONST 0,Redx
IFDEF WINDOWS
    div     FULLWORD ptr [Rebx]
ELSE
    DIVL    [Rebx]
ENDIF
    MOVL    Redx,[Recx]         ;# Store the remainder
    MOVL    Recx,Reax
    MOVL    Reax,Redx           ;# clobber this which has the remainder
    ret
mod_longword1:
    CALLMACRO   CALL_IO POLY_SYS_mod_longword
CALLMACRO   RegMask mod_longword,(M_Reax OR M_Recx OR M_Redx OR Mask_all)

CALLMACRO INLINE_ROUTINE andb_longword
    call    mem_for_largeword
    jb      andb_longword1
    MOVL    [Reax],Reax
    ANDL    [Rebx],Reax
    MOVL    Reax,[Recx]
    MOVL    Recx,Reax
    ret
andb_longword1:
    CALLMACRO   CALL_IO POLY_SYS_andb_longword
CALLMACRO   RegMask andb_longword,(M_Reax OR M_Recx OR Mask_all)

CALLMACRO INLINE_ROUTINE orb_longword
    call    mem_for_largeword
    jb      orb_longword1
    MOVL    [Reax],Reax
    ORL     [Rebx],Reax
    MOVL    Reax,[Recx]
    MOVL    Recx,Reax
    ret
orb_longword1:
    CALLMACRO   CALL_IO POLY_SYS_orb_longword
CALLMACRO   RegMask orb_longword,(M_Reax OR M_Recx OR Mask_all)

CALLMACRO INLINE_ROUTINE xorb_longword
    call    mem_for_largeword
    jb      xorb_longword1
    MOVL    [Reax],Reax
    XORL    [Rebx],Reax
    MOVL    Reax,[Recx]
    MOVL    Recx,Reax
    ret
xorb_longword1:
    CALLMACRO   CALL_IO POLY_SYS_xorb_longword
CALLMACRO   RegMask xorb_longword,(M_Reax OR M_Recx OR Mask_all)

CALLMACRO INLINE_ROUTINE shift_left_longword
    call    mem_for_largeword
    jb      shift_left_longword1
    MOVL    Recx,Redx           ;# We need Recx for the shift
 ;# The shift value is always a Word.word value i.e. tagged
 ;# LargeWord.<<(a,b) is defined to return 0 if b > LargeWord.wordSize
IFNDEF HOSTARCHITECTURE_X86_64
    CMPL    CONST TAGGED(32),Rebx
ELSE
    CMPL    CONST TAGGED(64),Rebx
ENDIF
    jb      sllw1
    MOVL    CONST 0,Reax
    jmp     sllw2
sllw1:
    MOVL    Rebx,Recx
    SHRL    CONST TAGSHIFT,Recx ;# remove tag
    MOVL    [Reax],Reax
    SHLL    R_cl,Reax
sllw2:
    MOVL    Reax,[Redx]
    MOVL    Redx,Reax
    MOVL    Reax,Recx           ;# Clobber Recx
    ret
shift_left_longword1:
    CALLMACRO   CALL_IO POLY_SYS_shift_left_longword
CALLMACRO   RegMask shift_left_longword,(M_Reax OR M_Recx OR M_Redx OR Mask_all)

CALLMACRO INLINE_ROUTINE shift_right_longword
    call    mem_for_largeword
    jb      shift_right_longword1
    MOVL    Recx,Redx           ;# We need Recx for the shift
 ;# The shift value is always a Word.word value i.e. tagged
 ;# LargeWord.>>(a,b) is defined to return 0 if b > LargeWord.wordSize
IFNDEF HOSTARCHITECTURE_X86_64
    CMPL    CONST TAGGED(32),Rebx
ELSE
    CMPL    CONST TAGGED(64),Rebx
ENDIF
    jb      srlw1
    MOVL    CONST 0,Reax
    jmp     srlw2
srlw1:
    MOVL    Rebx,Recx
    SHRL    CONST TAGSHIFT,Recx ;# remove tag
    MOVL    [Reax],Reax
    SHRL    R_cl,Reax
srlw2:
    MOVL    Reax,[Redx]
    MOVL    Redx,Reax
    MOVL    Reax,Recx           ;# Clobber Recx
    ret
shift_right_longword1:
    CALLMACRO   CALL_IO POLY_SYS_shift_right_longword
CALLMACRO   RegMask shift_right_longword,(M_Reax OR M_Recx OR M_Redx OR Mask_all)

CALLMACRO INLINE_ROUTINE shift_right_arith_longword
    call    mem_for_largeword
    jb      shift_right_arith_longword1
    MOVL    Recx,Redx           ;# We need Recx for the shift
 ;# The shift value is always a Word.word value i.e. tagged
 ;# LargeWord.~>>(a,b) is defined to return 0 or ~1 if b > LargeWord.wordSize
IFNDEF HOSTARCHITECTURE_X86_64
    CMPL    CONST TAGGED(32),Rebx
ELSE
    CMPL    CONST TAGGED(64),Rebx
ENDIF
    jb      sralw1
    ;# Setting the shift to 31/63 propagates the sign bit
IFNDEF HOSTARCHITECTURE_X86_64
    MOVL    CONST TAGGED(31),Rebx
ELSE
    MOVL    CONST TAGGED(63),Rebx
ENDIF
sralw1:
    MOVL    Rebx,Recx
    SHRL    CONST TAGSHIFT,Recx ;# remove tag
    MOVL    [Reax],Reax
    SARL    R_cl,Reax
    MOVL    Reax,[Redx]
    MOVL    Redx,Reax
    MOVL    Reax,Recx           ;# Clobber Recx
    ret
shift_right_arith_longword1:
    CALLMACRO   CALL_IO POLY_SYS_shift_right_arith_longword
CALLMACRO   RegMask shift_right_arith_longword,(M_Reax OR M_Rebx OR M_Recx OR M_Redx OR Mask_all)

;# C-memory operations.
CALLMACRO INLINE_ROUTINE cmem_load_asm_8
    MOVL    [Reax],Reax             ;# The address is boxed.
    SARL    CONST TAGSHIFT,Rebx     ;# The offset is a signed tagged value
    ADDL    Rebx,Reax               ;# Add it in
IFNDEF HOSTARCHITECTURE_X86_64
    MOVL    4[Resp],Rebx            ;# Get the index.
ELSE
    MOVL    R8,Rebx                 ;# Get the index.
ENDIF
    SARL    CONST TAGSHIFT,Rebx     ;# That's also tagged
IFDEF WINDOWS
    movzx   Reax, byte ptr [Reax][Rebx]
ELSE
IFNDEF HOSTARCHITECTURE_X86_64
    movzbl  (Reax,Rebx,1),Reax
ELSE
    movzbq  (Reax,Rebx,1),Reax
ENDIF
ENDIF
CALLMACRO   MAKETAGGED  Reax,Reax
    MOVL    Reax,Rebx       ;# Clobber bad value in %Rebx
    RET3
CALLMACRO   RegMask cmem_load_8,(M_Reax OR M_Rebx)

CALLMACRO INLINE_ROUTINE cmem_load_asm_16
    MOVL    [Reax],Reax             ;# The address is boxed.
    SARL    CONST TAGSHIFT,Rebx     ;# The offset is a signed tagged value
    ADDL    Rebx,Reax               ;# Add it in
IFNDEF HOSTARCHITECTURE_X86_64
    MOVL    4[Resp],Rebx            ;# Get the index.
ELSE
    MOVL    R8,Rebx                 ;# Get the index.
ENDIF
    ;# The index is tagged but since we want to multiply by two we don't need anything here.
IFDEF WINDOWS
    movzx   Reax, word ptr [Reax-1][Rebx]
ELSE
IFNDEF HOSTARCHITECTURE_X86_64
    movzwl  -1(Reax,Rebx,1),Reax
ELSE
    movzwq  -1(Reax,Rebx,1),Reax
ENDIF
ENDIF
CALLMACRO   MAKETAGGED  Reax,Reax
    RET3
CALLMACRO   RegMask cmem_load_16,(M_Reax OR M_Rebx)

CALLMACRO INLINE_ROUTINE cmem_load_asm_32
IFDEF HOSTARCHITECTURE_X86_64
;# 64-bit mode - the result is tagged
    MOVL    [Reax],Reax             ;# The address is boxed.
    SARL    CONST TAGSHIFT,Rebx     ;# The offset is a signed tagged value
    ADDL    Rebx,Reax               ;# Add it in
IFDEF WINDOWS
    mov     eax, dword ptr [Reax-2][R8*2]
ELSE
    movl    -2(Reax,R8,2),%eax
ENDIF
CALLMACRO   MAKETAGGED  Reax,Reax
    MOVL    Reax,Rebx       ;# Clobber bad value in %Rebx
    RET3

CALLMACRO   RegMask cmem_load_32,(M_Reax OR M_Rebx)

ELSE
;# 32-bit mode - the result is boxed
    call    mem_for_largeword
    jb      cmem_load_32_1
    MOVL    [Reax],Reax             ;# The address is boxed.
    SARL    CONST TAGSHIFT,Rebx     ;# The offset is a signed tagged value
    ADDL    Rebx,Reax               ;# Add it in
    MOVL    4[Resp],Rebx            ;# Get the index.
    MOVL    (-2)[Reax+Rebx*2],Reax
    MOVL    Reax,[Recx]             ;# Save in the new memory
    MOVL    Recx,Reax               ;# Copy the result address
    RET3

cmem_load_32_1:
    CALLMACRO   CALL_IO POLY_SYS_cmem_load_32
CALLMACRO   RegMask cmem_load_32,(M_Reax OR M_Rebx OR M_Recx OR Mask_all)
ENDIF

CALLMACRO INLINE_ROUTINE cmem_load_asm_64 ;# The result is boxed in 64-bit mode. Not implemented in 32-bit mode
IFDEF HOSTARCHITECTURE_X86_64
    call    mem_for_largeword
    jb      cmem_load_64_1
    MOVL    [Reax],Reax             ;# The address is boxed.
    SARL    CONST TAGSHIFT,Rebx     ;# The offset is a signed tagged value
    ADDL    Rebx,Reax               ;# Add it in
    MOVL    (-4)[Reax+R8*4],Reax
    MOVL    Reax,[Recx]             ;# Save in the new memory
    MOVL    Recx,Reax               ;# Copy the result address
    MOVL    Reax,Rebx               ;# Clobber bad value
    RET3

cmem_load_64_1:
    CALLMACRO   CALL_IO POLY_SYS_cmem_load_64
CALLMACRO   RegMask cmem_load_64,(M_Reax OR M_Rebx OR M_Recx OR Mask_all)
ENDIF

CALLMACRO INLINE_ROUTINE cmem_load_asm_float
    call    mem_for_real
    jb      cmem_load_float1
    MOVL    [Reax],Reax             ;# The address is boxed.
    SARL    CONST TAGSHIFT,Rebx     ;# The offset is a signed tagged value
    ADDL    Rebx,Reax               ;# Add it in
IFNDEF HOSTARCHITECTURE_X86_64
    MOVL    4[Resp],Rebx            ;# Get the index.
ELSE
    MOVL    R8,Rebx                 ;# Get the index.
ENDIF
IFDEF WINDOWS
    FLD     dword ptr [Reax-2][Rebx*2]
    FSTP    qword ptr [Recx]
ELSE
    FLDS    -2(Reax,Rebx,2)
    FSTPL   [Recx]
ENDIF
    MOVL    Recx,Reax
    RET3
cmem_load_float1:
     CALLMACRO   CALL_IO POLY_SYS_cmem_load_float
CALLMACRO   RegMask cmem_load_float,(M_Reax OR M_Rebx OR M_Recx OR M_FP7 OR Mask_all)

CALLMACRO INLINE_ROUTINE cmem_load_asm_double
    call    mem_for_real
    jb      cmem_load_double1
    MOVL    [Reax],Reax             ;# The address is boxed.
    SARL    CONST TAGSHIFT,Rebx     ;# The offset is a signed tagged value
    ADDL    Rebx,Reax               ;# Add it in
IFNDEF HOSTARCHITECTURE_X86_64
    MOVL    4[Resp],Rebx            ;# Get the index.
ELSE
    MOVL    R8,Rebx                 ;# Get the index.
ENDIF
IFDEF WINDOWS
    FLD     qword ptr [Reax-4][Rebx*4]
    FSTP    qword ptr [Recx]
ELSE
    FLDL    -4(Reax,Rebx,4)
    FSTPL   [Recx]
ENDIF
    MOVL    Recx,Reax
    RET3

cmem_load_double1:
     CALLMACRO   CALL_IO POLY_SYS_cmem_load_double
CALLMACRO   RegMask cmem_load_double,(M_Reax OR M_Rebx OR M_Recx OR M_FP7 OR Mask_all)
   
CALLMACRO INLINE_ROUTINE cmem_store_asm_8
    MOVL    [Reax],Reax             ;# The address is boxed.
    SARL    CONST TAGSHIFT,Rebx     ;# The offset is a signed tagged value
    ADDL    Rebx,Reax               ;# Add it in
IFNDEF HOSTARCHITECTURE_X86_64
    MOVL    8[Resp],Rebx            ;# Get the index.
    MOVL    4[Resp],Recx            ;# Get the value to store
ELSE
    MOVL    R8,Rebx                 ;# Get the index.
    MOVL    R9,Recx
ENDIF
    SARL    CONST TAGSHIFT,Rebx     ;# That's also tagged
    SARL    CONST TAGSHIFT,Recx
    MOVB    R_cl,[Reax+Rebx]
    MOVL    CONST UNIT,Reax             ;# The function returns unit
    MOVL    Reax,Rebx                   ;# Clobber bad value in %Rebx
    MOVL    Reax,Recx                   ;# and %Recx
    RET4
CALLMACRO   RegMask cmem_store_8,(M_Reax OR M_Rebx OR M_Recx)

CALLMACRO INLINE_ROUTINE cmem_store_asm_16
    MOVL    [Reax],Reax             ;# The address is boxed.
    SARL    CONST TAGSHIFT,Rebx     ;# The offset is a signed tagged value
    ADDL    Rebx,Reax               ;# Add it in
IFNDEF HOSTARCHITECTURE_X86_64
    MOVL    8[Resp],Rebx            ;# Get the index.
    MOVL    4[Resp],Recx            ;# Get the value to store
ELSE
    MOVL    R8,Rebx                 ;# Get the index.
    MOVL    R9,Recx
ENDIF
    SARL    CONST TAGSHIFT,Recx     ;# Untag the value to store
IFDEF WINDOWS
    mov     word ptr [Reax-1][Rebx],cx
ELSE
    movw    %cx,-1(Reax,Rebx,1)
ENDIF
    MOVL    CONST UNIT,Reax             ;# The function returns unit
    MOVL    Reax,Recx                   ;# Bad value in %Recx
    RET4
CALLMACRO   RegMask cmem_store_16,(M_Reax OR M_Rebx OR M_Recx)

CALLMACRO INLINE_ROUTINE cmem_store_asm_32
    MOVL    [Reax],Reax             ;# The address is boxed.
    SARL    CONST TAGSHIFT,Rebx     ;# The offset is a signed tagged value
    ADDL    Rebx,Reax               ;# Add it in
IFNDEF HOSTARCHITECTURE_X86_64
    MOVL    8[Resp],Rebx            ;# Get the index.
    MOVL    4[Resp],Recx            ;# Get the value to store
    MOVL    [Recx],Recx
ELSE
    MOVL    R8,Rebx                 ;# Get the index.
    MOVL    R9,Recx
    SARL    CONST TAGSHIFT,Recx     ;# Untag the value to store
ENDIF
IFDEF WINDOWS
    mov     dword ptr [Reax-2][Rebx*2],ecx
ELSE
    movl    %ecx,-2(Reax,Rebx,2)
ENDIF
    MOVL    CONST UNIT,Reax             ;# The function returns unit
    MOVL    Reax,Recx                   ;# Bad value in %Recx
    RET4
CALLMACRO   RegMask cmem_store_32,(M_Reax OR M_Rebx OR M_Recx)

CALLMACRO INLINE_ROUTINE cmem_store_asm_64 ;# The value is boxed in 64-bit mode. Not implemented in 32-bit mode
IFDEF HOSTARCHITECTURE_X86_64
    MOVL    [Reax],Reax             ;# The address is boxed.
    SARL    CONST TAGSHIFT,Rebx     ;# The offset is a signed tagged value
    ADDL    Rebx,Reax               ;# Add it in
    MOVL    [R9],Rebx               ;# Value to store
    MOVL    Rebx,(-4)[Reax+R8*4]    ;# Store it
    MOVL    CONST UNIT,Reax         ;# The function returns unit
    MOVL    Reax,Rebx               ;# Bad value in %Rebx
    RET4

CALLMACRO   RegMask cmem_store_64,(M_Reax OR M_Rebx OR M_Recx)
ENDIF

CALLMACRO INLINE_ROUTINE cmem_store_asm_float
    MOVL    [Reax],Reax             ;# The address is boxed.
    SARL    CONST TAGSHIFT,Rebx     ;# The offset is a signed tagged value
    ADDL    Rebx,Reax               ;# Add it in
IFNDEF HOSTARCHITECTURE_X86_64
    MOVL    8[Resp],Rebx            ;# Get the index.
    MOVL    4[Resp],Recx            ;# Get the address of the real
ELSE
    MOVL    R8,Rebx                 ;# Get the index.
    MOVL    R9,Recx
ENDIF
IFDEF WINDOWS
    FLD     qword ptr [Recx] 
    FSTP    dword ptr [Reax-2][Rebx*2]
ELSE
    FLDL    [Recx]
    FSTPS    -2(Reax,Rebx,2)
ENDIF
    MOVL    CONST UNIT,Reax         ;# The function returns unit
    MOVL    Reax,Rebx               ;# Bad value in %Rebx
    RET4
CALLMACRO   RegMask cmem_store_float,(M_Reax OR M_Rebx OR M_Recx OR M_FP7)

CALLMACRO INLINE_ROUTINE cmem_store_asm_double
    MOVL    [Reax],Reax             ;# The address is boxed.
    SARL    CONST TAGSHIFT,Rebx     ;# The offset is a signed tagged value
    ADDL    Rebx,Reax               ;# Add it in
IFNDEF HOSTARCHITECTURE_X86_64
    MOVL    8[Resp],Rebx            ;# Get the index.
    MOVL    4[Resp],Recx            ;# Get the address of the real
ELSE
    MOVL    R8,Rebx                 ;# Get the index.
    MOVL    R9,Recx
ENDIF
IFDEF WINDOWS
    FLD     qword ptr [Recx] 
    FSTP    qword ptr [Reax-4][Rebx*4]
ELSE
    FLDL    [Recx]
    FSTPL    -4(Reax,Rebx,4)
ENDIF
    MOVL    CONST UNIT,Reax         ;# The function returns unit
    MOVL    Reax,Rebx               ;# Bad value in %Rebx
    RET4
CALLMACRO   RegMask cmem_store_double,(M_Reax OR M_Rebx OR M_Recx OR M_FP7)


IFDEF WINDOWS

CREATE_IO_CALL  MACRO index
    INLINE_ROUTINE  Call&index&
    CALL_IO index
    ENDM

CREATE_EXTRA_CALL MACRO index
    INLINE_ROUTINE  X86AsmCallExtra&index&
    CALL_EXTRA index
    ENDM

ELSE

#define CREATE_IO_CALL(index) \
    INLINE_ROUTINE(Call##index##) \
    CALL_IO(index)

#define CREATE_EXTRA_CALL(index) \
    INLINE_ROUTINE(X86AsmCallExtra##index##) \
    CALL_EXTRA(index)

ENDIF

CALLMACRO CREATE_IO_CALL  POLY_SYS_exit
CALLMACRO CREATE_IO_CALL  POLY_SYS_chdir
CALLMACRO CREATE_IO_CALL  POLY_SYS_get_flags
CALLMACRO CREATE_IO_CALL  POLY_SYS_exception_trace_fn
CALLMACRO CREATE_IO_CALL  POLY_SYS_profiler
CALLMACRO CREATE_IO_CALL  POLY_SYS_Real_str
CALLMACRO CREATE_IO_CALL  POLY_SYS_Real_Dispatch
CALLMACRO CREATE_IO_CALL  POLY_SYS_conv_real
CALLMACRO CREATE_IO_CALL  POLY_SYS_real_to_int
CALLMACRO CREATE_IO_CALL  POLY_SYS_sqrt_real
CALLMACRO CREATE_IO_CALL  POLY_SYS_sin_real
CALLMACRO CREATE_IO_CALL  POLY_SYS_signal_handler
CALLMACRO CREATE_IO_CALL  POLY_SYS_os_specific
CALLMACRO CREATE_IO_CALL  POLY_SYS_network
CALLMACRO CREATE_IO_CALL  POLY_SYS_io_dispatch
CALLMACRO CREATE_IO_CALL  POLY_SYS_poly_specific
CALLMACRO CREATE_IO_CALL  POLY_SYS_set_code_constant
CALLMACRO CREATE_IO_CALL  POLY_SYS_code_flags
CALLMACRO CREATE_IO_CALL  POLY_SYS_shrink_stack
CALLMACRO CREATE_IO_CALL  POLY_SYS_process_env
CALLMACRO CREATE_IO_CALL  POLY_SYS_callcode_tupled
CALLMACRO CREATE_IO_CALL  POLY_SYS_foreign_dispatch
CALLMACRO CREATE_IO_CALL  POLY_SYS_ffi
CALLMACRO CREATE_IO_CALL  POLY_SYS_stack_trace
CALLMACRO CREATE_IO_CALL  POLY_SYS_full_gc
CALLMACRO CREATE_IO_CALL  POLY_SYS_XWindows
CALLMACRO CREATE_IO_CALL  POLY_SYS_timing_dispatch
CALLMACRO CREATE_IO_CALL  POLY_SYS_showsize
CALLMACRO CREATE_IO_CALL  POLY_SYS_objsize
CALLMACRO CREATE_IO_CALL  POLY_SYS_kill_self
CALLMACRO CREATE_IO_CALL  POLY_SYS_thread_dispatch
CALLMACRO CREATE_IO_CALL  POLY_SYS_io_operation
CALLMACRO CREATE_IO_CALL  POLY_SYS_ln_real
CALLMACRO CREATE_IO_CALL  POLY_SYS_exp_real
CALLMACRO CREATE_IO_CALL  POLY_SYS_arctan_real
CALLMACRO CREATE_IO_CALL  POLY_SYS_cos_real

CALLMACRO CREATE_EXTRA_CALL RETURN_HEAP_OVERFLOW
CALLMACRO CREATE_EXTRA_CALL RETURN_STACK_OVERFLOW
CALLMACRO CREATE_EXTRA_CALL RETURN_STACK_OVERFLOWEX
CALLMACRO CREATE_EXTRA_CALL RETURN_RAISE_DIV
CALLMACRO CREATE_EXTRA_CALL RETURN_ARB_EMULATION

;# Register mask vector. - extern int registerMaskVector[];
;# Each entry in this vector is a set of the registers modified
;# by the function.  It is an untagged bitmap with the registers
;# encoded in the same way as the 
IFDEF WINDOWS
    align   4
    PUBLIC  registerMaskVector
registerMaskVector  dd  Mask_all                ;# 0 is unused
ELSE
        GLOBAL EXTNAME(registerMaskVector)
EXTNAME(registerMaskVector):
#define dd  .long
    dd  Mask_all                ;# 0 is unused
ENDIF
    dd  Mask_all                 ;# 1
    dd  Mask_all                 ;# 2
    dd  Mask_all                 ;# 3 is unused
    dd  Mask_all                 ;# 4 is unused
    dd  Mask_all                 ;# 5 is unused
    dd  Mask_all                 ;# 6
    dd  Mask_all                 ;# 7 is unused
    dd  Mask_all                 ;# 8 is unused
    dd  Mask_all                 ;# 9
    dd  Mask_all                 ;# 10 is unused
    dd  Mask_alloc_store         ;# 11
    dd  Mask_alloc_uninit        ;# 12
    dd  Mask_all                 ;# return = 13
    dd  Mask_all                 ;# raisex = 14
    dd  Mask_get_length          ;# 15
    dd  Mask_all                 ;# 16 is unused
    dd  Mask_all                 ;# 17
    dd  Mask_all                 ;# 18 is no longer used
    dd  Mask_all                 ;# 19 is no longer used
    dd  Mask_all                 ;# 20 is no longer used
    dd  Mask_all                 ;# 21 is unused
    dd  Mask_all                 ;# 22 is unused
    dd  Mask_str_compare         ;# 23
    dd  Mask_all                 ;# 24 is unused
    dd  Mask_all                 ;# 25 is unused
    dd  Mask_teststrgtr          ;# 26
    dd  Mask_teststrlss          ;# 27
    dd  Mask_teststrgeq          ;# 28
    dd  Mask_teststrleq          ;# 29
    dd  Mask_all                 ;# 30
    dd  Mask_all                 ;# 31 is no longer used
    dd  Mask_all                 ;# exception_trace_fn 32
    dd  Mask_all                 ;# 33 is no longer used
    dd  Mask_all                 ;# 34 is no longer used
    dd  Mask_all                 ;# 35 is no longer used
    dd  Mask_all                 ;# 36 is no longer used
    dd  Mask_all                 ;# 37 is unused
    dd  Mask_all                 ;# 38 is unused
    dd  Mask_all                 ;# 39 is unused
    dd  Mask_all                 ;# 40
    dd  Mask_all                 ;# 41 is unused
    dd  Mask_all                 ;# 42
    dd  Mask_all                 ;# 43
    dd  Mask_all                 ;# 44 is no longer used
    dd  Mask_all                 ;# 45 is no longer used
    dd  Mask_all                 ;# 46
    dd  Mask_lockseg             ;# 47
    dd  Mask_all                 ;# nullorzero = 48
    dd  Mask_all                 ;# 49 is no longer used
    dd  Mask_all                 ;# 50 is no longer used
    dd  Mask_all                 ;# 51
    dd  Mask_all                 ;# 52
    dd  Mask_eq_longword         ;# 53
    dd  Mask_neq_longword        ;# 54
    dd  Mask_geq_longword        ;# 55
    dd  Mask_leq_longword        ;# 56
    dd  Mask_gt_longword         ;# 57
    dd  Mask_lt_longword         ;# 58
    dd  Mask_all                 ;# 59 is unused
    dd  Mask_all                 ;# 60 is unused
    dd  Mask_all                 ;# 61
    dd  Mask_all                 ;# 62
    dd  Mask_all                 ;# 63 is unused
    dd  Mask_all                 ;# 64 is unused
    dd  Mask_all                 ;# 65 is unused
    dd  Mask_all                 ;# 66 is unused
    dd  Mask_all                 ;# 67 is unused
    dd  Mask_all                 ;# 68 is unused
    dd  Mask_atomic_reset        ;# 69
    dd  Mask_atomic_incr         ;# 70
    dd  Mask_atomic_decr         ;# 71
    dd  Mask_thread_self         ;# 72
    dd  Mask_all                 ;# 73
    dd  Mask_plus_longword       ;# 74
    dd  Mask_minus_longword      ;# 75
    dd  Mask_mul_longword        ;# 76
    dd  Mask_div_longword        ;# 77
    dd  Mask_mod_longword        ;# 78
    dd  Mask_andb_longword       ;# 79
    dd  Mask_orb_longword        ;# 80
    dd  Mask_xorb_longword       ;# 81
    dd  Mask_all                 ;# 82 is unused
    dd  Mask_all                 ;# 83 is now unused
    dd  Mask_all                 ;# 84
    dd  Mask_shift_left_longword ;# 85
    dd  Mask_shift_right_longword ;# 86
    dd  Mask_shift_right_arith_longword ;# 87
    dd  Mask_all                 ;# 88
    dd  Mask_longword_to_tagged  ;# 89
    dd  Mask_signed_to_longword  ;# 90
    dd  Mask_unsigned_to_longword ;# 91
    dd  Mask_all                 ;# 92
    dd  Mask_all                 ;# 93
    dd  Mask_all                 ;# 94
    dd  Mask_all                 ;# 95 is unused
    dd  Mask_all                 ;# 96 is unused
    dd  Mask_all                 ;# 97 is unused
    dd  Mask_all                 ;# 98
    dd  Mask_all                 ;# 99
    dd  Mask_all                 ;# 100
    dd  Mask_all                 ;# 101 is unused
    dd  Mask_all                 ;# 102 is unused
    dd  Mask_all                 ;# 103
    dd  Mask_quotrem             ;# 104
    dd  Mask_is_short            ;# 105
    dd  Mask_aplus               ;# 106
    dd  Mask_aminus              ;# 107
    dd  Mask_amul                ;# 108
    dd  Mask_adiv                ;# 109
    dd  Mask_amod                ;# 110
    dd  Mask_aneg                ;# 111
    dd  Mask_xora                ;# 112
    dd  Mask_equala              ;# 113
    dd  Mask_ora                 ;# 114
    dd  Mask_anda                ;# 115
    dd  Mask_all                 ;# 116 is unused
    dd  Mask_all                 ;# 117
    dd  Mask_real_geq            ;# 118
    dd  Mask_real_leq            ;# 119
    dd  Mask_real_gtr            ;# 120
    dd  Mask_real_lss            ;# 121
    dd  Mask_real_eq             ;# 122
    dd  Mask_real_neq            ;# 123
    dd  Mask_all                 ;# 124
    dd  Mask_real_add            ;# 125
    dd  Mask_real_sub            ;# 126
    dd  Mask_real_mul            ;# 127
    dd  Mask_real_div            ;# 128
    dd  Mask_real_abs            ;# 129
    dd  Mask_real_neg            ;# 130
    dd  Mask_all                 ;# 131 is unused
    dd  Mask_all                 ;# 132
    dd  Mask_all                 ;# 133
    dd  Mask_all                 ;# 134
    dd  Mask_real_from_int       ;# 135
    dd  Mask_all                 ;# 136
    dd  Mask_all                 ;# 137
    dd  Mask_all                 ;# 138
    dd  Mask_all                 ;# 139
    dd  Mask_all                 ;# 140
    dd  Mask_all                 ;# 141
    dd  Mask_all                 ;# 142 is no longer used
    dd  Mask_all                 ;# 143 is unused
    dd  Mask_all                 ;# 144 is unused
    dd  Mask_all                 ;# 145 is unused
    dd  Mask_all                 ;# 146 is unused
    dd  Mask_all                 ;# 147 is unused
    dd  Mask_all                 ;# stdin = 148
    dd  Mask_all                 ;# stdout= 149
    dd  Mask_all                 ;# 150
    dd  Mask_set_string_length   ;# 151
    dd  Mask_get_first_long_word ;# 152
    dd  Mask_all                 ;# poly_specific = 153
    dd  Mask_bytevec_eq          ;# 154
    dd  Mask_all                 ;# 155 is unused
    dd  Mask_all                 ;# 156 is unused
    dd  Mask_all                 ;# 157 is unused
    dd  Mask_all                 ;# 158 is unused
    dd  Mask_all                 ;# 159 is unused
    dd  Mask_cmem_load_8         ;# 160
    dd  Mask_cmem_load_16        ;# 161
    dd  Mask_cmem_load_32        ;# 162
IFDEF HOSTARCHITECTURE_X86_64
    dd  Mask_cmem_load_64        ;# 163
ELSE
    dd  Mask_all                 ;# 169
ENDIF
    dd  Mask_cmem_load_float     ;# 164
    dd  Mask_cmem_load_double    ;# 165
    dd  Mask_cmem_store_8        ;# 166
    dd  Mask_cmem_store_16       ;# 167
    dd  Mask_cmem_store_32       ;# 168
IFDEF HOSTARCHITECTURE_X86_64
    dd  Mask_cmem_store_64       ;# 169
ELSE
    dd  Mask_all                 ;# 169
ENDIF
    dd  Mask_cmem_store_float    ;# 170
    dd  Mask_cmem_store_double   ;# 171
    dd  Mask_all                 ;# 172 is unused
    dd  Mask_all                 ;# 173 is unused
    dd  Mask_all                 ;# 174 is unused
    dd  Mask_all                 ;# 175 is unused
    dd  Mask_all                 ;# 176 is unused
    dd  Mask_all                 ;# 177 is unused
    dd  Mask_all                 ;# 178 is unused
    dd  Mask_all                 ;# 179 is unused
    dd  Mask_all                 ;# 180 is unused
    dd  Mask_all                 ;# 181 is unused
    dd  Mask_all                 ;# 182 is unused
    dd  Mask_all                 ;# 183 is unused
    dd  Mask_all                 ;# 184 is unused
    dd  Mask_all                 ;# 185 is unused
    dd  Mask_all                 ;# 186 is unused
    dd  Mask_all                 ;# 187 is unused
    dd  Mask_all                 ;# 188 is unused
    dd  Mask_all                 ;# 189
    dd  Mask_all                 ;# 190
    dd  Mask_all                 ;# 191 is no longer used
    dd  Mask_all                 ;# 192 is unused
    dd  Mask_move_words          ;# 193
    dd  Mask_all                 ;# 194
    dd  Mask_move_words          ;# 195
    dd  Mask_shift_right_arith_word  ;# 196
    dd  Mask_int_to_word         ;# 197
    dd  Mask_move_bytes          ;# 198
    dd  Mask_move_bytes          ;# 199
    dd  Mask_all                 ;# 200
    dd  Mask_all                 ;# 201
    dd  Mask_all                 ;# stderr = 202
    dd  Mask_all                 ;# 203 now unused
    dd  Mask_all                 ;# 204
    dd  Mask_all                 ;# 205
    dd  Mask_all                 ;# 206
    dd  Mask_all                 ;# 207 is unused
    dd  Mask_all                 ;# 208 now unused
    dd  Mask_all                 ;# 209
    dd  Mask_all                 ;# 210 is unused
    dd  Mask_all                 ;# 211 is unused
    dd  Mask_all                 ;# 212 is unused
    dd  Mask_is_big_endian       ;# 213
    dd  Mask_bytes_per_word      ;# 214
    dd  Mask_offset_address      ;# 215
    dd  Mask_shift_right_word    ;# 216
    dd  Mask_word_neq            ;# 217
    dd  Mask_not_bool            ;# 218
    dd  Mask_all                 ;# 219 is unused
    dd  Mask_all                 ;# 220 is unused
    dd  Mask_all                 ;# 221 is unused
    dd  Mask_all                 ;# 222 is unused
    dd  Mask_string_length       ;# 223
    dd  Mask_all                 ;# 224 is unused
    dd  Mask_all                 ;# 225 is unused
    dd  Mask_all                 ;# 226 is unused
    dd  Mask_all                 ;# 227 is unused
    dd  Mask_touch_final         ;# 228
    dd  Mask_all                 ;# 229 - no longer used
    dd  Mask_all                 ;# 230 - no longer used
    dd  Mask_int_geq             ;# 231
    dd  Mask_int_leq             ;# 232
    dd  Mask_int_gtr             ;# 233
    dd  Mask_int_lss             ;# 234
    dd  Mask_load_byte           ;# load_byte_immut = 235
    dd  Mask_load_word           ;# load_word_immut = 236
    dd  Mask_all                 ;# 237 is unused
    dd  Mask_mul_word            ;# 238
    dd  Mask_plus_word           ;# 239
    dd  Mask_minus_word          ;# 240
    dd  Mask_div_word            ;# 241
    dd  Mask_or_word             ;# 242
    dd  Mask_and_word            ;# 243
    dd  Mask_xor_word            ;# 244
    dd  Mask_shift_left_word     ;# 245
    dd  Mask_mod_word            ;# 246
    dd  Mask_word_geq            ;# 247
    dd  Mask_word_leq            ;# 248
    dd  Mask_word_gtr            ;# 249
    dd  Mask_word_lss            ;# 250
    dd  Mask_word_eq             ;# 251
    dd  Mask_load_byte           ;# 252
    dd  Mask_load_word           ;# 253
    dd  Mask_assign_byte         ;# 254
    dd  Mask_assign_word         ;# 255

END