mirror of
git://repo.or.cz/tinycc.git
synced 2026-06-17 15:44:18 +08:00
Compare commits
1420 Commits
release_0_
...
mob
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a338258d30 | ||
|
|
fb4077f2da | ||
|
|
724b24eeb4 | ||
|
|
d8aee9b26e | ||
|
|
b8f680a3b4 | ||
|
|
1444843fd1 | ||
|
|
6b53465347 | ||
|
|
3b1fe97a59 | ||
|
|
904e95cbdf | ||
|
|
601a088214 | ||
|
|
1a54e47dda | ||
|
|
37b7247796 | ||
|
|
6a7c3df4d5 | ||
|
|
757507eb02 | ||
|
|
6728a64f1b | ||
|
|
256b4ef63c | ||
|
|
8502540b4a | ||
|
|
841ce0da03 | ||
|
|
8abaf10ab5 | ||
|
|
11f5c6e1f9 | ||
|
|
ea26b85ac0 | ||
|
|
8443e25bf5 | ||
|
|
fad812360b | ||
|
|
2888e49f39 | ||
|
|
c77339ab41 | ||
|
|
7f764f340f | ||
|
|
a672babc6f | ||
|
|
44977b0de8 | ||
|
|
6daf1617ef | ||
|
|
923fba83f1 | ||
|
|
7e01b20362 | ||
|
|
016087c954 | ||
|
|
f8011ea9b7 | ||
|
|
199369bb17 | ||
|
|
3935c3bb55 | ||
|
|
273978b927 | ||
|
|
2a33daedca | ||
|
|
3257afa160 | ||
|
|
419b527657 | ||
|
|
5c2240a896 | ||
|
|
366569eb7a | ||
|
|
ff917c09aa | ||
|
|
9f0915a506 | ||
|
|
69c8e92566 | ||
|
|
30afb50e64 | ||
|
|
576cd2a923 | ||
|
|
44e6853cb1 | ||
|
|
5c728d6506 | ||
|
|
90d17c9748 | ||
|
|
99713bcbfa | ||
|
|
303badef22 | ||
|
|
41bcb4a78f | ||
|
|
f459aff5f6 | ||
|
|
ea823189d6 | ||
|
|
03d58b0746 | ||
|
|
ff5d3b4874 | ||
|
|
d9a6d9aec0 | ||
|
|
a66ac623b2 | ||
|
|
4768b11737 | ||
|
|
b39da9f6fa | ||
|
|
5675177b7f | ||
|
|
543d84c668 | ||
|
|
9b8765d8ba | ||
|
|
7b92d2dcd2 | ||
|
|
169628a6ab | ||
|
|
8ecfd0a722 | ||
|
|
690fb14015 | ||
|
|
d5ecb52a71 | ||
|
|
6547ea47d6 | ||
|
|
898f496dc9 | ||
|
|
98765e5ebc | ||
|
|
085bdf8997 | ||
|
|
fada98b1ce | ||
|
|
4597a9621e | ||
|
|
5ad52cc1ed | ||
|
|
c937095552 | ||
|
|
8c61b91de8 | ||
|
|
aeae4b4cee | ||
|
|
c39eaf10cf | ||
|
|
1cb0a3d52a | ||
|
|
abb2f394dd | ||
|
|
4fccaf6124 | ||
|
|
41fa74fc84 | ||
|
|
b39cbc70c4 | ||
|
|
5ec0e6f84b | ||
|
|
518279dc3e | ||
|
|
1401967ce2 | ||
|
|
1fe3e3bff5 | ||
|
|
8a8388c6ff | ||
|
|
9a7edb20d3 | ||
|
|
5ce2c4b454 | ||
|
|
b8513fe895 | ||
|
|
11118be717 | ||
|
|
5a370d8a6b | ||
|
|
64cf0b816b | ||
|
|
96119149fe | ||
|
|
34eed88a70 | ||
|
|
3c18df610d | ||
|
|
f3de8b5307 | ||
|
|
8569427459 | ||
|
|
829c848520 | ||
|
|
cb41cbfe71 | ||
|
|
831c3fa184 | ||
|
|
0fcd46f364 | ||
|
|
b4569233cb | ||
|
|
f5f544f436 | ||
|
|
7479a5c21a | ||
|
|
78e5e690a2 | ||
|
|
6da45946ae | ||
|
|
fc424c9f7b | ||
|
|
5b96aeb7fc | ||
|
|
06e24e7eed | ||
|
|
3c631fdb6d | ||
|
|
e7be7b192d | ||
|
|
3327327e5d | ||
|
|
7e4fc3a0d0 | ||
|
|
264229a0d4 | ||
|
|
fa6a6bfbbd | ||
|
|
3e8f1da9c5 | ||
|
|
c52b96cf85 | ||
|
|
d9ec17d334 | ||
|
|
ab2ce3b13a | ||
|
|
cdebce3079 | ||
|
|
f4e01bfcab | ||
|
|
234e2dd2bf | ||
|
|
01d1b7bc76 | ||
|
|
19589288cb | ||
|
|
edcd228214 | ||
|
|
96229004c4 | ||
|
|
c96f0cad61 | ||
|
|
34b45a69ff | ||
|
|
ce8b3432bf | ||
|
|
bcfb872fd0 | ||
|
|
ba0899d909 | ||
|
|
2f88764100 | ||
|
|
95d184cba1 | ||
|
|
5aebf106e8 | ||
|
|
9dc59f9c23 | ||
|
|
de8c19e1da | ||
|
|
47106ce103 | ||
|
|
8f23997ca7 | ||
|
|
e73529865d | ||
|
|
38ab5f65b3 | ||
|
|
ce4de961af | ||
|
|
03072a301c | ||
|
|
8c3396a76f | ||
|
|
b45cea5f4b | ||
|
|
b427545419 | ||
|
|
e6ea0d0424 | ||
|
|
8c59fd3cb6 | ||
|
|
6ca6328e29 | ||
|
|
acb2a909dd | ||
|
|
4e6c4db340 | ||
|
|
e5e3dc687b | ||
|
|
f52b480f89 | ||
|
|
80e7040d0c | ||
|
|
2662b7b43c | ||
|
|
deb7a3fc73 | ||
|
|
8845b6cd45 | ||
|
|
199e135142 | ||
|
|
f8eb5f4ab8 | ||
|
|
19fdef46f9 | ||
|
|
571868c4f7 | ||
|
|
03184fe33b | ||
|
|
37e1c88d78 | ||
|
|
087cf2e579 | ||
|
|
fa9795406d | ||
|
|
9dffcd29d3 | ||
|
|
311218ee5f | ||
|
|
5364bc7c82 | ||
|
|
6694391b74 | ||
|
|
80bef6162a | ||
|
|
8a0ccbbd94 | ||
|
|
666e88ee2a | ||
|
|
8025a829cc | ||
|
|
a2902d37a1 | ||
|
|
2ffb5869e0 | ||
|
|
2eca4df6e9 | ||
|
|
7c23c48a93 | ||
|
|
9670d10294 | ||
|
|
28d7fb85b2 | ||
|
|
717a510a19 | ||
|
|
7657d871c1 | ||
|
|
854d6c5ab4 | ||
|
|
0c12363fd3 | ||
|
|
32b597746c | ||
|
|
7f13f24e12 | ||
|
|
3f06cb0f2e | ||
|
|
2d4e4a69c4 | ||
|
|
5fad6dc4a3 | ||
|
|
f2b9fcf85d | ||
|
|
59aecdb539 | ||
|
|
c6792dac03 | ||
|
|
cb39bc4cac | ||
|
|
83de532563 | ||
|
|
b6a16e3be4 | ||
|
|
6ca228339c | ||
|
|
30c2373c8a | ||
|
|
36ff4f52b5 | ||
|
|
f10ab130ec | ||
|
|
b3381269d7 | ||
|
|
f57cc34a0c | ||
|
|
5527ca6dcb | ||
|
|
52a9a541b0 | ||
|
|
a06c608625 | ||
|
|
8c4e67380e | ||
|
|
006174449e | ||
|
|
f075851f9d | ||
|
|
6ec4a10652 | ||
|
|
1747b45649 | ||
|
|
ec60d28e0f | ||
|
|
f8bd136d19 | ||
|
|
f6385c0530 | ||
|
|
999ec460a6 | ||
|
|
68000c01ae | ||
|
|
eef2db71a9 | ||
|
|
c6afdff7ab | ||
|
|
90ae383f62 | ||
|
|
af1cfd9e82 | ||
|
|
34b7b2cef5 | ||
|
|
8620a312b2 | ||
|
|
b776bfaa53 | ||
|
|
ea75d5cf39 | ||
|
|
0ce0533854 | ||
|
|
68c8c352fd | ||
|
|
d440ed819c | ||
|
|
a522213cc8 | ||
|
|
315828720d | ||
|
|
126b1ffd10 | ||
|
|
c45559e124 | ||
|
|
9289c6c5e0 | ||
|
|
ab6e750bd5 | ||
|
|
2127206790 | ||
|
|
6f4b384e79 | ||
|
|
05ebe494dd | ||
|
|
cea857bf73 | ||
|
|
729918ef35 | ||
|
|
4b0402825e | ||
|
|
249a0b6b60 | ||
|
|
085e029f08 | ||
|
|
1cf33feb0f | ||
|
|
a6ef31823b | ||
|
|
ef7e84454e | ||
|
|
cff81434a5 | ||
|
|
00b29f49a9 | ||
|
|
dd2e5f8b06 | ||
|
|
3eb6352c52 | ||
|
|
f24727b6bb | ||
|
|
c717bac6e3 | ||
|
|
f0cd0fbe1b | ||
|
|
233e22f23d | ||
|
|
322c4dc275 | ||
|
|
a21b5f1fd7 | ||
|
|
6acf301e77 | ||
|
|
50cfe1141b | ||
|
|
d9f1836124 | ||
|
|
c7bf40b958 | ||
|
|
4f7b8304df | ||
|
|
45788e91ca | ||
|
|
e1c8d3a1e6 | ||
|
|
9fb89c23d0 | ||
|
|
d7f9166ab5 | ||
|
|
5a467ddc98 | ||
|
|
7a6f3fded4 | ||
|
|
45cff8f03f | ||
|
|
c21576f8a3 | ||
|
|
b668b72b06 | ||
|
|
3110f69e4e | ||
|
|
3ead10dd94 | ||
|
|
b8b6a5fd7b | ||
|
|
12acbf3e92 | ||
|
|
3d963aebcd | ||
|
|
3415dec979 | ||
|
|
3d65c596a2 | ||
|
|
1cee0908d2 | ||
|
|
f15008da05 | ||
|
|
e4d874d88a | ||
|
|
c85eface68 | ||
|
|
08a4c52de3 | ||
|
|
6b78e561c8 | ||
|
|
3b943bec5d | ||
|
|
8cd21e91cc | ||
|
|
da5aa7d7a8 | ||
|
|
0aca861194 | ||
|
|
8baadb3b55 | ||
|
|
159776304f | ||
|
|
671d03f944 | ||
|
|
c994068175 | ||
|
|
0703df1a6a | ||
|
|
4944f509c3 | ||
|
|
6b3cfdd025 | ||
|
|
e02eec6bde | ||
|
|
0239133488 | ||
|
|
cbe70fa629 | ||
|
|
618c173421 | ||
|
|
3782da8d0c | ||
|
|
e2d8eb3d1c | ||
|
|
409007c9d5 | ||
|
|
8bfef6ab18 | ||
|
|
8cbbd2b88a | ||
|
|
019d10fc12 | ||
|
|
2b0a663df9 | ||
|
|
9d2068c630 | ||
|
|
ca061f3a96 | ||
|
|
9675c1e245 | ||
|
|
42395a1912 | ||
|
|
7bc0cb5ba0 | ||
|
|
2656f8edcc | ||
|
|
f9cb198aa8 | ||
|
|
4e91d38ddc | ||
|
|
d2f8ceac7a | ||
|
|
c88b19966c | ||
|
|
8d8d75ca75 | ||
|
|
f2e8b2ad79 | ||
|
|
a7cd016d71 | ||
|
|
7b9f19eaab | ||
|
|
b671fc0594 | ||
|
|
a0ab99169e | ||
|
|
76d605192d | ||
|
|
cd6ad857cf | ||
|
|
be6584e2b9 | ||
|
|
105d70f7b4 | ||
|
|
da0d43903b | ||
|
|
6426cc3384 | ||
|
|
c7263571d2 | ||
|
|
7f0a28f6ca | ||
|
|
7d1bbc80d4 | ||
|
|
0059d89c0f | ||
|
|
bbe2e5a421 | ||
|
|
04365dd4c9 | ||
|
|
6120656cbf | ||
|
|
2701dcfb06 | ||
|
|
c13bbb5cb5 | ||
|
|
6379f2ee76 | ||
|
|
48798969c5 | ||
|
|
ada17a08eb | ||
|
|
b390feec6d | ||
|
|
5dc241fee1 | ||
|
|
3b3c9412ac | ||
|
|
279dbb94e2 | ||
|
|
275dfbea20 | ||
|
|
c71415b543 | ||
|
|
d87801bd50 | ||
|
|
81a32ec305 | ||
|
|
0655fd9637 | ||
|
|
c45cb650fc | ||
|
|
70328621f1 | ||
|
|
fb164e0ab4 | ||
|
|
be8f894710 | ||
|
|
fc8c01861b | ||
|
|
ded713e90d | ||
|
|
0f29dbcfd5 | ||
|
|
bf928f3f4f | ||
|
|
be8cded098 | ||
|
|
2c1c20a48c | ||
|
|
36f53cdc3b | ||
|
|
b7c732f01c | ||
|
|
a473473fed | ||
|
|
ece74ceaaf | ||
|
|
32ac23656f | ||
|
|
7a53029e4d | ||
|
|
1bfed06c2a | ||
|
|
e9aa113240 | ||
|
|
fd775d941d | ||
|
|
32c4df1497 | ||
|
|
6b967b1285 | ||
|
|
f44060f8fc | ||
|
|
08c777053c | ||
|
|
b214fb6ed3 | ||
|
|
3d128041c3 | ||
|
|
7f39b4f573 | ||
|
|
31206a5bb8 | ||
|
|
9bb9a04b5f | ||
|
|
086870addd | ||
|
|
8c5fe87665 | ||
|
|
452045422b | ||
|
|
cd75ca692a | ||
|
|
3f3cbb51ed | ||
|
|
ff2a372a9a | ||
|
|
b50a0bdf31 | ||
|
|
598134fff6 | ||
|
|
d1c107738b | ||
|
|
e70fec871b | ||
|
|
c29420ab0d | ||
|
|
022fb4293b | ||
|
|
fd6d2180c5 | ||
|
|
5b28165fbf | ||
|
|
a82aff3337 | ||
|
|
c92f4f52d9 | ||
|
|
4e363a1728 | ||
|
|
30fd24abd4 | ||
|
|
5077d4c915 | ||
|
|
583c3b4746 | ||
|
|
da3a763e97 | ||
|
|
a46372e910 | ||
|
|
0ec3a40dfd | ||
|
|
bb93bf8cd2 | ||
|
|
a045400501 | ||
|
|
40131b7e0f | ||
|
|
7916cf71cc | ||
|
|
19ef024aa9 | ||
|
|
86f3d8e331 | ||
|
|
6a24b762d3 | ||
|
|
24c930a9b8 | ||
|
|
b006b98334 | ||
|
|
e7262accb6 | ||
|
|
afa05caacf | ||
|
|
95aab7d687 | ||
|
|
e21523529b | ||
|
|
4dc4e93f1d | ||
|
|
19e3e10e4b | ||
|
|
5f08561e10 | ||
|
|
7abf2c03d6 | ||
|
|
cad8739594 | ||
|
|
cb3589c56e | ||
|
|
88d5c70bdb | ||
|
|
ef3eb02ccb | ||
|
|
96b31ba670 | ||
|
|
2cb8bddd82 | ||
|
|
2cf3a6eb4d | ||
|
|
ec81877fa7 | ||
|
|
80909254c4 | ||
|
|
3f0a1719dc | ||
|
|
c771cb52fa | ||
|
|
ccc1651075 | ||
|
|
29ae3ed4d5 | ||
|
|
605538f46d | ||
|
|
bdec3c5345 | ||
|
|
b2485d6cd5 | ||
|
|
4dc7662a07 | ||
|
|
7874397373 | ||
|
|
4cccba74d2 | ||
|
|
d0efbc5d3a | ||
|
|
ee3fef2ce2 | ||
|
|
79d439ee4f | ||
|
|
560526a49d | ||
|
|
fa0fa62b0c | ||
|
|
20a22cf3d6 | ||
|
|
d15dec711d | ||
|
|
9957c686a4 | ||
|
|
78c3ea30a6 | ||
|
|
7ed9c95ae7 | ||
|
|
d1fa89a11f | ||
|
|
676755f6ee | ||
|
|
95e39517ef | ||
|
|
3fd6a05fff | ||
|
|
03841b6f16 | ||
|
|
da0cc61794 | ||
|
|
62d857a6f9 | ||
|
|
909d58dd5e | ||
|
|
d5f25d19b3 | ||
|
|
f6f3d646fb | ||
|
|
04810db83a | ||
|
|
d66a62fa6b | ||
|
|
8d3930bdb6 | ||
|
|
9cfc8f60ce | ||
|
|
079692016d | ||
|
|
dd69143ae6 | ||
|
|
ea0c57e90a | ||
|
|
ac9eeea1d5 | ||
|
|
657262c7e5 | ||
|
|
d0c26ba4e5 | ||
|
|
d1f5d132c6 | ||
|
|
a0f88dca75 | ||
|
|
6b9c0024ac | ||
|
|
85b27432bb | ||
|
|
e2db3a5e57 | ||
|
|
7cc1cc3881 | ||
|
|
ab39d34dde | ||
|
|
894e166ecf | ||
|
|
14e78d7cc2 | ||
|
|
b7356bb638 | ||
|
|
6b398686d6 | ||
|
|
ffbf6c26b2 | ||
|
|
bdaccc2898 | ||
|
|
7015838f51 | ||
|
|
fef701b57f | ||
|
|
60d52f0d68 | ||
|
|
702b802316 | ||
|
|
4cb99787a7 | ||
|
|
62096265ed | ||
|
|
ac0604a4d4 | ||
|
|
065b401c6e | ||
|
|
a722a124f3 | ||
|
|
afcdaf121a | ||
|
|
747ad409ac | ||
|
|
6b9fb93cd1 | ||
|
|
d8329c2d19 | ||
|
|
312d28b0a8 | ||
|
|
28fa4d3db6 | ||
|
|
f48efeef8c | ||
|
|
b86d82c8b3 | ||
|
|
d605d75ba8 | ||
|
|
d578151f8c | ||
|
|
e99cf72784 | ||
|
|
233d5d5f6f | ||
|
|
f89a6f12a7 | ||
|
|
c8ef84c854 | ||
|
|
c6b722f3f8 | ||
|
|
8eabf67e1e | ||
|
|
6219b2de00 | ||
|
|
40f01478d8 | ||
|
|
aea2b53123 | ||
|
|
df6fd04aaf | ||
|
|
7d76420857 | ||
|
|
878fcccdb2 | ||
|
|
79a8229fb5 | ||
|
|
bb80cbe0d9 | ||
|
|
c60f1d953c | ||
|
|
d27ca0e0c0 | ||
|
|
d76e03232b | ||
|
|
c03d59eae0 | ||
|
|
b9aeb21f3f | ||
|
|
aef64762c1 | ||
|
|
0fd7376000 | ||
|
|
e5eedc0cda | ||
|
|
e41730f11a | ||
|
|
414c22c67b | ||
|
|
2507c71704 | ||
|
|
fa25630ce4 | ||
|
|
76b88e22a4 | ||
|
|
4410dbdd7f | ||
|
|
c51236eee7 | ||
|
|
2acf65f7e6 | ||
|
|
20a1ebf854 | ||
|
|
85c32ddd0b | ||
|
|
0f72db09ab | ||
|
|
90b68cbd58 | ||
|
|
aa9093a144 | ||
|
|
c3e3a07ed4 | ||
|
|
0c36b3ff2d | ||
|
|
64f4b00d34 | ||
|
|
1da92cdd93 | ||
|
|
b077bc8ff7 | ||
|
|
2309517066 | ||
|
|
98bab41cba | ||
|
|
154c3e7450 | ||
|
|
47dc6e6d7b | ||
|
|
1de025c13a | ||
|
|
b7733aeef1 | ||
|
|
8b906427e3 | ||
|
|
ef19711ba5 | ||
|
|
746560dc45 | ||
|
|
bc12ab02c0 | ||
|
|
2647dc063d | ||
|
|
4589fdfad4 | ||
|
|
09808f327f | ||
|
|
8e860702e4 | ||
|
|
ebaa5c81f4 | ||
|
|
e460f7dbb2 | ||
|
|
d653cf01f3 | ||
|
|
7d6979d452 | ||
|
|
c81519e1c4 | ||
|
|
e8adc64203 | ||
|
|
7d31904247 | ||
|
|
8482682061 | ||
|
|
af1abf1f45 | ||
|
|
e588b65390 | ||
|
|
a83b285685 | ||
|
|
2c70652e04 | ||
|
|
2d210fef49 | ||
|
|
3715f1d7ee | ||
|
|
fe7ee1105c | ||
|
|
73c22f831f | ||
|
|
ebb4e71236 | ||
|
|
9712541156 | ||
|
|
cd627c6c40 | ||
|
|
afc136262e | ||
|
|
a4e0f7ef05 | ||
|
|
e301a0ba8d | ||
|
|
aaec564a82 | ||
|
|
4c82b00342 | ||
|
|
a4f9e3cf4c | ||
|
|
0e47167cbe | ||
|
|
53dd065daf | ||
|
|
19cc80788d | ||
|
|
e7396c99b0 | ||
|
|
748e38ad99 | ||
|
|
9a81e6366b | ||
|
|
2caaff20fb | ||
|
|
56481d554f | ||
|
|
1cd7998905 | ||
|
|
0241120b54 | ||
|
|
499cf2305b | ||
|
|
18808e325f | ||
|
|
f0df48fcdd | ||
|
|
2f2708a769 | ||
|
|
d3e940c71c | ||
|
|
fa9c31c3db | ||
|
|
9ac128c0bd | ||
|
|
5a3d1024d9 | ||
|
|
39ea340a31 | ||
|
|
0366924047 | ||
|
|
8777ae984c | ||
|
|
d3e4664629 | ||
|
|
e86aae4f6d | ||
|
|
c1725a8f6e | ||
|
|
a5588501ab | ||
|
|
aea68dbb40 | ||
|
|
ac42d6826b | ||
|
|
ecf8e5a00e | ||
|
|
fe6b5c08dc | ||
|
|
6bb41a05d7 | ||
|
|
5fb582ab7f | ||
|
|
3ce7bc6efc | ||
|
|
b3bebdb20a | ||
|
|
8759b2581d | ||
|
|
e2e5377e7b | ||
|
|
4a03f1fb20 | ||
|
|
0244320b88 | ||
|
|
750f0a3e3f | ||
|
|
313855c232 | ||
|
|
8a3d0a0557 | ||
|
|
4efcada291 | ||
|
|
184d845838 | ||
|
|
291eccc154 | ||
|
|
719d96665e | ||
|
|
0c6adcbe53 | ||
|
|
ec5d94291c | ||
|
|
917aad3bcf | ||
|
|
308d8d17dc | ||
|
|
7225282ea5 | ||
|
|
e9f59c804d | ||
|
|
4e0e9b8f21 | ||
|
|
d33b189427 | ||
|
|
1692060fb0 | ||
|
|
6c0e0b998b | ||
|
|
027b8fb9b8 | ||
|
|
d88857b210 | ||
|
|
da11cf6515 | ||
|
|
1645616843 | ||
|
|
2ce2dbcb09 | ||
|
|
d33f582e25 | ||
|
|
1a8fb94350 | ||
|
|
61537d899a | ||
|
|
af686a796b | ||
|
|
ca11849ebb | ||
|
|
15e9b7384e | ||
|
|
e97e108d0b | ||
|
|
c7a57bf1fa | ||
|
|
675046bd59 | ||
|
|
e538160a32 | ||
|
|
e449db5f1d | ||
|
|
a951dc026f | ||
|
|
dda95e9b0b | ||
|
|
4b2c6cf3a4 | ||
|
|
931a146591 | ||
|
|
2709b7ab03 | ||
|
|
49cd6f59b2 | ||
|
|
0d59ac4817 | ||
|
|
0c16762418 | ||
|
|
b1d9de6794 | ||
|
|
a7a13896b3 | ||
|
|
eadcee6501 | ||
|
|
ecb384ac0c | ||
|
|
46bf3f940c | ||
|
|
ab13f1a25a | ||
|
|
6e76d894fe | ||
|
|
91a956823e | ||
|
|
592cf7fb25 | ||
|
|
b964fc6922 | ||
|
|
588d64c538 | ||
|
|
cca4ece0a8 | ||
|
|
d5e4b258e1 | ||
|
|
c4a2c52411 | ||
|
|
33fa3a4d41 | ||
|
|
f6fb4d0cf1 | ||
|
|
e3a0eb5089 | ||
|
|
ee75521dd5 | ||
|
|
64d29c942a | ||
|
|
24d35faed2 | ||
|
|
39d586d7fc | ||
|
|
b5d4b908c4 | ||
|
|
0378168c13 | ||
|
|
3564c47e52 | ||
|
|
431a74a446 | ||
|
|
9b76a64f96 | ||
|
|
468f338e23 | ||
|
|
99189ea707 | ||
|
|
b28bf50d2b | ||
|
|
9c0760a4d4 | ||
|
|
1e37ec4917 | ||
|
|
8b1a89fbdf | ||
|
|
0b1cc489e1 | ||
|
|
e5a898e510 | ||
|
|
4891ab71a0 | ||
|
|
7f3114ebba | ||
|
|
1432574b2b | ||
|
|
f8e50d23f5 | ||
|
|
0f0f701212 | ||
|
|
d64923c7b4 | ||
|
|
035ae7d735 | ||
|
|
48df89e10e | ||
|
|
4bb3b3cec7 | ||
|
|
aa7727964b | ||
|
|
affd736f19 | ||
|
|
f68b39b922 | ||
|
|
65d00b13d5 | ||
|
|
47da8e450e | ||
|
|
82b0af7450 | ||
|
|
9ed3de91a2 | ||
|
|
806b3f987e | ||
|
|
1ff8679e79 | ||
|
|
d0d0c8b688 | ||
|
|
310d49668e | ||
|
|
ac8af47d7f | ||
|
|
e8bff295f9 | ||
|
|
97800177c9 | ||
|
|
72f1dea537 | ||
|
|
02795106e1 | ||
|
|
e4f151c4cd | ||
|
|
a1d10c8bde | ||
|
|
5201312cb2 | ||
|
|
3658c29b43 | ||
|
|
87dcba16eb | ||
|
|
f5b8444739 | ||
|
|
dd5b546bf7 | ||
|
|
355897a920 | ||
|
|
d7f2775af8 | ||
|
|
24c94fff09 | ||
|
|
f1fb23a661 | ||
|
|
30814dfacf | ||
|
|
468e59206b | ||
|
|
ce8814cdd6 | ||
|
|
c4ae326a1d | ||
|
|
405aef9155 | ||
|
|
fbef90a703 | ||
|
|
d6f2d58158 | ||
|
|
ad16628c9e | ||
|
|
2ac8568503 | ||
|
|
458457590d | ||
|
|
9d862be1e7 | ||
|
|
1c255baad5 | ||
|
|
65773a5300 | ||
|
|
5053fd03a7 | ||
|
|
02ea864ad2 | ||
|
|
f2e7742aea | ||
|
|
719a6b3a16 | ||
|
|
a110287c31 | ||
|
|
557b4a1f6d | ||
|
|
25628cffe5 | ||
|
|
1c9d999114 | ||
|
|
90343eba3a | ||
|
|
0416594071 | ||
|
|
b82e52a497 | ||
|
|
104037a4c5 | ||
|
|
1ed4b6ba1a | ||
|
|
5043268cb1 | ||
|
|
38eaf9b3a7 | ||
|
|
b40a88ea46 | ||
|
|
bc6c0c34c1 | ||
|
|
66de1550ab | ||
|
|
e350058532 | ||
|
|
2e87eb18ab | ||
|
|
3fc55e15e8 | ||
|
|
cdbb55396c | ||
|
|
31dde11ad5 | ||
|
|
7900a6bb61 | ||
|
|
d1a6c4aefa | ||
|
|
a1dad7a9f7 | ||
|
|
036a7fe7d4 | ||
|
|
593bed9b52 | ||
|
|
d60d2bb60e | ||
|
|
704c8163fd | ||
|
|
ffb95c2e0c | ||
|
|
6b614c4deb | ||
|
|
debe8d013d | ||
|
|
a2987fef19 | ||
|
|
53f7d8baf4 | ||
|
|
f5f8326531 | ||
|
|
5aba20f270 | ||
|
|
757eccd1d2 | ||
|
|
007839597f | ||
|
|
1d7b233562 | ||
|
|
13f6e8a866 | ||
|
|
96e3923239 | ||
|
|
20dbfe99b8 | ||
|
|
23989cbcf3 | ||
|
|
d5c78ce655 | ||
|
|
c35f61b958 | ||
|
|
d7d470b357 | ||
|
|
56f74f2eeb | ||
|
|
62c0c4c77a | ||
|
|
c74c6ed61a | ||
|
|
28646b559d | ||
|
|
ecdee4a697 | ||
|
|
00d467d44c | ||
|
|
4d254312be | ||
|
|
64d5db7635 | ||
|
|
c9bdfcedb4 | ||
|
|
cd91ea658a | ||
|
|
bbc7070c82 | ||
|
|
42220676d7 | ||
|
|
db6dd66047 | ||
|
|
6f27eca785 | ||
|
|
1018ee8749 | ||
|
|
ef7c4388e7 | ||
|
|
0e74965d7f | ||
|
|
68744e3260 | ||
|
|
a3524bd780 | ||
|
|
e6d15a5df1 | ||
|
|
5f9d4ad144 | ||
|
|
aed4941e6b | ||
|
|
f44332c891 | ||
|
|
cb788d72c7 | ||
|
|
760024bde9 | ||
|
|
f9c3b61884 | ||
|
|
f3912fafdd | ||
|
|
aeb8f427e2 | ||
|
|
a5865fab22 | ||
|
|
81fec84012 | ||
|
|
77a6a9166d | ||
|
|
0c399306b8 | ||
|
|
425bd2a3db | ||
|
|
3873f95197 | ||
|
|
0754912ebd | ||
|
|
29f36a8953 | ||
|
|
483625065f | ||
|
|
54ef167111 | ||
|
|
29d8871d61 | ||
|
|
4c9516941c | ||
|
|
33d5a9fadb | ||
|
|
78d0f07e32 | ||
|
|
a7205f738b | ||
|
|
9539f51369 | ||
|
|
8712b4c9c1 | ||
|
|
7f98aefddf | ||
|
|
9a460d3234 | ||
|
|
795d7d5ce6 | ||
|
|
d66c155239 | ||
|
|
14b7973ab5 | ||
|
|
c882d03673 | ||
|
|
86cc9c587b | ||
|
|
79567004b4 | ||
|
|
612d9d7ae6 | ||
|
|
67b402fda4 | ||
|
|
3a6f3e5f30 | ||
|
|
e0cb5184f5 | ||
|
|
49365d563e | ||
|
|
daaa88ce68 | ||
|
|
abef8f6ca7 | ||
|
|
b940d8edb2 | ||
|
|
b85c3e1595 | ||
|
|
3b1f06c3b2 | ||
|
|
c7682dd9aa | ||
|
|
632b213756 | ||
|
|
82663d33bb | ||
|
|
c4e13c1ef9 | ||
|
|
c9e0c2a543 | ||
|
|
b495959e4b | ||
|
|
c5428cd19c | ||
|
|
a16678e9f3 | ||
|
|
aaf052391d | ||
|
|
9d302620c2 | ||
|
|
b10824dcdc | ||
|
|
f88ded6c2d | ||
|
|
4a6fb47b8d | ||
|
|
3221cc4a5a | ||
|
|
b147a37c23 | ||
|
|
c9fe8fe470 | ||
|
|
2633c30fb4 | ||
|
|
9a2a05ba1e | ||
|
|
33257c6439 | ||
|
|
8db839cc85 | ||
|
|
9d49883895 | ||
|
|
ea82d0826d | ||
|
|
d784b28877 | ||
|
|
b117088a91 | ||
|
|
60eac659d4 | ||
|
|
cf10c1db66 | ||
|
|
85b6efbf0c | ||
|
|
766bd82032 | ||
|
|
0821940e26 | ||
|
|
c13c434383 | ||
|
|
cc40305a12 | ||
|
|
16ed67537c | ||
|
|
b9db7c90ee | ||
|
|
1032e7175a | ||
|
|
b56099aeb4 | ||
|
|
63e29113ab | ||
|
|
ba61c7bb37 | ||
|
|
f7d2d04d96 | ||
|
|
0352c41a07 | ||
|
|
9f6b65230a | ||
|
|
8f8abcc756 | ||
|
|
888f4fd982 | ||
|
|
6cc87629b4 | ||
|
|
a493fbb1fa | ||
|
|
d4a4ee798b | ||
|
|
ac470a49d5 | ||
|
|
7eea5306e9 | ||
|
|
7f898abb82 | ||
|
|
a87dee588b | ||
|
|
50b4f320dc | ||
|
|
e2e62fcb8b | ||
|
|
02f61d5b49 | ||
|
|
d5519c929c | ||
|
|
6eef0e35b4 | ||
|
|
f48a9ed001 | ||
|
|
eab324a7cf | ||
|
|
c32cfc1113 | ||
|
|
f233cb182c | ||
|
|
8ff705554d | ||
|
|
a06fef3b11 | ||
|
|
f9c580b8a0 | ||
|
|
591feda103 | ||
|
|
72250bece2 | ||
|
|
baacb0f52a | ||
|
|
19d287aae3 | ||
|
|
a3d5e4aa43 | ||
|
|
170be79a42 | ||
|
|
6f2659c230 | ||
|
|
38dea90b2f | ||
|
|
dfe031caa6 | ||
|
|
4e12c2a6dc | ||
|
|
cf8d9cf072 | ||
|
|
13a18906ef | ||
|
|
4a42b0d95e | ||
|
|
2f78f54924 | ||
|
|
3709f8de14 | ||
|
|
3b1a42e734 | ||
|
|
b11144d69c | ||
|
|
82611f5e6d | ||
|
|
1073b379c8 | ||
|
|
08d8015750 | ||
|
|
54b4aa3cd6 | ||
|
|
8b69059f66 | ||
|
|
2b7aa2a1e1 | ||
|
|
985d963745 | ||
|
|
53587ee415 | ||
|
|
558c6f56e2 | ||
|
|
72b520e709 | ||
|
|
40395511d7 | ||
|
|
cdc3df949b | ||
|
|
ae1796fc34 | ||
|
|
78da4586a0 | ||
|
|
0da93838c1 | ||
|
|
afc0917f88 | ||
|
|
352e1d0fc4 | ||
|
|
727e24cb0a | ||
|
|
8fd7a384e2 | ||
|
|
89ea62481d | ||
|
|
8f9bf3f223 | ||
|
|
ffac4e7688 | ||
|
|
8cb3e5368f | ||
|
|
5c6356ff8e | ||
|
|
6d819d7267 | ||
|
|
bea7dcde86 | ||
|
|
aed5cd0ce9 | ||
|
|
4cd6298f9d | ||
|
|
55b4754e84 | ||
|
|
c9bbd4e707 | ||
|
|
4a16bebfab | ||
|
|
757a97466f | ||
|
|
13c66526ed | ||
|
|
15182d7fdd | ||
|
|
a3578379fb | ||
|
|
7eebf614dc | ||
|
|
89935229a7 | ||
|
|
43ae350390 | ||
|
|
55eafa66b7 | ||
|
|
d55e586bc6 | ||
|
|
61c0c852b5 | ||
|
|
8878c29c5d | ||
|
|
a5e714abec | ||
|
|
618ba55a81 | ||
|
|
60c1f70bb9 | ||
|
|
310e3b428c | ||
|
|
55f8963dfa | ||
|
|
853a498f2c | ||
|
|
53d815b8a0 | ||
|
|
d746e32349 | ||
|
|
f9870f7860 | ||
|
|
a34a9775ba | ||
|
|
696b765437 | ||
|
|
b107f7bdd9 | ||
|
|
3613a11454 | ||
|
|
777c017034 | ||
|
|
62c30a4a13 | ||
|
|
4c9e3a5988 | ||
|
|
c740fa2795 | ||
|
|
50fe33f880 | ||
|
|
5aaed43efd | ||
|
|
a06e8350aa | ||
|
|
cdf001c296 | ||
|
|
70b16cb7f8 | ||
|
|
8b8e714517 | ||
|
|
09ed7e9557 | ||
|
|
e5da657c85 | ||
|
|
dcb87d36fe | ||
|
|
9085b38a71 | ||
|
|
3cfaaaf1eb | ||
|
|
a0a0f4d029 | ||
|
|
b8fb2b02d9 | ||
|
|
1da7159689 | ||
|
|
d55a3f3362 | ||
|
|
d1ce34448f | ||
|
|
58be11f701 | ||
|
|
9b2329f66c | ||
|
|
2e798523e4 | ||
|
|
a614269794 | ||
|
|
92769362c7 | ||
|
|
c1e1c17c0a | ||
|
|
8314119662 | ||
|
|
497678eee3 | ||
|
|
b5af2d3428 | ||
|
|
28e9fc1913 | ||
|
|
e19665c0d8 | ||
|
|
513a8b074d | ||
|
|
c69290fb0c | ||
|
|
6c94df6e2d | ||
|
|
6bd0ced239 | ||
|
|
af0370a75d | ||
|
|
b5a89c8c93 | ||
|
|
1ea425811a | ||
|
|
9d75f14107 | ||
|
|
20fa63488a | ||
|
|
49e2d06921 | ||
|
|
fc05da3c0b | ||
|
|
40671f76e4 | ||
|
|
de06193d88 | ||
|
|
2a0167adfe | ||
|
|
6a4f3cf127 | ||
|
|
72277967ff | ||
|
|
0ee4989ed3 | ||
|
|
90e9e34bec | ||
|
|
e5d7e37157 | ||
|
|
9712aff9c0 | ||
|
|
6a15f15093 | ||
|
|
03646ad46f | ||
|
|
86992622dc | ||
|
|
383acf8eff | ||
|
|
50abaaeb0a | ||
|
|
d5822b725e | ||
|
|
f6e392a4af | ||
|
|
f635de709e | ||
|
|
8bad5bfae5 | ||
|
|
6b2bed447f | ||
|
|
15e4f8b3b0 | ||
|
|
9617ea6a3a | ||
|
|
3c53d54a43 | ||
|
|
039e4ec2a4 | ||
|
|
0262f0eb1e | ||
|
|
f84e96fe81 | ||
|
|
28d5c5e54f | ||
|
|
9ad25d7257 | ||
|
|
925f6704ce | ||
|
|
4d28120e9b | ||
|
|
c69356635c | ||
|
|
a3d1e9cd3d | ||
|
|
8d9b83bd11 | ||
|
|
ba8980f492 | ||
|
|
c883d43ae5 | ||
|
|
18db8da7df | ||
|
|
1711eb2ef3 | ||
|
|
d174af08f9 | ||
|
|
ac86fb50cd | ||
|
|
c86760c1e9 | ||
|
|
fbfe6209be | ||
|
|
3cf7bec12f | ||
|
|
f486b19f56 | ||
|
|
f2e154e1e5 | ||
|
|
9ce5b4a691 | ||
|
|
4eff2b5f6a | ||
|
|
f18f865159 | ||
|
|
5d2f4cb403 | ||
|
|
b0b0e48409 | ||
|
|
57ba50e611 | ||
|
|
0b3c8360a0 | ||
|
|
91cb41330d | ||
|
|
71b0634168 | ||
|
|
cc11750bda | ||
|
|
ef730c4d2f | ||
|
|
51f15d9971 | ||
|
|
1ca209dad0 | ||
|
|
84c3fecf5e | ||
|
|
d82e64c163 | ||
|
|
fab8787b23 | ||
|
|
6ebd463021 | ||
|
|
bbccb13566 | ||
|
|
1320d85742 | ||
|
|
94066765ed | ||
|
|
b882cad67e | ||
|
|
9d2ce50d2f | ||
|
|
6178e47345 | ||
|
|
032664bf7f | ||
|
|
c16f5d2fe6 | ||
|
|
34a5658564 | ||
|
|
4cc27b816f | ||
|
|
7b6931ed1f | ||
|
|
b2d351e0ec | ||
|
|
b5faa45d90 | ||
|
|
781872517d | ||
|
|
cbef54653a | ||
|
|
e7a4140d28 | ||
|
|
8fb8d88ea6 | ||
|
|
44019e874f | ||
|
|
0b8ee7364a | ||
|
|
9eef33993a | ||
|
|
068d5b3d20 | ||
|
|
e640ed1aeb | ||
|
|
bbb3f79bb8 | ||
|
|
47363cbb97 | ||
|
|
ae14ef5426 | ||
|
|
3b617fdc53 | ||
|
|
045632defb | ||
|
|
b5b92c7d6d | ||
|
|
4429cef9f6 | ||
|
|
7bb5454ef3 | ||
|
|
92236bfe1d | ||
|
|
9c28349757 | ||
|
|
5bc1720776 | ||
|
|
8de7c092f0 | ||
|
|
29ba50da29 | ||
|
|
8370bc03a1 | ||
|
|
973a14bb2f | ||
|
|
3e731e3a78 | ||
|
|
fb1fb8219c | ||
|
|
2f94390223 | ||
|
|
245f6a0d13 | ||
|
|
8c6143d86f | ||
|
|
1803762e3f | ||
|
|
38ab621b55 | ||
|
|
c085645f98 | ||
|
|
00fbf65524 | ||
|
|
096c93c0c6 | ||
|
|
6696da2f61 | ||
|
|
d019586378 | ||
|
|
024214af2d | ||
|
|
df67d8617b | ||
|
|
c386ca91c6 | ||
|
|
5ade19c421 | ||
|
|
ec0e93616f | ||
|
|
6fa78a3635 | ||
|
|
4caa9a4cc7 | ||
|
|
704b602184 | ||
|
|
cb041f11f6 | ||
|
|
e050ae845e | ||
|
|
923100c498 | ||
|
|
9272fac7c4 | ||
|
|
a9e7fe19c7 | ||
|
|
89b3cf0b87 | ||
|
|
c092f2ed61 | ||
|
|
7e901299bf | ||
|
|
aeac24de98 | ||
|
|
23a8bac7b5 | ||
|
|
fdeeb62e28 | ||
|
|
d79e1dee8c | ||
|
|
a5f6e6189e | ||
|
|
2b7cffac74 | ||
|
|
ef42295fe8 | ||
|
|
4092b05068 | ||
|
|
c2976962da | ||
|
|
c7e3d5d7a3 | ||
|
|
0d7c40b948 | ||
|
|
65f2fe390c | ||
|
|
4a70b2bc2d | ||
|
|
3877618785 | ||
|
|
0d6801b130 | ||
|
|
269042503e | ||
|
|
f150f93854 | ||
|
|
43fb5a72e7 | ||
|
|
1d4d74d6d0 | ||
|
|
c8ca64d28b | ||
|
|
2d17e5a6c4 | ||
|
|
d30d68d738 | ||
|
|
a64353ce71 | ||
|
|
89372dc482 | ||
|
|
35475b5423 | ||
|
|
5914f4d57d | ||
|
|
ff3b5ee91c | ||
|
|
b476a5f478 | ||
|
|
6cb68c3a17 | ||
|
|
2fb79a6326 | ||
|
|
65f74a4df0 | ||
|
|
56db092ab7 | ||
|
|
a86f47889c | ||
|
|
87639aae7c | ||
|
|
56e70bfa31 | ||
|
|
39c0ff311d | ||
|
|
35512be1ee | ||
|
|
75145ddc1a | ||
|
|
4a2e33d160 | ||
|
|
ce4eafb34f | ||
|
|
11fc58fa13 | ||
|
|
90e09ed75f | ||
|
|
83f822d0cd | ||
|
|
8b23662d53 | ||
|
|
b3893baa45 | ||
|
|
b45a8d456d | ||
|
|
426d32af23 | ||
|
|
a0bc149b0c | ||
|
|
72729d8e36 | ||
|
|
6082dd62bb | ||
|
|
df349ddc43 | ||
|
|
4d297d354c | ||
|
|
fb22e0c12d | ||
|
|
ac2a61d1b3 | ||
|
|
353db307ed | ||
|
|
88dd577302 | ||
|
|
17850a51f5 | ||
|
|
4461f38a9e | ||
|
|
474f95dda8 | ||
|
|
1dc92f8ff8 | ||
|
|
4873f6fada | ||
|
|
14fc6b6dcb | ||
|
|
df72b8d487 | ||
|
|
4e9ce59fe8 | ||
|
|
8a93ce106a | ||
|
|
25781e4552 | ||
|
|
f420259ee5 | ||
|
|
96f1fb1da0 | ||
|
|
fadfc118e5 | ||
|
|
800c3a5e0b | ||
|
|
c4c5ea4381 | ||
|
|
b84ab23011 | ||
|
|
588dd6827a | ||
|
|
a7b37f9c63 | ||
|
|
749dd15ee8 | ||
|
|
66a14a1e33 | ||
|
|
b073a9c103 | ||
|
|
7268fe7239 | ||
|
|
491773ac58 | ||
|
|
944c4003bd | ||
|
|
c6635504fe | ||
|
|
53a1521c2e | ||
|
|
7b8799e5ff | ||
|
|
9298555eb6 | ||
|
|
7d4a71fc8b | ||
|
|
9264f06efe | ||
|
|
91e297acd3 | ||
|
|
48ba22c744 | ||
|
|
d5bb407cc4 | ||
|
|
f8d80464a9 | ||
|
|
83cf5bf17f | ||
|
|
c505074a9f | ||
|
|
9b0efa9346 | ||
|
|
0cb6e3fff8 | ||
|
|
98f1b83ffe | ||
|
|
98dc4c123d | ||
|
|
e9c2a1996a | ||
|
|
509f561823 | ||
|
|
1ada32900b | ||
|
|
06184aec53 | ||
|
|
69c77d1597 | ||
|
|
2668eda595 | ||
|
|
2616c6b230 | ||
|
|
982de78e8d | ||
|
|
f44df9d85b | ||
|
|
ddb0c2de92 | ||
|
|
b69c2ea2cf | ||
|
|
31ecaa7c28 | ||
|
|
b0329ac081 | ||
|
|
5390a729d9 | ||
|
|
9164594d1f | ||
|
|
215bc1aab4 | ||
|
|
f64d460d29 | ||
|
|
5fcb87138d | ||
|
|
9309585dbe | ||
|
|
9c1b17407f | ||
|
|
02c8e69a07 | ||
|
|
0d3db83f16 | ||
|
|
9214087259 | ||
|
|
b1c7520886 | ||
|
|
16edda58b7 | ||
|
|
55040845f3 | ||
|
|
ef7c1a4e96 | ||
|
|
35d7b5934e | ||
|
|
1353ccd9e2 | ||
|
|
0676d5bc23 | ||
|
|
9e429dbef0 | ||
|
|
ce1ef5b8fc | ||
|
|
4bb5bc4401 | ||
|
|
756e766295 | ||
|
|
a4997bf3d9 | ||
|
|
a9340dd325 | ||
|
|
a7eef33859 | ||
|
|
84779b2b84 | ||
|
|
3d78918e63 | ||
|
|
8227db3a23 | ||
|
|
1b57560502 | ||
|
|
8569048031 | ||
|
|
cbbba01b46 | ||
|
|
942b73bbbb | ||
|
|
6599483304 | ||
|
|
dd60b20c6e | ||
|
|
7894f39e65 | ||
|
|
e6d8f9a8bb | ||
|
|
5dfcc7506c | ||
|
|
944fe7036c | ||
|
|
d39c49db2d | ||
|
|
d052f609fe | ||
|
|
21841cb622 | ||
|
|
78ee3eb7c7 | ||
|
|
cb73be5346 | ||
|
|
c3f0937012 | ||
|
|
3980e4a5b9 | ||
|
|
fe23a14ebb | ||
|
|
69a46b0c53 | ||
|
|
cb8bbf1ab9 | ||
|
|
4dfc27b101 | ||
|
|
7ed2d15345 | ||
|
|
eaf5f3fa52 | ||
|
|
4c2b55f962 | ||
|
|
47722a8c2e | ||
|
|
587e1f5598 | ||
|
|
f2fd56a27d | ||
|
|
60ceab1453 | ||
|
|
18a2ed2936 | ||
|
|
d04ce7772c | ||
|
|
1dd6842654 | ||
|
|
cf3d23741f | ||
|
|
14be3a1dc1 | ||
|
|
0d54946dec | ||
|
|
d30bc6d00a | ||
|
|
e371642e6b | ||
|
|
5a0101856b | ||
|
|
85483f321d | ||
|
|
c07e81b087 | ||
|
|
f2461096b1 | ||
|
|
c16dadbb97 | ||
|
|
105107124d | ||
|
|
0344c0b6a0 | ||
|
|
94846d3eef | ||
|
|
ce4aea2478 | ||
|
|
38a6aba468 | ||
|
|
fa0ef91a24 | ||
|
|
2a417b50ee | ||
|
|
5ac2a26666 | ||
|
|
d00f98a7a5 | ||
|
|
9382a3ad58 | ||
|
|
1fd3709379 | ||
|
|
e6980f6cc7 | ||
|
|
d72b877e45 | ||
|
|
be7c870718 | ||
|
|
920f773a81 | ||
|
|
4b46e0ec63 | ||
|
|
ef0397cf3d | ||
|
|
b082659f19 | ||
|
|
fef838db2d | ||
|
|
749d19d70b | ||
|
|
5f737fb4d3 | ||
|
|
5c862a08b4 | ||
|
|
d27ea5155f | ||
|
|
08e22d8ad2 | ||
|
|
4cc802a88e | ||
|
|
5d805a90e3 | ||
|
|
46145af4a1 | ||
|
|
5010023428 | ||
|
|
de92fbee7e | ||
|
|
26f0cf0708 | ||
|
|
ff38d90d5d | ||
|
|
0d91ba749c | ||
|
|
f6be0d483b | ||
|
|
acac38afb2 | ||
|
|
45b8b0e57d | ||
|
|
05f6aa1ade | ||
|
|
adbe794a46 | ||
|
|
d44d8cdf60 | ||
|
|
ecb90de4cc | ||
|
|
8482f9e54b | ||
|
|
065a3b35fc | ||
|
|
2b94c0c3b1 | ||
|
|
756988e8f9 | ||
|
|
a3a291784a | ||
|
|
337dc84b57 | ||
|
|
51f6e52dd3 | ||
|
|
3f05d88d5b | ||
|
|
b3b685d92a | ||
|
|
0c313f491b | ||
|
|
7369cfc490 | ||
|
|
7eceba178d | ||
|
|
f21b53b5ed | ||
|
|
3e007193a2 | ||
|
|
325241c0de | ||
|
|
bf09349f8e | ||
|
|
82abfd75f3 | ||
|
|
63f69c2bdd | ||
|
|
f68a1f50fd | ||
|
|
adfcf3b1dd | ||
|
|
8494f2c318 | ||
|
|
070646b790 | ||
|
|
c4787e3626 | ||
|
|
f7779efe58 | ||
|
|
49dfb5755a | ||
|
|
3058d4116e | ||
|
|
9d44b02a49 | ||
|
|
e0012c2767 | ||
|
|
c81116e29a | ||
|
|
f85b1e393f | ||
|
|
1e2e5671f7 | ||
|
|
314843ffc3 | ||
|
|
73ca09ff32 | ||
|
|
93a4ddfa63 | ||
|
|
3b9c3fd186 | ||
|
|
61ba9f2299 | ||
|
|
22420ee1ee | ||
|
|
0edbed1d52 | ||
|
|
d79caa9ff6 | ||
|
|
65c7f19deb | ||
|
|
91bdb5a4a3 | ||
|
|
8f6fcb709a | ||
|
|
2b155a8c16 | ||
|
|
ace1225492 | ||
|
|
671dcace82 | ||
|
|
ef668aae1e | ||
|
|
d6d3cf00ec | ||
|
|
f0a25ca263 | ||
|
|
c41caac02d | ||
|
|
e76058c478 | ||
|
|
776aa0c093 | ||
|
|
3e6515b64f | ||
|
|
7ad2cf8d68 | ||
|
|
8294285d8f | ||
|
|
988e2ff7fe | ||
|
|
414b224efa | ||
|
|
9e47b18229 | ||
|
|
3b27b3b1d1 | ||
|
|
1b1b270f1e | ||
|
|
3f8225509b |
143
.github/workflows/build.yml
vendored
Normal file
143
.github/workflows/build.yml
vendored
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
name: build and test
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ mob ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test-x86_64-linux:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
timeout-minutes: 2
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: make & test tcc (x86_64-linux)
|
||||||
|
run: ./configure && make && make test -k
|
||||||
|
|
||||||
|
test-x86_64-osx:
|
||||||
|
runs-on: macos-15-intel
|
||||||
|
timeout-minutes: 2
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: make & test tcc (x86_64-osx)
|
||||||
|
run: ./configure && make && make test -k
|
||||||
|
|
||||||
|
test-aarch64-osx:
|
||||||
|
runs-on: macos-15
|
||||||
|
timeout-minutes: 2
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: make & test tcc (aarch64-osx)
|
||||||
|
run: ./configure && make && make test -k
|
||||||
|
|
||||||
|
test-x86_64-win32:
|
||||||
|
runs-on: windows-2025
|
||||||
|
timeout-minutes: 6
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: build tcc (x86_64-win32)
|
||||||
|
shell: cmd
|
||||||
|
run: |
|
||||||
|
cd win32
|
||||||
|
for /f "delims=" %%i in ('vswhere.exe -latest -property installationPath') do call "%%i\VC\Auxiliary\Build\vcvarsall.bat" amd64
|
||||||
|
call build-tcc.bat -c cl -t x86_64
|
||||||
|
- name: test (x86_64-win32)
|
||||||
|
shell: cmd
|
||||||
|
run: |
|
||||||
|
cd tests
|
||||||
|
call test-win32.bat all -k
|
||||||
|
|
||||||
|
test-i386-win32:
|
||||||
|
runs-on: windows-2025
|
||||||
|
timeout-minutes: 6
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: build tcc (i386-win32)
|
||||||
|
shell: cmd
|
||||||
|
run: |
|
||||||
|
cd win32
|
||||||
|
for /f "delims=" %%i in ('vswhere.exe -latest -property installationPath') do call "%%i\VC\Auxiliary\Build\vcvarsall.bat" x86
|
||||||
|
call build-tcc.bat -c cl -t i386
|
||||||
|
- name: test (i386-win32)
|
||||||
|
shell: cmd
|
||||||
|
run: |
|
||||||
|
cd tests
|
||||||
|
call test-win32.bat -p c:\mingw32\bin all -k
|
||||||
|
|
||||||
|
test-arm64-win32:
|
||||||
|
runs-on: windows-11-arm
|
||||||
|
timeout-minutes: 6
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: build and test (arm64-win32)
|
||||||
|
shell: cmd
|
||||||
|
run: |
|
||||||
|
cd win32
|
||||||
|
for /f "delims=" %%i in ('vswhere.exe -latest -property installationPath') do call "%%i\VC\Auxiliary\Build\vcvarsall.bat" amd64_arm64
|
||||||
|
call build-tcc.bat -c cl -t arm64
|
||||||
|
set "PATH=C:\Program Files\LLVM\bin;%CD%;%PATH%"
|
||||||
|
cd ..\tests
|
||||||
|
call test-win32.bat -c clang all -k
|
||||||
|
|
||||||
|
test-armv7-linux:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
timeout-minutes: 8
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: uraimo/run-on-arch-action@v3
|
||||||
|
name: make & test tcc (armv7-linux)
|
||||||
|
with:
|
||||||
|
arch: armv7
|
||||||
|
distro: ubuntu22.04
|
||||||
|
githubToken: ${{ github.token }}
|
||||||
|
install: |
|
||||||
|
apt-get update -q -y
|
||||||
|
apt-get install -q -y gcc make
|
||||||
|
run: |
|
||||||
|
echo "::endgroup::" # flatten 'run container'
|
||||||
|
./configure && make && make test -k
|
||||||
|
|
||||||
|
test-aarch64-linux:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
timeout-minutes: 8
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: uraimo/run-on-arch-action@v3
|
||||||
|
name: make & test tcc (aarch64-linux)
|
||||||
|
with:
|
||||||
|
arch: aarch64
|
||||||
|
distro: ubuntu24.04
|
||||||
|
githubToken: ${{ github.token }}
|
||||||
|
install: |
|
||||||
|
apt-get update -q -y
|
||||||
|
apt-get install -q -y gcc make
|
||||||
|
run: |
|
||||||
|
echo "::endgroup::" # flatten 'run container'
|
||||||
|
./configure && make && make test -k
|
||||||
|
|
||||||
|
test-riscv64-linux:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
timeout-minutes: 8
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: uraimo/run-on-arch-action@v3
|
||||||
|
name: make & test tcc (riscv64-linux)
|
||||||
|
with:
|
||||||
|
arch: riscv64
|
||||||
|
distro: ubuntu22.04
|
||||||
|
githubToken: ${{ github.token }}
|
||||||
|
install: |
|
||||||
|
apt-get update -q -y
|
||||||
|
apt-get install -q -y gcc make
|
||||||
|
run: |
|
||||||
|
echo "::endgroup::" # flatten 'run container'
|
||||||
|
./configure && make && make test -k
|
||||||
|
|
||||||
|
test-riscv64-linux-native:
|
||||||
|
runs-on: ubuntu-24.04-riscv
|
||||||
|
timeout-minutes: 8
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: make & test tcc (riscv64-linux native)
|
||||||
|
run: |
|
||||||
|
uname -m # riscv64
|
||||||
|
./configure && make && make test -k
|
||||||
15
.gitignore
vendored
15
.gitignore
vendored
@ -16,30 +16,41 @@
|
|||||||
a.out
|
a.out
|
||||||
tcc_g
|
tcc_g
|
||||||
tcc
|
tcc
|
||||||
|
tcc_c
|
||||||
|
tcc_p
|
||||||
*-tcc
|
*-tcc
|
||||||
libtcc*.def
|
libtcc*.def
|
||||||
|
|
||||||
config*.h
|
config*.h
|
||||||
|
*_.h
|
||||||
config*.mak
|
config*.mak
|
||||||
config.texi
|
config.texi
|
||||||
conftest*
|
conftest*
|
||||||
|
c2str
|
||||||
tags
|
tags
|
||||||
TAGS
|
TAGS
|
||||||
tcc.1
|
tcc.1
|
||||||
tcc.pod
|
*.pod
|
||||||
|
*.tcov
|
||||||
tcc-doc.html
|
tcc-doc.html
|
||||||
tcc-doc.info
|
tcc-doc.info
|
||||||
|
|
||||||
win32/doc
|
win32/doc
|
||||||
|
win32/examples/libtcc_test.c
|
||||||
win32/libtcc
|
win32/libtcc
|
||||||
win32/lib/32
|
win32/lib/32
|
||||||
win32/lib/64
|
win32/lib/64
|
||||||
win32/include/float.h
|
win32/include/float.h
|
||||||
|
win32/include/stdalign.h
|
||||||
win32/include/stdarg.h
|
win32/include/stdarg.h
|
||||||
win32/include/stdbool.h
|
win32/include/stdbool.h
|
||||||
win32/include/stddef.h
|
win32/include/stddef.h
|
||||||
|
win32/include/stdnoreturn.h
|
||||||
win32/include/varargs.h
|
win32/include/varargs.h
|
||||||
win32/include/tcclib.h
|
win32/include/tcclib.h
|
||||||
|
win32/include/tccdefs.h
|
||||||
|
win32/include/stdatomic.h
|
||||||
|
win32/include/tgmath.h
|
||||||
|
|
||||||
tests/tcctest[1234]
|
tests/tcctest[1234]
|
||||||
tests/tcctest.gcc
|
tests/tcctest.gcc
|
||||||
@ -50,8 +61,10 @@ tests/*.gcc
|
|||||||
tests/*-cc*
|
tests/*-cc*
|
||||||
tests/*-tcc*
|
tests/*-tcc*
|
||||||
tests/libtcc_test
|
tests/libtcc_test
|
||||||
|
tests/libtcc_test_mt
|
||||||
tests/asm-c-connect
|
tests/asm-c-connect
|
||||||
tests/asm-c-connect-sep
|
tests/asm-c-connect-sep
|
||||||
tests/vla_test
|
tests/vla_test
|
||||||
tests/hello
|
tests/hello
|
||||||
tests/tests2/fred.txt
|
tests/tests2/fred.txt
|
||||||
|
libtcc.dylib
|
||||||
|
|||||||
24
Changelog
24
Changelog
@ -1,3 +1,27 @@
|
|||||||
|
version 0.9.28:
|
||||||
|
|
||||||
|
User interface:
|
||||||
|
- -b : bounds checker much improved (herman ten brugge)
|
||||||
|
- -bt : support for standalone backtraces also (grischka)
|
||||||
|
- -gdwarf : debug format (herman ten brugge)
|
||||||
|
- -M, -MM, and -MMD (Arthur Williams)
|
||||||
|
- -W[no-]error=<option> (Steffen Nurpmeso)
|
||||||
|
|
||||||
|
Platforms:
|
||||||
|
- new RISC-V (riscv64) target (Michael Matz)
|
||||||
|
- native macOS support for x86_64 (Michael Matz, Herman ten Brugge)
|
||||||
|
- arm and riscv64 assemblers (Danny Milosavljevic)
|
||||||
|
- Android support with position independent executables (grischka)
|
||||||
|
|
||||||
|
Features:
|
||||||
|
- _Static_assert() (matthias)
|
||||||
|
- __attribute__ ((cleanup(func))) (matthias)
|
||||||
|
- stdatomic (Dmitry Selyutin)
|
||||||
|
- asm goto ("jmp %l[label]" : : : : label) (Michael Matz)
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
- ... many, see git shortlog release_0_9_27...release_0_9_27
|
||||||
|
|
||||||
Version 0.9.27:
|
Version 0.9.27:
|
||||||
|
|
||||||
User interface:
|
User interface:
|
||||||
|
|||||||
436
Makefile
436
Makefile
@ -8,9 +8,11 @@ ifndef TOP
|
|||||||
INCLUDED = no
|
INCLUDED = no
|
||||||
endif
|
endif
|
||||||
|
|
||||||
include $(TOP)/config.mak
|
ifeq ($(findstring $(MAKECMDGOALS),clean distclean),)
|
||||||
|
include $(TOP)/config.mak
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq (-$(CC)-$(GCC_MAJOR)-$(findstring $(GCC_MINOR),56789)-,-gcc-4--)
|
ifeq (-$(GCC_MAJOR)-$(findstring $(GCC_MINOR),56789)-,-4--)
|
||||||
CFLAGS += -D_FORTIFY_SOURCE=0
|
CFLAGS += -D_FORTIFY_SOURCE=0
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -18,84 +20,125 @@ LIBTCC = libtcc.a
|
|||||||
LIBTCC1 = libtcc1.a
|
LIBTCC1 = libtcc1.a
|
||||||
LINK_LIBTCC =
|
LINK_LIBTCC =
|
||||||
LIBS =
|
LIBS =
|
||||||
CFLAGS += -I$(TOP)
|
|
||||||
CFLAGS += $(CPPFLAGS)
|
CFLAGS += $(CPPFLAGS)
|
||||||
VPATH = $(TOPSRC)
|
VPATH = $(TOPSRC)
|
||||||
|
-LTCC = $(TOP)/$(LIBTCC)
|
||||||
|
|
||||||
ifdef CONFIG_WIN32
|
ifdef CONFIG_WIN32
|
||||||
|
CFG = -win
|
||||||
ifneq ($(CONFIG_static),yes)
|
ifneq ($(CONFIG_static),yes)
|
||||||
LIBTCC = libtcc$(DLLSUF)
|
LIBTCC = libtcc$(DLLSUF)
|
||||||
LIBTCCDEF = libtcc.def
|
LIBTCCDEF = libtcc.def
|
||||||
endif
|
endif
|
||||||
CFGWIN = -win
|
ifneq ($(CONFIG_debug),yes)
|
||||||
NATIVE_TARGET = $(ARCH)-win$(if $(findstring arm,$(ARCH)),ce,32)
|
ifneq ($(CC_NAME),clang)
|
||||||
|
LDFLAGS += -s
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
NATIVE_TARGET = $(if $(findstring arm64,$(ARCH)),arm64-win32,$(ARCH)-win$(if $(findstring arm,$(ARCH)),ce,32))
|
||||||
else
|
else
|
||||||
LIBS=-lm
|
CFG = -unx
|
||||||
|
LIBS+=-lm
|
||||||
ifneq ($(CONFIG_ldl),no)
|
ifneq ($(CONFIG_ldl),no)
|
||||||
LIBS+=-ldl
|
LIBS+=-ldl
|
||||||
endif
|
endif
|
||||||
|
ifneq ($(CONFIG_pthread),no)
|
||||||
|
LIBS+=-lpthread
|
||||||
|
endif
|
||||||
# make libtcc as static or dynamic library?
|
# make libtcc as static or dynamic library?
|
||||||
ifeq ($(CONFIG_static),no)
|
ifeq ($(CONFIG_static),no)
|
||||||
LIBTCC=libtcc$(DLLSUF)
|
LIBTCC=libtcc$(DLLSUF)
|
||||||
export LD_LIBRARY_PATH := $(CURDIR)/$(TOP)
|
export LD_LIBRARY_PATH := $(CURDIR)/$(TOP)
|
||||||
ifneq ($(CONFIG_rpath),no)
|
ifneq ($(CONFIG_rpath),no)
|
||||||
LINK_LIBTCC += -Wl,-rpath,"$(libdir)"
|
ifndef CONFIG_OSX
|
||||||
|
LINK_LIBTCC += -Wl,-rpath,"$(libdir)"
|
||||||
|
else
|
||||||
|
# macOS doesn't support env-vars libdir out of the box - which we need for
|
||||||
|
# `make test' when libtcc.dylib is used (configure --disable-static), so
|
||||||
|
# we bake a relative path into the binary. $libdir is used after install.
|
||||||
|
LINK_LIBTCC += -Wl,-rpath,"@executable_path/$(TOP)" -Wl,-rpath,"$(libdir)"
|
||||||
|
# -current/compatibility_version must not contain letters.
|
||||||
|
MACOS_DYLIB_VERSION := $(firstword $(subst rc, ,$(VERSION)))
|
||||||
|
DYLIBVER += -current_version $(MACOS_DYLIB_VERSION)
|
||||||
|
DYLIBVER += -compatibility_version $(MACOS_DYLIB_VERSION)
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
CFGWIN =-unx
|
|
||||||
NATIVE_TARGET = $(ARCH)
|
NATIVE_TARGET = $(ARCH)
|
||||||
ifdef CONFIG_OSX
|
ifdef CONFIG_OSX
|
||||||
NATIVE_TARGET = $(ARCH)-osx
|
NATIVE_TARGET = $(ARCH)-osx
|
||||||
LDFLAGS += -flat_namespace -undefined warning
|
ifneq ($(CC_NAME),tcc)
|
||||||
export MACOSX_DEPLOYMENT_TARGET := 10.2
|
LDFLAGS += -flat_namespace
|
||||||
|
ifneq (1,$(shell expr $(GCC_MAJOR) ">=" 15))
|
||||||
|
LDFLAGS += -undefined warning # depreciated in clang >= 15.0
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
export MACOSX_DEPLOYMENT_TARGET := 10.6
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# run local version of tcc with local libraries and includes
|
# run local version of tcc with local libraries and includes
|
||||||
TCCFLAGS-unx = -B$(TOP) -I$(TOPSRC)/include -I$(TOPSRC) -I$(TOP)
|
TCCFLAGS-unx = -B$(TOP) -I$(TOPSRC)/include -I$(TOPSRC) -I$(TOP)
|
||||||
TCCFLAGS-win = -B$(TOPSRC)/win32 -I$(TOPSRC)/include -I$(TOPSRC) -I$(TOP) -L$(TOP)
|
TCCFLAGS-win = -B$(TOPSRC)/win32 -I$(TOPSRC)/include -I$(TOPSRC) -I$(TOP) -L$(TOP)
|
||||||
TCCFLAGS = $(TCCFLAGS$(CFGWIN))
|
TCCFLAGS = $(TCCFLAGS$(CFG))
|
||||||
TCC = $(TOP)/tcc$(EXESUF) $(TCCFLAGS)
|
TCC_LOCAL = $(TOP)/tcc$(EXESUF)
|
||||||
ifdef CONFIG_OSX
|
TCC = $(TCC_LOCAL) $(TCCFLAGS)
|
||||||
TCCFLAGS += -D_ANSI_SOURCE
|
|
||||||
|
# run tests with the installed tcc instead
|
||||||
|
ifdef TESTINSTALL
|
||||||
|
TCC_LOCAL = $(bindir)/tcc
|
||||||
|
TCCFLAGS-unx = -I$(TOP)
|
||||||
|
TCCFLAGS-win = -B$(bindir) -I$(TOP)
|
||||||
|
-LTCC = $(libdir)/$(LIBTCC) $(LINK_LIBTCC)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CFLAGS_P = $(CFLAGS) -pg -static -DCONFIG_TCC_STATIC -DTCC_PROFILE
|
CFLAGS_P = $(CFLAGS) -pg -static -DCONFIG_TCC_STATIC -DTCC_PROFILE
|
||||||
LIBS_P = $(LIBS)
|
LIBS_P = $(LIBS)
|
||||||
LDFLAGS_P = $(LDFLAGS)
|
LDFLAGS_P = $(LDFLAGS)
|
||||||
|
|
||||||
CONFIG_$(ARCH) = yes
|
DEF-i386 = -DTCC_TARGET_I386
|
||||||
NATIVE_DEFINES_$(CONFIG_i386) += -DTCC_TARGET_I386
|
DEF-i386-win32 = -DTCC_TARGET_I386 -DTCC_TARGET_PE
|
||||||
NATIVE_DEFINES_$(CONFIG_x86_64) += -DTCC_TARGET_X86_64
|
DEF-i386-OpenBSD = $(DEF-i386) -DTARGETOS_OpenBSD
|
||||||
NATIVE_DEFINES_$(CONFIG_WIN32) += -DTCC_TARGET_PE
|
DEF-x86_64 = -DTCC_TARGET_X86_64
|
||||||
NATIVE_DEFINES_$(CONFIG_OSX) += -DTCC_TARGET_MACHO
|
DEF-x86_64-win32 = -DTCC_TARGET_X86_64 -DTCC_TARGET_PE
|
||||||
NATIVE_DEFINES_$(CONFIG_uClibc) += -DTCC_UCLIBC
|
DEF-x86_64-osx = -DTCC_TARGET_X86_64 -DTCC_TARGET_MACHO
|
||||||
NATIVE_DEFINES_$(CONFIG_musl) += -DTCC_MUSL
|
DEF-arm-fpa = -DTCC_TARGET_ARM
|
||||||
NATIVE_DEFINES_$(CONFIG_libgcc) += -DCONFIG_USE_LIBGCC
|
DEF-arm-fpa-ld = -DTCC_TARGET_ARM -DLDOUBLE_SIZE=12
|
||||||
NATIVE_DEFINES_$(CONFIG_selinux) += -DHAVE_SELINUX
|
DEF-arm-vfp = -DTCC_TARGET_ARM -DTCC_ARM_VFP
|
||||||
NATIVE_DEFINES_$(CONFIG_arm) += -DTCC_TARGET_ARM
|
DEF-arm-eabi = -DTCC_TARGET_ARM -DTCC_ARM_VFP -DTCC_ARM_EABI
|
||||||
NATIVE_DEFINES_$(CONFIG_arm_eabihf) += -DTCC_ARM_EABI -DTCC_ARM_HARDFLOAT
|
DEF-arm-eabihf = $(DEF-arm-eabi) -DTCC_ARM_HARDFLOAT
|
||||||
NATIVE_DEFINES_$(CONFIG_arm_eabi) += -DTCC_ARM_EABI
|
DEF-arm = $(DEF-arm-eabihf)
|
||||||
NATIVE_DEFINES_$(CONFIG_arm_vfp) += -DTCC_ARM_VFP
|
DEF-arm-NetBSD = $(DEF-arm-eabihf) -DTARGETOS_NetBSD
|
||||||
NATIVE_DEFINES_$(CONFIG_arm64) += -DTCC_TARGET_ARM64
|
DEF-arm-wince = $(DEF-arm-eabihf) -DTCC_TARGET_PE
|
||||||
NATIVE_DEFINES += $(NATIVE_DEFINES_yes)
|
DEF-arm64 = -DTCC_TARGET_ARM64
|
||||||
|
DEF-arm64-osx = $(DEF-arm64) -DTCC_TARGET_MACHO
|
||||||
|
DEF-arm64-FreeBSD = $(DEF-arm64) -DTARGETOS_FreeBSD
|
||||||
|
DEF-arm64-NetBSD = $(DEF-arm64) -DTARGETOS_NetBSD
|
||||||
|
DEF-arm64-OpenBSD = $(DEF-arm64) -DTARGETOS_OpenBSD
|
||||||
|
DEF-arm64-win32 = $(DEF-arm64) -DTCC_TARGET_PE
|
||||||
|
DEF-riscv64 = -DTCC_TARGET_RISCV64
|
||||||
|
DEF-c67 = -DTCC_TARGET_C67 -w # disable warnigs
|
||||||
|
DEF-x86_64-FreeBSD = $(DEF-x86_64) -DTARGETOS_FreeBSD
|
||||||
|
DEF-x86_64-NetBSD = $(DEF-x86_64) -DTARGETOS_NetBSD
|
||||||
|
DEF-x86_64-OpenBSD = $(DEF-x86_64) -DTARGETOS_OpenBSD
|
||||||
|
|
||||||
ifeq ($(INCLUDED),no)
|
ifeq ($(INCLUDED),no)
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
# running top Makefile
|
# running top Makefile
|
||||||
|
|
||||||
PROGS = tcc$(EXESUF)
|
PROGS = tcc$(EXESUF)
|
||||||
TCCLIBS = $(LIBTCC1) $(LIBTCC) $(LIBTCCDEF)
|
TCCLIBS = $(LIBTCCDEF) $(LIBTCC) $(LIBTCC1)
|
||||||
TCCDOCS = tcc.1 tcc-doc.html tcc-doc.info
|
TCCDOCS = tcc.1 tcc-doc.html tcc-doc.info
|
||||||
|
|
||||||
all: $(PROGS) $(TCCLIBS) $(TCCDOCS)
|
all: $(PROGS) $(TCCLIBS) $(TCCDOCS)
|
||||||
|
|
||||||
# cross compiler targets to build
|
# cross compiler targets to build
|
||||||
TCC_X = i386 x86_64 i386-win32 x86_64-win32 x86_64-osx arm arm64 arm-wince c67
|
TCC_X = i386 x86_64 i386-win32 x86_64-win32 x86_64-osx arm arm64 arm64-win32 arm-wince c67
|
||||||
|
TCC_X += riscv64 arm64-osx
|
||||||
# TCC_X += arm-fpa arm-fpa-ld arm-vfp arm-eabi
|
# TCC_X += arm-fpa arm-fpa-ld arm-vfp arm-eabi
|
||||||
|
|
||||||
# cross libtcc1.a targets to build
|
# cross libtcc1.a targets to build
|
||||||
LIBTCC1_X = i386 x86_64 i386-win32 x86_64-win32 x86_64-osx arm arm64 arm-wince
|
LIBTCC1_X = $(filter-out c67,$(TCC_X))
|
||||||
|
|
||||||
PROGS_CROSS = $(foreach X,$(TCC_X),$X-tcc$(EXESUF))
|
PROGS_CROSS = $(foreach X,$(TCC_X),$X-tcc$(EXESUF))
|
||||||
LIBTCC1_CROSS = $(foreach X,$(LIBTCC1_X),$X-libtcc1.a)
|
LIBTCC1_CROSS = $(foreach X,$(LIBTCC1_X),$X-libtcc1.a)
|
||||||
@ -106,66 +149,76 @@ cross: $(LIBTCC1_CROSS) $(PROGS_CROSS)
|
|||||||
# build specific cross compiler & lib
|
# build specific cross compiler & lib
|
||||||
cross-%: %-tcc$(EXESUF) %-libtcc1.a ;
|
cross-%: %-tcc$(EXESUF) %-libtcc1.a ;
|
||||||
|
|
||||||
install: ; @$(MAKE) --no-print-directory install$(CFGWIN)
|
install: ; @$(MAKE) --no-print-directory install$(CFG)
|
||||||
install-strip: ; @$(MAKE) --no-print-directory install$(CFGWIN) CONFIG_strip=yes
|
install-strip: ; @$(MAKE) --no-print-directory install$(CFG) CONFIG_strip=yes
|
||||||
uninstall: ; @$(MAKE) --no-print-directory uninstall$(CFGWIN)
|
uninstall: ; @$(MAKE) --no-print-directory uninstall$(CFG)
|
||||||
|
|
||||||
ifdef CONFIG_cross
|
ifdef CONFIG_cross
|
||||||
all : cross
|
all : cross
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
|
T = $(or $(CROSS_TARGET),$(NATIVE_TARGET))
|
||||||
T = $(or $(CROSS_TARGET),$(NATIVE_TARGET),unknown)
|
|
||||||
X = $(if $(CROSS_TARGET),$(CROSS_TARGET)-)
|
X = $(if $(CROSS_TARGET),$(CROSS_TARGET)-)
|
||||||
|
|
||||||
DEF-i386 = -DTCC_TARGET_I386
|
ifneq ($(T),$(NATIVE_TARGET))
|
||||||
DEF-x86_64 = -DTCC_TARGET_X86_64
|
$(if $(DEF-$T),,$(error error: unknown target: '$T'))
|
||||||
DEF-i386-win32 = -DTCC_TARGET_PE -DTCC_TARGET_I386
|
ifneq ($(CONFIG_WIN32),yes)
|
||||||
DEF-x86_64-win32= -DTCC_TARGET_PE -DTCC_TARGET_X86_64
|
DEF-win = -DCONFIG_TCCDIR="\"$(tccdir)/win32\""
|
||||||
DEF-x86_64-osx = -DTCC_TARGET_MACHO -DTCC_TARGET_X86_64
|
endif
|
||||||
DEF-arm-wince = -DTCC_TARGET_PE -DTCC_TARGET_ARM -DTCC_ARM_EABI -DTCC_ARM_VFP -DTCC_ARM_HARDFLOAT
|
# some default config for cross compilers
|
||||||
DEF-arm64 = -DTCC_TARGET_ARM64
|
TRIPLET-i386 = i686-linux-gnu
|
||||||
DEF-c67 = -DTCC_TARGET_C67 -w # disable warnigs
|
TRIPLET-x86_64 = x86_64-linux-gnu
|
||||||
DEF-arm-fpa = -DTCC_TARGET_ARM
|
TRIPLET-arm = arm-linux-gnueabihf
|
||||||
DEF-arm-fpa-ld = -DTCC_TARGET_ARM -DLDOUBLE_SIZE=12
|
TRIPLET-arm64 = aarch64-linux-gnu
|
||||||
DEF-arm-vfp = -DTCC_TARGET_ARM -DTCC_ARM_VFP
|
TRIPLET-riscv64 = riscv64-linux-gnu
|
||||||
DEF-arm-eabi = -DTCC_TARGET_ARM -DTCC_ARM_VFP -DTCC_ARM_EABI
|
ifneq ($(TRIPLET-$T),)
|
||||||
DEF-arm-eabihf = -DTCC_TARGET_ARM -DTCC_ARM_VFP -DTCC_ARM_EABI -DTCC_ARM_HARDFLOAT
|
# assume support files in "/usr/<triplet>"
|
||||||
DEF-arm = $(DEF-arm-eabihf)
|
ROOT-$T = /usr/$(TRIPLET-$T)
|
||||||
DEF-$(NATIVE_TARGET) = $(NATIVE_DEFINES)
|
INC-$T = {B}/include:{R}/include
|
||||||
|
LIB-$T = {R}/lib:{B}
|
||||||
DEFINES += $(DEF-$T) $(DEF-all)
|
CRT-$T = {R}/lib
|
||||||
|
endif
|
||||||
|
DEFINES += $(DEF-$T)
|
||||||
DEFINES += $(if $(ROOT-$T),-DCONFIG_SYSROOT="\"$(ROOT-$T)\"")
|
DEFINES += $(if $(ROOT-$T),-DCONFIG_SYSROOT="\"$(ROOT-$T)\"")
|
||||||
DEFINES += $(if $(CRT-$T),-DCONFIG_TCC_CRTPREFIX="\"$(CRT-$T)\"")
|
DEFINES += $(if $(CRT-$T),-DCONFIG_TCC_CRTPREFIX="\"$(CRT-$T)\"")
|
||||||
DEFINES += $(if $(LIB-$T),-DCONFIG_TCC_LIBPATHS="\"$(LIB-$T)\"")
|
DEFINES += $(if $(LIB-$T),-DCONFIG_TCC_LIBPATHS="\"$(LIB-$T)\"")
|
||||||
DEFINES += $(if $(INC-$T),-DCONFIG_TCC_SYSINCLUDEPATHS="\"$(INC-$T)\"")
|
DEFINES += $(if $(INC-$T),-DCONFIG_TCC_SYSINCLUDEPATHS="\"$(INC-$T)\"")
|
||||||
|
DEFINES += $(if $(ELF-$T),-DCONFIG_TCC_ELFINTERP="\"$(ELF-$T)\"")
|
||||||
DEFINES += $(DEF-$(or $(findstring win,$T),unx))
|
DEFINES += $(DEF-$(or $(findstring win,$T),unx))
|
||||||
|
DEFINES += -DCONFIG_TCC_CROSSPREFIX="\"$X\""
|
||||||
ifneq ($(X),)
|
|
||||||
ifeq ($(CONFIG_WIN32),yes)
|
|
||||||
DEF-win += -DTCC_LIBTCC1="\"$(X)libtcc1.a\""
|
|
||||||
DEF-unx += -DTCC_LIBTCC1="\"lib/$(X)libtcc1.a\""
|
|
||||||
else
|
|
||||||
DEF-all += -DTCC_LIBTCC1="\"$(X)libtcc1.a\""
|
|
||||||
DEF-win += -DCONFIG_TCCDIR="\"$(tccdir)/win32\""
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# include custom configuration (see make help)
|
# include custom configuration (see make help)
|
||||||
-include config-extra.mak
|
-include config-extra.mak
|
||||||
|
|
||||||
CORE_FILES = tcc.c tcctools.c libtcc.c tccpp.c tccgen.c tccelf.c tccasm.c tccrun.c
|
# so one can use: make EXTRA-DEFS=...
|
||||||
|
DEFINES += $(EXTRA-DEFS)
|
||||||
|
|
||||||
|
# find config.h with 'out of tree' builds
|
||||||
|
DEFINES += -I$(TOP)
|
||||||
|
|
||||||
|
CORE_FILES = tcc.c tcctools.c libtcc.c tccpp.c tccgen.c tccdbg.c tccelf.c tccasm.c tccrun.c
|
||||||
CORE_FILES += tcc.h config.h libtcc.h tcctok.h
|
CORE_FILES += tcc.h config.h libtcc.h tcctok.h
|
||||||
i386_FILES = $(CORE_FILES) i386-gen.c i386-link.c i386-asm.c i386-asm.h i386-tok.h
|
i386_FILES = $(CORE_FILES) i386-gen.c i386-link.c i386-asm.c i386-asm.h i386-tok.h
|
||||||
i386-win32_FILES = $(i386_FILES) tccpe.c
|
i386-win32_FILES = $(i386_FILES) tccpe.c
|
||||||
x86_64_FILES = $(CORE_FILES) x86_64-gen.c x86_64-link.c i386-asm.c x86_64-asm.h
|
x86_64_FILES = $(CORE_FILES) x86_64-gen.c x86_64-link.c i386-asm.c x86_64-asm.h
|
||||||
x86_64-win32_FILES = $(x86_64_FILES) tccpe.c
|
x86_64-win32_FILES = $(x86_64_FILES) tccpe.c
|
||||||
x86_64-osx_FILES = $(x86_64_FILES)
|
x86_64-osx_FILES = $(x86_64_FILES) tccmacho.c
|
||||||
arm_FILES = $(CORE_FILES) arm-gen.c arm-link.c arm-asm.c
|
arm_FILES = $(CORE_FILES) arm-gen.c arm-link.c arm-asm.c arm-tok.h
|
||||||
arm-wince_FILES = $(arm_FILES) tccpe.c
|
arm-wince_FILES = $(arm_FILES) tccpe.c
|
||||||
arm64_FILES = $(CORE_FILES) arm64-gen.c arm64-link.c
|
arm-fpa_FILES = $(arm_FILES)
|
||||||
|
arm-fpa-ld_FILES = $(arm_FILES)
|
||||||
|
arm-vfp_FILES = $(arm_FILES)
|
||||||
|
arm-eabi_FILES = $(arm_FILES)
|
||||||
|
arm-eabihf_FILES = $(arm_FILES)
|
||||||
|
arm64_FILES = $(CORE_FILES) arm64-gen.c arm64-link.c arm64-asm.c arm64-tok.h
|
||||||
|
arm64-osx_FILES = $(arm64_FILES) tccmacho.c
|
||||||
|
arm64-win32_FILES = $(arm64_FILES) tccpe.c
|
||||||
c67_FILES = $(CORE_FILES) c67-gen.c c67-link.c tcccoff.c
|
c67_FILES = $(CORE_FILES) c67-gen.c c67-link.c tcccoff.c
|
||||||
|
riscv64_FILES = $(CORE_FILES) riscv64-gen.c riscv64-link.c riscv64-asm.c
|
||||||
|
|
||||||
|
TCCDEFS_H$(subst yes,,$(CONFIG_predefs)) = tccdefs_.h
|
||||||
|
|
||||||
# libtcc sources
|
# libtcc sources
|
||||||
LIBTCC_SRC = $(filter-out tcc.c tcctools.c,$(filter %.c,$($T_FILES)))
|
LIBTCC_SRC = $(filter-out tcc.c tcctools.c,$(filter %.c,$($T_FILES)))
|
||||||
@ -174,100 +227,158 @@ ifeq ($(ONE_SOURCE),yes)
|
|||||||
LIBTCC_OBJ = $(X)libtcc.o
|
LIBTCC_OBJ = $(X)libtcc.o
|
||||||
LIBTCC_INC = $($T_FILES)
|
LIBTCC_INC = $($T_FILES)
|
||||||
TCC_FILES = $(X)tcc.o
|
TCC_FILES = $(X)tcc.o
|
||||||
tcc.o : DEFINES += -DONE_SOURCE=0
|
$(X)tcc.o $(X)libtcc.o : $(TCCDEFS_H)
|
||||||
else
|
else
|
||||||
LIBTCC_OBJ = $(patsubst %.c,$(X)%.o,$(LIBTCC_SRC))
|
LIBTCC_OBJ = $(patsubst %.c,$(X)%.o,$(LIBTCC_SRC))
|
||||||
LIBTCC_INC = $(filter %.h %-gen.c %-link.c,$($T_FILES))
|
LIBTCC_INC = $(filter %.h %-gen.c %-link.c,$($T_FILES))
|
||||||
TCC_FILES = $(X)tcc.o $(LIBTCC_OBJ)
|
TCC_FILES = $(X)tcc.o $(LIBTCC_OBJ)
|
||||||
$(TCC_FILES) : DEFINES += -DONE_SOURCE=0
|
$(X)tccpp.o : $(TCCDEFS_H)
|
||||||
|
$(X)libtcc.o : DEFINES += -DONE_SOURCE=0
|
||||||
|
$(CROSS_TARGET)-tcc.o : DEFINES += -DONE_SOURCE=0
|
||||||
endif
|
endif
|
||||||
|
# native tcc always made from tcc.o and libtcc.[so|a]
|
||||||
|
tcc.o : DEFINES += -DONE_SOURCE=0
|
||||||
|
|
||||||
|
GITHASH:=$(shell git rev-parse --abbrev-ref HEAD 2>/dev/null || echo no)
|
||||||
|
ifneq ($(GITHASH),no)
|
||||||
|
GITHASH:=$(shell git log -1 --date=short --pretty='format:%cd $(GITHASH)@%h')
|
||||||
|
GITMODF:=$(shell git diff --quiet || echo '*')
|
||||||
|
DEF_GITHASH:= -DTCC_GITHASH="\"$(GITHASH)$(GITMODF)\""
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_debug),yes)
|
||||||
|
CFLAGS += -g
|
||||||
|
LDFLAGS += -g
|
||||||
|
endif
|
||||||
|
|
||||||
|
# convert "include/tccdefs.h" to "tccdefs_.h"
|
||||||
|
%_.h : include/%.h c2str.exe
|
||||||
|
$S./c2str.exe $< $@
|
||||||
|
|
||||||
|
c2str.exe : conftest.c
|
||||||
|
$S$(CC) -DC2STR $< -o $@
|
||||||
|
|
||||||
# target specific object rule
|
# target specific object rule
|
||||||
$(X)%.o : %.c $(LIBTCC_INC)
|
$(X)%.o : %.c $(LIBTCC_INC)
|
||||||
$(CC) -o $@ -c $< $(DEFINES) $(CFLAGS)
|
$S$(CC) -o $@ -c $< $(addsuffix ,$(DEFINES) $(CFLAGS))
|
||||||
|
|
||||||
# additional dependencies
|
# additional dependencies
|
||||||
$(X)tcc.o : tcctools.c
|
$(X)tcc.o : tcctools.c
|
||||||
|
$(X)tcc.o : DEFINES += $(DEF_GITHASH)
|
||||||
|
|
||||||
# Host Tiny C Compiler
|
# Host Tiny C Compiler
|
||||||
tcc$(EXESUF): tcc.o $(LIBTCC)
|
tcc$(EXESUF): tcc.o $(LIBTCC)
|
||||||
$(CC) -o $@ $^ $(LIBS) $(LDFLAGS) $(LINK_LIBTCC)
|
$S$(CC) -o $@ $^ $(addsuffix ,$(LIBS) $(LDFLAGS) $(LINK_LIBTCC))
|
||||||
|
|
||||||
# Cross Tiny C Compilers
|
# Cross Tiny C Compilers
|
||||||
%-tcc$(EXESUF): FORCE
|
# (the TCCDEFS_H dependency is only necessary for parallel makes,
|
||||||
|
# ala 'make -j x86_64-tcc i386-tcc tcc', which would create multiple
|
||||||
|
# c2str.exe and tccdefs_.h files in parallel, leading to access errors.
|
||||||
|
# This forces it to be made only once. Make normally tracks multiple paths
|
||||||
|
# to the same goals and only remakes it once, but that doesn't work over
|
||||||
|
# sub-makes like in this target)
|
||||||
|
%-tcc$(EXESUF): $(TCCDEFS_H) FORCE
|
||||||
@$(MAKE) --no-print-directory $@ CROSS_TARGET=$* ONE_SOURCE=$(or $(ONE_SOURCE),yes)
|
@$(MAKE) --no-print-directory $@ CROSS_TARGET=$* ONE_SOURCE=$(or $(ONE_SOURCE),yes)
|
||||||
|
|
||||||
$(CROSS_TARGET)-tcc$(EXESUF): $(TCC_FILES)
|
$(CROSS_TARGET)-tcc$(EXESUF): $(TCC_FILES)
|
||||||
$(CC) -o $@ $^ $(LIBS) $(LDFLAGS)
|
$S$(CC) -o $@ $^ $(LIBS) $(LDFLAGS)
|
||||||
|
|
||||||
# profiling version
|
# profiling version
|
||||||
tcc_p$(EXESUF): $($T_FILES)
|
tcc_p$(EXESUF): $($T_FILES)
|
||||||
$(CC) -o $@ $< $(DEFINES) $(CFLAGS_P) $(LIBS_P) $(LDFLAGS_P)
|
$S$(CC) -o $@ $< $(DEFINES) $(CFLAGS_P) $(LIBS_P) $(LDFLAGS_P)
|
||||||
|
|
||||||
# static libtcc library
|
# static libtcc library
|
||||||
libtcc.a: $(LIBTCC_OBJ)
|
libtcc.a: $(LIBTCC_OBJ)
|
||||||
$(AR) rcs $@ $^
|
$S$(AR) rcs $@ $^
|
||||||
|
|
||||||
|
ifeq ($(CC_NAME)-$(ARCH),clang-x86_64)
|
||||||
|
# avoid 32-bit relocations in libtcc.a for its usage with tcc -run
|
||||||
|
libtcc.a: override CFLAGS += -fPIC
|
||||||
|
endif
|
||||||
|
|
||||||
# dynamic libtcc library
|
# dynamic libtcc library
|
||||||
libtcc.so: $(LIBTCC_OBJ)
|
libtcc.so: $(LIBTCC_OBJ)
|
||||||
$(CC) -shared -Wl,-soname,$@ -o $@ $^ $(LDFLAGS)
|
$S$(CC) -shared -Wl,-soname,$@ -o $@ $^ $(LIBS) $(LDFLAGS)
|
||||||
|
|
||||||
libtcc.so: CFLAGS+=-fPIC
|
libtcc.so: override CFLAGS += -fPIC
|
||||||
libtcc.so: LDFLAGS+=-fPIC
|
libtcc.so: override LDFLAGS += -fPIC
|
||||||
|
|
||||||
|
# OSX dynamic libtcc library
|
||||||
|
libtcc.dylib: $(LIBTCC_OBJ)
|
||||||
|
$S$(CC) -dynamiclib $(DYLIBVER) -install_name @rpath/$@ -o $@ $^ $(LDFLAGS)
|
||||||
|
|
||||||
|
# OSX libtcc.dylib (without rpath/ prefix)
|
||||||
|
libtcc.osx: $(LIBTCC_OBJ)
|
||||||
|
$S$(CC) -shared -install_name libtcc.dylib -o libtcc.dylib $^ $(LDFLAGS)
|
||||||
|
|
||||||
# windows dynamic libtcc library
|
# windows dynamic libtcc library
|
||||||
libtcc.dll : $(LIBTCC_OBJ)
|
libtcc.dll : $(LIBTCC_OBJ)
|
||||||
$(CC) -shared -o $@ $^ $(LDFLAGS)
|
$S$(CC) -shared -o $@ $^ $(LDFLAGS)
|
||||||
libtcc.dll : DEFINES += -DLIBTCC_AS_DLL
|
libtcc.dll : DEFINES += -DLIBTCC_AS_DLL
|
||||||
|
|
||||||
# import file for windows libtcc.dll
|
# import file for windows libtcc.dll
|
||||||
libtcc.def : libtcc.dll tcc$(EXESUF)
|
libtcc.def : libtcc.dll tcc$(EXESUF)
|
||||||
$(XTCC) -impdef $< -o $@
|
$S$(XTCC) -impdef $< -o $@
|
||||||
XTCC ?= ./tcc$(EXESUF)
|
XTCC ?= ./tcc$(EXESUF)
|
||||||
|
|
||||||
# TinyCC runtime libraries
|
# TinyCC runtime libraries
|
||||||
libtcc1.a : tcc$(EXESUF) FORCE
|
libtcc1.a : tcc$(EXESUF) FORCE
|
||||||
@$(MAKE) -C lib DEFINES='$(DEF-$T)'
|
@$(MAKE) -C lib
|
||||||
|
|
||||||
# Cross libtcc1.a
|
# Cross libtcc1.a
|
||||||
%-libtcc1.a : %-tcc$(EXESUF) FORCE
|
%-libtcc1.a : %-tcc$(EXESUF) FORCE
|
||||||
@$(MAKE) -C lib DEFINES='$(DEF-$*)' CROSS_TARGET=$*
|
@$(MAKE) -C lib CROSS_TARGET=$*
|
||||||
|
|
||||||
.PRECIOUS: %-libtcc1.a
|
.PRECIOUS: %-libtcc1.a
|
||||||
FORCE:
|
FORCE:
|
||||||
|
|
||||||
|
# WHICH = which $1 2>/dev/null
|
||||||
|
# some versions of gnu-make do not recognize 'command' as a shell builtin
|
||||||
|
WHICH = sh -c 'command -v $1'
|
||||||
|
|
||||||
|
run-if = $(if $(shell $(call WHICH,$1x)),$S $1 $2,@true||echo "(skipping $@ - no $1)")
|
||||||
|
S = $(if $(findstring yes,$(SILENT)),@$(info * $@))
|
||||||
|
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
# documentation and man page
|
# documentation and man page
|
||||||
tcc-doc.html: tcc-doc.texi
|
tcc-doc.html: tcc-doc.texi
|
||||||
makeinfo --no-split --html --number-sections -o $@ $< || true
|
$(call run-if,makeinfo,--no-split --html --number-sections -o $@ $<)
|
||||||
|
|
||||||
tcc.1: tcc-doc.texi
|
|
||||||
$(TOPSRC)/texi2pod.pl $< tcc.pod \
|
|
||||||
&& pod2man --section=1 --center="Tiny C Compiler" --release="$(VERSION)" tcc.pod >tmp.1 \
|
|
||||||
&& mv tmp.1 $@ || rm -f tmp.1
|
|
||||||
|
|
||||||
tcc-doc.info: tcc-doc.texi
|
tcc-doc.info: tcc-doc.texi
|
||||||
makeinfo $< || true
|
$(call run-if,makeinfo,$< || true)
|
||||||
|
|
||||||
|
tcc.1 : tcc-doc.pod
|
||||||
|
$(call run-if,pod2man,--section=1 --center="Tiny C Compiler" \
|
||||||
|
--release="$(VERSION)" $< >$@)
|
||||||
|
%.pod : %.texi
|
||||||
|
$(call run-if,perl,$(TOPSRC)/texi2pod.pl $< $@)
|
||||||
|
|
||||||
|
doc : $(TCCDOCS)
|
||||||
|
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
# install
|
# install
|
||||||
|
|
||||||
INSTALL = install -m644
|
INSTALL = install -m 644
|
||||||
INSTALLBIN = install -m755 $(STRIP_$(CONFIG_strip))
|
INSTALLBIN = install -m 755 $(STRIP_$(CONFIG_strip))
|
||||||
STRIP_yes = -s
|
STRIP_yes = -s
|
||||||
|
|
||||||
LIBTCC1_W = $(filter %-win32-libtcc1.a %-wince-libtcc1.a,$(LIBTCC1_CROSS))
|
LIBTCC1_W = $(filter %-win32-libtcc1.a %-wince-libtcc1.a,$(LIBTCC1_CROSS))
|
||||||
LIBTCC1_U = $(filter-out $(LIBTCC1_W),$(LIBTCC1_CROSS))
|
LIBTCC1_U = $(filter-out $(LIBTCC1_W),$(wildcard *-libtcc1.a))
|
||||||
IB = $(if $1,mkdir -p $2 && $(INSTALLBIN) $1 $2)
|
IB = $(if $1,$(IM) mkdir -p $2 && $(INSTALLBIN) $1 $2)
|
||||||
IBw = $(call IB,$(wildcard $1),$2)
|
IBw = $(call IB,$(wildcard $1),$2)
|
||||||
IF = $(if $1,mkdir -p $2 && $(INSTALL) $1 $2)
|
IF = $(if $1,$(IM) mkdir -p $2 && $(INSTALL) $1 $2)
|
||||||
IFw = $(call IF,$(wildcard $1),$2)
|
IFw = $(call IF,$(wildcard $1),$2)
|
||||||
IR = mkdir -p $2 && cp -r $1/. $2
|
IR = $(IM) mkdir -p $2 && cp -r $1/. $2
|
||||||
|
IM = @echo "-> $2 : $1" ;
|
||||||
|
BINCHECK = $(if $(wildcard $(PROGS) *-tcc$(EXESUF)),,@echo "Makefile: nothing found to install" && exit 1)
|
||||||
|
|
||||||
|
EXTRA_O = runmain.o bt-exe.o bt-dll.o bt-log.o bcheck.o
|
||||||
|
|
||||||
# install progs & libs
|
# install progs & libs
|
||||||
install-unx:
|
install-unx:
|
||||||
$(call IBw,$(PROGS) $(PROGS_CROSS),"$(bindir)")
|
$(call BINCHECK)
|
||||||
$(call IFw,$(LIBTCC1) $(LIBTCC1_U),"$(tccdir)")
|
$(call IBw,$(PROGS) *-tcc,"$(bindir)")
|
||||||
|
$(call IFw,$(LIBTCC1) $(EXTRA_O) $(LIBTCC1_U),"$(tccdir)")
|
||||||
$(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/include")
|
$(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/include")
|
||||||
$(call $(if $(findstring .so,$(LIBTCC)),IBw,IFw),$(LIBTCC),"$(libdir)")
|
$(call $(if $(findstring .so,$(LIBTCC)),IBw,IFw),$(LIBTCC),"$(libdir)")
|
||||||
$(call IF,$(TOPSRC)/libtcc.h,"$(includedir)")
|
$(call IF,$(TOPSRC)/libtcc.h,"$(includedir)")
|
||||||
@ -282,40 +393,43 @@ endif
|
|||||||
|
|
||||||
# uninstall
|
# uninstall
|
||||||
uninstall-unx:
|
uninstall-unx:
|
||||||
@rm -fv $(foreach P,$(PROGS) $(PROGS_CROSS),"$(bindir)/$P")
|
@rm -fv $(addprefix "$(bindir)/",$(PROGS) $(PROGS_CROSS))
|
||||||
@rm -fv "$(libdir)/libtcc.a" "$(libdir)/libtcc.so" "$(includedir)/libtcc.h"
|
@rm -fv $(addprefix "$(libdir)/", libtcc*.a libtcc*.so libtcc.dylib)
|
||||||
|
@rm -fv $(addprefix "$(includedir)/", libtcc.h)
|
||||||
@rm -fv "$(mandir)/man1/tcc.1" "$(infodir)/tcc-doc.info"
|
@rm -fv "$(mandir)/man1/tcc.1" "$(infodir)/tcc-doc.info"
|
||||||
@rm -fv "$(docdir)/tcc-doc.html"
|
@rm -fv "$(docdir)/tcc-doc.html"
|
||||||
rm -r "$(tccdir)"
|
@rm -frv "$(tccdir)"
|
||||||
|
|
||||||
# install progs & libs on windows
|
# install progs & libs on windows
|
||||||
install-win:
|
install-win:
|
||||||
$(call IBw,$(PROGS) $(PROGS_CROSS) $(subst libtcc.a,,$(LIBTCC)),"$(bindir)")
|
$(call BINCHECK)
|
||||||
|
$(call IBw,$(PROGS) *-tcc.exe libtcc.dll,"$(bindir)")
|
||||||
$(call IF,$(TOPSRC)/win32/lib/*.def,"$(tccdir)/lib")
|
$(call IF,$(TOPSRC)/win32/lib/*.def,"$(tccdir)/lib")
|
||||||
$(call IFw,libtcc1.a $(LIBTCC1_W),"$(tccdir)/lib")
|
$(call IFw,libtcc1.a $(EXTRA_O) $(LIBTCC1_W),"$(tccdir)/lib")
|
||||||
$(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/include")
|
$(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/include")
|
||||||
$(call IR,$(TOPSRC)/win32/include,"$(tccdir)/include")
|
$(call IR,$(TOPSRC)/win32/include,"$(tccdir)/include")
|
||||||
$(call IR,$(TOPSRC)/win32/examples,"$(tccdir)/examples")
|
$(call IR,$(TOPSRC)/win32/examples,"$(tccdir)/examples")
|
||||||
$(call IF,$(TOPSRC)/tests/libtcc_test.c,"$(tccdir)/examples")
|
$(call IF,$(TOPSRC)/tests/libtcc_test.c,"$(tccdir)/examples")
|
||||||
$(call IFw,$(TOPSRC)/libtcc.h $(subst .dll,.def,$(LIBTCC)),"$(libdir)")
|
$(call IFw,$(TOPSRC)/libtcc.h libtcc.def libtcc.a,"$(libdir)")
|
||||||
$(call IFw,$(TOPSRC)/win32/tcc-win32.txt tcc-doc.html,"$(docdir)")
|
$(call IFw,$(TOPSRC)/win32/tcc-win32.txt tcc-doc.html,"$(docdir)")
|
||||||
ifneq "$(wildcard $(LIBTCC1_U))" ""
|
ifneq "$(wildcard $(LIBTCC1_U))" ""
|
||||||
$(call IFw,$(LIBTCC1_U),"$(tccdir)/lib")
|
$(call IFw,$(LIBTCC1_U),"$(tccdir)/lib")
|
||||||
$(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/lib/include")
|
$(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/lib/include")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# the msys-git shell works to configure && make except it does not have install
|
|
||||||
ifeq "$(and $(CONFIG_WIN32),$(shell which install >/dev/null 2>&1 || echo no))" "no"
|
|
||||||
install-win : INSTALL = cp
|
|
||||||
install-win : INSTALLBIN = cp
|
|
||||||
endif
|
|
||||||
|
|
||||||
# uninstall on windows
|
# uninstall on windows
|
||||||
uninstall-win:
|
uninstall-win:
|
||||||
@rm -fv $(foreach P,$(PROGS) $(PROGS_CROSS) libtcc.dll,"$(bindir)/$P")
|
@rm -fv $(foreach P,libtcc*.dll $(PROGS) *-tcc.exe,"$(bindir)"/$P)
|
||||||
@rm -fv $(foreach F,tcc-doc.html tcc-win32.txt,"$(docdir)/$F")
|
@rm -fr $(foreach P,doc examples include lib libtcc,"$(tccdir)"/$P/*)
|
||||||
@rm -fv $(foreach F,libtcc.h libtcc.def libtcc.a,"$(libdir)/$F")
|
@rm -frv $(foreach P,doc examples include lib libtcc,"$(tccdir)"/$P)
|
||||||
rm -r "$(tccdir)"
|
|
||||||
|
# the msys-git shell works to configure && make except it does not have install
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
ifeq ($(shell $(call WHICH,install) || echo no),no)
|
||||||
|
INSTALL = cp
|
||||||
|
INSTALLBIN = cp
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
# other stuff
|
# other stuff
|
||||||
@ -328,8 +442,9 @@ ETAGS : ; etags $(TAGFILES)
|
|||||||
# create release tarball from *current* git branch (including tcc-doc.html
|
# create release tarball from *current* git branch (including tcc-doc.html
|
||||||
# and converting two files to CRLF)
|
# and converting two files to CRLF)
|
||||||
TCC-VERSION = tcc-$(VERSION)
|
TCC-VERSION = tcc-$(VERSION)
|
||||||
|
TCC-VERSION = tinycc-mob-$(shell git rev-parse --short=7 HEAD)
|
||||||
tar: tcc-doc.html
|
tar: tcc-doc.html
|
||||||
mkdir $(TCC-VERSION)
|
mkdir -p $(TCC-VERSION)
|
||||||
( cd $(TCC-VERSION) && git --git-dir ../.git checkout -f )
|
( cd $(TCC-VERSION) && git --git-dir ../.git checkout -f )
|
||||||
cp tcc-doc.html $(TCC-VERSION)
|
cp tcc-doc.html $(TCC-VERSION)
|
||||||
for f in tcc-win32.txt build-tcc.bat ; do \
|
for f in tcc-win32.txt build-tcc.bat ; do \
|
||||||
@ -344,60 +459,79 @@ config.mak:
|
|||||||
|
|
||||||
# run all tests
|
# run all tests
|
||||||
test:
|
test:
|
||||||
$(MAKE) -C tests
|
@$(MAKE) -C tests
|
||||||
# run test(s) from tests2 subdir (see make help)
|
# run test(s) from tests2 subdir (see make help)
|
||||||
tests2.%:
|
tests2.%:
|
||||||
$(MAKE) -C tests/tests2 $@
|
@$(MAKE) -C tests/tests2 $@
|
||||||
|
# run test(s) from testspp subdir (see make help)
|
||||||
|
testspp.%:
|
||||||
|
@$(MAKE) -C tests/pp $@
|
||||||
|
# run tests with code coverage
|
||||||
|
tcov-tes% : tcc_c$(EXESUF)
|
||||||
|
@rm -f $<.tcov
|
||||||
|
@$(MAKE) --no-print-directory TCC_LOCAL=$(CURDIR)/$< tes$*
|
||||||
|
tcc_c$(EXESUF): $($T_FILES)
|
||||||
|
$S$(TCC) tcc.c -o $@ -ftest-coverage $(DEFINES) $(LIBS)
|
||||||
|
# run tests with sanitize option
|
||||||
|
sani-tes% : tcc_s$(EXESUF)
|
||||||
|
@$(MAKE) --no-print-directory TCC_LOCAL=$(CURDIR)/$< tes$*
|
||||||
|
tcc_s$(EXESUF): $($T_FILES)
|
||||||
|
$S$(CC) tcc.c -o $@ -fsanitize=address,undefined $(DEFINES) $(CFLAGS) $(LDFLAGS) $(LIBS)
|
||||||
|
# test the installed tcc instead
|
||||||
|
test-install: $(TCCDEFS_H)
|
||||||
|
@$(MAKE) -C tests TESTINSTALL=yes #_all
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f tcc$(EXESUF) tcc_p$(EXESUF) *-tcc$(EXESUF) tcc.pod
|
@rm -f tcc *-tcc tcc_p tcc_c tcc_s
|
||||||
rm -f *~ *.o *.a *.so* *.out *.log lib*.def *.exe *.dll a.out tags TAGS
|
@rm -f tags ETAGS *.o *.a *.so* *.out *.log lib*.def *.exe *.dll
|
||||||
@$(MAKE) -C lib $@
|
@rm -f a.out *.dylib *_.h *.pod *.tcov
|
||||||
@$(MAKE) -C tests $@
|
@$(MAKE) -s -C lib $@
|
||||||
|
@$(MAKE) -s -C tests $@
|
||||||
|
|
||||||
distclean: clean
|
distclean: clean
|
||||||
rm -f config.h config.mak config.texi tcc.1 tcc-doc.info tcc-doc.html
|
@rm -vf config.h config.mak config.texi
|
||||||
|
@rm -vf $(TCCDOCS)
|
||||||
|
|
||||||
.PHONY: all clean test tar tags ETAGS distclean install uninstall FORCE
|
.PHONY: all clean test tar tags ETAGS doc distclean install uninstall FORCE
|
||||||
|
|
||||||
help:
|
help:
|
||||||
@echo "make"
|
@echo "make"
|
||||||
@echo " build native compiler (from separate objects)"
|
@echo " build native compiler (from separate objects)"
|
||||||
@echo ""
|
@echo "make ONE_SOURCE=no/yes SILENT=no/yes"
|
||||||
@echo "make cross"
|
@echo " force building from separate/one object(s), less/more silently"
|
||||||
@echo " build cross compilers (from one source)"
|
|
||||||
@echo ""
|
|
||||||
@echo "make ONE_SOURCE=yes / no"
|
|
||||||
@echo " force building from one source / separate objects"
|
|
||||||
@echo ""
|
|
||||||
@echo "make cross-TARGET"
|
@echo "make cross-TARGET"
|
||||||
@echo " build one specific cross compiler for 'TARGET', as in"
|
@echo " build one specific cross compiler for 'TARGET'. Currently supported:"
|
||||||
@echo " $(TCC_X)"
|
@echo " $(wordlist 1,8,$(TCC_X))"
|
||||||
@echo ""
|
@echo " $(wordlist 9,99,$(TCC_X))"
|
||||||
@echo "Custom configuration:"
|
@echo "make cross"
|
||||||
@echo " The makefile includes a file 'config-extra.mak' if it is present."
|
@echo " build all cross compilers"
|
||||||
@echo " This file may contain some custom configuration. For example:"
|
|
||||||
@echo ""
|
|
||||||
@echo " NATIVE_DEFINES += -D..."
|
|
||||||
@echo ""
|
|
||||||
@echo " Or for example to configure the search paths for a cross-compiler"
|
|
||||||
@echo " that expects the linux files in <tccdir>/i386-linux:"
|
|
||||||
@echo ""
|
|
||||||
@echo " ROOT-i386 = {B}/i386-linux"
|
|
||||||
@echo " CRT-i386 = {B}/i386-linux/usr/lib"
|
|
||||||
@echo " LIB-i386 = {B}/i386-linux/lib:{B}/i386-linux/usr/lib"
|
|
||||||
@echo " INC-i386 = {B}/lib/include:{B}/i386-linux/usr/include"
|
|
||||||
@echo " DEF-i386 += -D__linux__"
|
|
||||||
@echo ""
|
|
||||||
@echo "make test"
|
@echo "make test"
|
||||||
@echo " run all tests"
|
@echo " run all tests"
|
||||||
@echo ""
|
|
||||||
@echo "make tests2.all / make tests2.37 / make tests2.37+"
|
@echo "make tests2.all / make tests2.37 / make tests2.37+"
|
||||||
@echo " run all/single test(s) from tests2, optionally update .expect"
|
@echo " run all/single test(s) from tests2, optionally update .expect"
|
||||||
@echo ""
|
@echo "make testspp.all / make testspp.17"
|
||||||
|
@echo " run all/single test(s) from tests/pp"
|
||||||
|
@echo "make tcov-test / tcov-tests2.37 / tcov-testspp.17"
|
||||||
|
@echo " run tests as above with code coverage. After test(s) see tcc_c$(EXESUF).tcov"
|
||||||
|
@echo "make sani-test / sani-tests2.37 / sani-testspp.17"
|
||||||
|
@echo " run tests as above with sanitize option."
|
||||||
|
@echo "make test-install"
|
||||||
|
@echo " run tests with the installed tcc"
|
||||||
@echo "Other supported make targets:"
|
@echo "Other supported make targets:"
|
||||||
@echo " install install-strip tags ETAGS tar clean distclean help"
|
@echo " install install-strip uninstall doc [dist]clean tags ETAGS tar help"
|
||||||
@echo ""
|
@echo "Custom configuration:"
|
||||||
|
@echo " The makefile includes a file 'config-extra.mak' if it is present."
|
||||||
|
@echo " This file may contain some custom configuration. For example to"
|
||||||
|
@echo " configure the search paths for a cross-compiler, assuming the"
|
||||||
|
@echo " support files in /usr/i686-linux-gnu:"
|
||||||
|
@echo " ROOT-i386 = /usr/i686-linux-gnu"
|
||||||
|
@echo " CRT-i386 = {R}/lib"
|
||||||
|
@echo " LIB-i386 = {B}:{R}/lib"
|
||||||
|
@echo " INC-i386 = {B}/include:{R}/include (*)"
|
||||||
|
@echo " DEF-i386 += -D__linux__"
|
||||||
|
@echo " Or also, for the cross platform files in /usr/<triplet>"
|
||||||
|
@echo " TRIPLET-i386 = i686-linux-gnu"
|
||||||
|
@echo " (*) tcc replaces {B} by 'tccdir' and {R} by 'CONFIG_SYSROOT'"
|
||||||
|
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
endif # ($(INCLUDED),no)
|
endif # ($(INCLUDED),no)
|
||||||
|
|||||||
18
README
18
README
@ -7,19 +7,18 @@ Features:
|
|||||||
- SMALL! You can compile and execute C code everywhere, for example on
|
- SMALL! You can compile and execute C code everywhere, for example on
|
||||||
rescue disks.
|
rescue disks.
|
||||||
|
|
||||||
- FAST! tcc generates optimized x86 code. No byte code
|
- FAST! tcc generates machine code for i386, x86_64, arm, aarch64 or
|
||||||
overhead. Compile, assemble and link about 7 times faster than 'gcc
|
riscv64. Compiles and links about 10 times faster than 'gcc -O0'.
|
||||||
-O0'.
|
|
||||||
|
|
||||||
- UNLIMITED! Any C dynamic library can be used directly. TCC is
|
- UNLIMITED! Any C dynamic library can be used directly. TCC is
|
||||||
heading torward full ISOC99 compliance. TCC can of course compile
|
heading toward full ISOC99 compliance. TCC can of course compile
|
||||||
itself.
|
itself.
|
||||||
|
|
||||||
- SAFE! tcc includes an optional memory and bound checker. Bound
|
- SAFE! tcc includes an optional memory and bound checker. Bound
|
||||||
checked code can be mixed freely with standard code.
|
checked code can be mixed freely with standard code.
|
||||||
|
|
||||||
- Compile and execute C source directly. No linking or assembly
|
- Compile and execute C source directly. No linking or assembly
|
||||||
necessary. Full C preprocessor included.
|
necessary. Full C preprocessor included.
|
||||||
|
|
||||||
- C script supported : just add '#!/usr/local/bin/tcc -run' at the first
|
- C script supported : just add '#!/usr/local/bin/tcc -run' at the first
|
||||||
line of your C source, and execute it directly from the command
|
line of your C source, and execute it directly from the command
|
||||||
@ -28,14 +27,14 @@ Features:
|
|||||||
Documentation:
|
Documentation:
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
1) Installation on a i386/x86_64/arm Linux/OSX/FreeBSD host
|
1) Installation on Linux, BSD variants or macOS hosts:
|
||||||
|
|
||||||
./configure
|
./configure
|
||||||
make
|
make
|
||||||
make test
|
make test
|
||||||
make install
|
make install
|
||||||
|
|
||||||
Notes: For OSX and FreeBSD, gmake should be used instead of make.
|
Notes: On BSD hosts, gmake should be used instead of make.
|
||||||
For Windows read tcc-win32.txt.
|
For Windows read tcc-win32.txt.
|
||||||
|
|
||||||
makeinfo must be installed to compile the doc. By default, tcc is
|
makeinfo must be installed to compile the doc. By default, tcc is
|
||||||
@ -82,9 +81,8 @@ when doing 'make test'.
|
|||||||
|
|
||||||
4) Full Documentation
|
4) Full Documentation
|
||||||
|
|
||||||
Please read tcc-doc.html to have all the features of TCC.
|
Please read tcc-doc.html to have all the features of TCC. Additional
|
||||||
|
information for the Windows port is in tcc-win32.txt.
|
||||||
Additional information is available for the Windows port in tcc-win32.txt.
|
|
||||||
|
|
||||||
License:
|
License:
|
||||||
-------
|
-------
|
||||||
|
|||||||
@ -30,23 +30,30 @@
|
|||||||
Adam Sampson YES makefiles
|
Adam Sampson YES makefiles
|
||||||
Daniel Glöckner NO arm-gen.c
|
Daniel Glöckner NO arm-gen.c
|
||||||
Daniel Glöckner YES not arm-gen.c
|
Daniel Glöckner YES not arm-gen.c
|
||||||
|
Danny Milosavljevic YES arm-asm.c riscv64-asm.c
|
||||||
Edmund Grimley Evans YES arm64
|
Edmund Grimley Evans YES arm64
|
||||||
Fabrice Bellard YES original author
|
Fabrice Bellard YES original author
|
||||||
Frédéric Féret YES x86 64/16 bit asm
|
Frédéric Féret YES x86 64/16 bit asm
|
||||||
grischka YES tccpe.c
|
grischka YES tccpe.c
|
||||||
Henry Kroll YES
|
Henry Kroll YES
|
||||||
|
Herman ten Brugge YES
|
||||||
Joe Soroka YES
|
Joe Soroka YES
|
||||||
Kirill Smelkov YES
|
Kirill Smelkov YES
|
||||||
mingodad YES
|
mingodad YES
|
||||||
Pip Cet YES
|
Pip Cet YES
|
||||||
Shinichiro Hamaji YES x86_64-gen.c
|
Shinichiro Hamaji YES x86_64-gen.c
|
||||||
|
Steffen Nurpmeso YES
|
||||||
Vincent Lefèvre YES
|
Vincent Lefèvre YES
|
||||||
Thomas Preud'homme YES arm-gen.c
|
Thomas Preud'homme YES arm-gen.c
|
||||||
Timo VJ Lähde (Timppa) ? tiny_libmaker.c
|
Timo VJ Lähde (Timppa) ? tiny_libmaker.c
|
||||||
TK ? tcccoff.c c67-gen.c
|
TK ? tcccoff.c c67-gen.c
|
||||||
|
Tyge Løvset YES tgmath.h, Windows tcc_libm.h math.h
|
||||||
Urs Janssen YES
|
Urs Janssen YES
|
||||||
waddlesplash YES
|
waddlesplash YES
|
||||||
Christian Jullien YES Windows Cygwin build and tests
|
Christian Jullien YES Windows Cygwin build and tests
|
||||||
|
Reimar Döffinger YES
|
||||||
|
noneofyourbusiness YES
|
||||||
|
Cyan Ogilvie YES
|
||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|||||||
10
TODO
10
TODO
@ -1,5 +1,10 @@
|
|||||||
TODO list:
|
TODO list:
|
||||||
|
|
||||||
|
Releases:
|
||||||
|
|
||||||
|
- release tcc on a regular basis
|
||||||
|
- testing repo.or.cz
|
||||||
|
|
||||||
Bugs:
|
Bugs:
|
||||||
|
|
||||||
- i386 fastcall is mostly wrong
|
- i386 fastcall is mostly wrong
|
||||||
@ -33,7 +38,10 @@ Portability:
|
|||||||
|
|
||||||
Linking:
|
Linking:
|
||||||
|
|
||||||
- static linking (-static) does not work
|
- static linking (-static) does sort of work
|
||||||
|
works with musl libc
|
||||||
|
glibc requires libc.so even when statically linked (very bad, but not
|
||||||
|
up to tcc)
|
||||||
|
|
||||||
Bound checking:
|
Bound checking:
|
||||||
|
|
||||||
|
|||||||
68
USES
Normal file
68
USES
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
The following software are known to use or support tcc builds.
|
||||||
|
Feel free to complete this list (*).
|
||||||
|
|
||||||
|
Name Short Description
|
||||||
|
---- -----------------
|
||||||
|
bigz An infinite precision Z & Q library.
|
||||||
|
gawk GNU awk.
|
||||||
|
gmp Library for arbitrary precision arithmetic.
|
||||||
|
gnumake GNU makefile.
|
||||||
|
gnu mes using tinycc to bootstrap a system
|
||||||
|
mpfr Multiple-precision floating-point library.
|
||||||
|
mpc Complex floating-point library with exact rounding.
|
||||||
|
mpv A free, open source, and cross-platform media player.
|
||||||
|
openlisp ISLISP ISO/IEC 13816 Lisp interpreter and compiler.
|
||||||
|
s-nail BSD Mail/POSIX mailx: send and receive Internet mail.
|
||||||
|
sqlite Embbedable SQL engine.
|
||||||
|
st Simple Terminal.
|
||||||
|
tcc Tiny CC which compiles itself.
|
||||||
|
zlib Lossless data-compression library.
|
||||||
|
|
||||||
|
(*) This list is ordered by name.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Forks & Experiments
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
arm-thumb target
|
||||||
|
by Erlend Sveen <erlend.sveen@hotmail.com>
|
||||||
|
https://git.erlendjs.no/erlendjs/tinycc.git
|
||||||
|
|
||||||
|
riscv32 target
|
||||||
|
by Sam Ellicott <sellicott@cedarville.edu>
|
||||||
|
https://github.com/sellicott/tcc-riscv32.git
|
||||||
|
|
||||||
|
Transputer target
|
||||||
|
by David Smith <agentdavo@mac.com>
|
||||||
|
https://github.com/agentdavo/tinycc-transputer
|
||||||
|
|
||||||
|
tcc-65816 - Tiny C Compiler for 65816 CPU (based on V0.9.23) from SNES-SDK
|
||||||
|
https://github.com/nArnoSNES/tcc-65816
|
||||||
|
|
||||||
|
PE-UEFI arm64
|
||||||
|
by Andrei Warkentin <andrey.warkentin@gmail.com>
|
||||||
|
https://github.com/andreiw/tinycc/
|
||||||
|
|
||||||
|
TCCLS - global register allocator (proof of concept)
|
||||||
|
by Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
|
||||||
|
https://bitbucket.org/theStack/tccls_poc.git
|
||||||
|
|
||||||
|
softfloat
|
||||||
|
by Giovanni Mascellani <gio@debian.org>
|
||||||
|
https://gitlab.com/giomasce/tinycc.git
|
||||||
|
|
||||||
|
optimize 386
|
||||||
|
by Jason Hood <jadoxa@yahoo.com.au>
|
||||||
|
|
||||||
|
tcctcl : tcl binding
|
||||||
|
https://code.google.com/archive/p/tcltcc/
|
||||||
|
|
||||||
|
tcc4tcl : tcl binding
|
||||||
|
https://chiselapp.com/user/rkeene/repository/tcc4tcl/index
|
||||||
|
|
||||||
|
lua-tcc : allows a Lua script to compile C code
|
||||||
|
https://github.com/javierguerragiraldez/lua-tcc
|
||||||
|
|
||||||
|
tcclua : semi-high-level bindings for `libtcc`
|
||||||
|
https://github.com/nucular/tcclua/blob/master/tcc.lua
|
||||||
212
arm-link.c
212
arm-link.c
@ -12,24 +12,20 @@
|
|||||||
|
|
||||||
#define R_NUM R_ARM_NUM
|
#define R_NUM R_ARM_NUM
|
||||||
|
|
||||||
#define ELF_START_ADDR 0x00008000
|
#define ELF_START_ADDR 0x00010000
|
||||||
#define ELF_PAGE_SIZE 0x1000
|
#define ELF_PAGE_SIZE 0x10000
|
||||||
|
|
||||||
#define PCRELATIVE_DLLPLT 1
|
#define PCRELATIVE_DLLPLT 1
|
||||||
#define RELOCATE_DLLPLT 0
|
#define RELOCATE_DLLPLT 1
|
||||||
|
|
||||||
enum float_abi {
|
|
||||||
ARM_SOFTFP_FLOAT,
|
|
||||||
ARM_HARD_FLOAT,
|
|
||||||
};
|
|
||||||
|
|
||||||
#else /* !TARGET_DEFS_ONLY */
|
#else /* !TARGET_DEFS_ONLY */
|
||||||
|
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
|
|
||||||
|
#ifdef NEED_RELOC_TYPE
|
||||||
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
|
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
|
||||||
relocations, returns -1. */
|
relocations, returns -1. */
|
||||||
int code_reloc (int reloc_type)
|
ST_FUNC int code_reloc (int reloc_type)
|
||||||
{
|
{
|
||||||
switch (reloc_type) {
|
switch (reloc_type) {
|
||||||
case R_ARM_MOVT_ABS:
|
case R_ARM_MOVT_ABS:
|
||||||
@ -41,9 +37,14 @@ int code_reloc (int reloc_type)
|
|||||||
case R_ARM_GOTPC:
|
case R_ARM_GOTPC:
|
||||||
case R_ARM_GOTOFF:
|
case R_ARM_GOTOFF:
|
||||||
case R_ARM_GOT32:
|
case R_ARM_GOT32:
|
||||||
|
case R_ARM_GOT_PREL:
|
||||||
case R_ARM_COPY:
|
case R_ARM_COPY:
|
||||||
case R_ARM_GLOB_DAT:
|
case R_ARM_GLOB_DAT:
|
||||||
case R_ARM_NONE:
|
case R_ARM_NONE:
|
||||||
|
case R_ARM_TARGET1:
|
||||||
|
case R_ARM_MOVT_PREL:
|
||||||
|
case R_ARM_MOVW_PREL_NC:
|
||||||
|
case R_ARM_TLS_LE32:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case R_ARM_PC24:
|
case R_ARM_PC24:
|
||||||
@ -57,21 +58,20 @@ int code_reloc (int reloc_type)
|
|||||||
case R_ARM_JUMP_SLOT:
|
case R_ARM_JUMP_SLOT:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
tcc_error ("Unknown relocation type: %d", reloc_type);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns an enumerator to describe whether and when the relocation needs a
|
/* Returns an enumerator to describe whether and when the relocation needs a
|
||||||
GOT and/or PLT entry to be created. See tcc.h for a description of the
|
GOT and/or PLT entry to be created. See tcc.h for a description of the
|
||||||
different values. */
|
different values. */
|
||||||
int gotplt_entry_type (int reloc_type)
|
ST_FUNC int gotplt_entry_type (int reloc_type)
|
||||||
{
|
{
|
||||||
switch (reloc_type) {
|
switch (reloc_type) {
|
||||||
case R_ARM_NONE:
|
case R_ARM_NONE:
|
||||||
case R_ARM_COPY:
|
case R_ARM_COPY:
|
||||||
case R_ARM_GLOB_DAT:
|
case R_ARM_GLOB_DAT:
|
||||||
case R_ARM_JUMP_SLOT:
|
case R_ARM_JUMP_SLOT:
|
||||||
|
case R_ARM_TLS_LE32:
|
||||||
return NO_GOTPLT_ENTRY;
|
return NO_GOTPLT_ENTRY;
|
||||||
|
|
||||||
case R_ARM_PC24:
|
case R_ARM_PC24:
|
||||||
@ -88,6 +88,9 @@ int gotplt_entry_type (int reloc_type)
|
|||||||
case R_ARM_ABS32:
|
case R_ARM_ABS32:
|
||||||
case R_ARM_REL32:
|
case R_ARM_REL32:
|
||||||
case R_ARM_V4BX:
|
case R_ARM_V4BX:
|
||||||
|
case R_ARM_TARGET1:
|
||||||
|
case R_ARM_MOVT_PREL:
|
||||||
|
case R_ARM_MOVW_PREL_NC:
|
||||||
return AUTO_GOTPLT_ENTRY;
|
return AUTO_GOTPLT_ENTRY;
|
||||||
|
|
||||||
case R_ARM_GOTPC:
|
case R_ARM_GOTPC:
|
||||||
@ -95,13 +98,13 @@ int gotplt_entry_type (int reloc_type)
|
|||||||
return BUILD_GOT_ONLY;
|
return BUILD_GOT_ONLY;
|
||||||
|
|
||||||
case R_ARM_GOT32:
|
case R_ARM_GOT32:
|
||||||
|
case R_ARM_GOT_PREL:
|
||||||
return ALWAYS_GOTPLT_ENTRY;
|
return ALWAYS_GOTPLT_ENTRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
tcc_error ("Unknown relocation type: %d", reloc_type);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef NEED_BUILD_GOT
|
||||||
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
|
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
|
||||||
{
|
{
|
||||||
Section *plt = s1->plt;
|
Section *plt = s1->plt;
|
||||||
@ -110,8 +113,6 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
|
|||||||
|
|
||||||
/* when building a DLL, GOT entry accesses must be done relative to
|
/* when building a DLL, GOT entry accesses must be done relative to
|
||||||
start of GOT (see x86_64 example above) */
|
start of GOT (see x86_64 example above) */
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL)
|
|
||||||
tcc_error("DLLs unimplemented!");
|
|
||||||
|
|
||||||
/* empty PLT: create PLT0 entry that push address of call site and
|
/* empty PLT: create PLT0 entry that push address of call site and
|
||||||
jump to ld.so resolution routine (GOT + 8) */
|
jump to ld.so resolution routine (GOT + 8) */
|
||||||
@ -131,12 +132,8 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
|
|||||||
write32le(p+2, 0x46c0); /* nop */
|
write32le(p+2, 0x46c0); /* nop */
|
||||||
}
|
}
|
||||||
p = section_ptr_add(plt, 16);
|
p = section_ptr_add(plt, 16);
|
||||||
/* Jump to GOT entry where ld.so initially put address of PLT0 */
|
/* save GOT offset for relocate_plt */
|
||||||
write32le(p, 0xe59fc004); /* ldr ip, [pc, #4] */
|
write32le(p + 4, got_offset);
|
||||||
write32le(p+4, 0xe08fc00c); /* add ip, pc, ip */
|
|
||||||
write32le(p+8, 0xe59cf000); /* ldr pc, [ip] */
|
|
||||||
/* p + 12 contains offset to GOT entry once patched by relocate_plt */
|
|
||||||
write32le(p+12, got_offset);
|
|
||||||
return plt_offset;
|
return plt_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,23 +151,35 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
|||||||
|
|
||||||
if (p < p_end) {
|
if (p < p_end) {
|
||||||
int x = s1->got->sh_addr - s1->plt->sh_addr - 12;
|
int x = s1->got->sh_addr - s1->plt->sh_addr - 12;
|
||||||
write32le(s1->plt->data + 16, x - 16);
|
write32le(s1->plt->data + 16, x - 4);
|
||||||
p += 20;
|
p += 20;
|
||||||
while (p < p_end) {
|
while (p < p_end) {
|
||||||
|
unsigned off = x + read32le(p + 4) + (s1->plt->data - p) + 4;
|
||||||
if (read32le(p) == 0x46c04778) /* PLT Thumb stub present */
|
if (read32le(p) == 0x46c04778) /* PLT Thumb stub present */
|
||||||
p += 4;
|
p += 4;
|
||||||
add32le(p + 12, x + s1->plt->data - p);
|
write32le(p, 0xe28fc200 | ((off >> 28) & 0xf)); // add ip, pc, #0xN0000000
|
||||||
|
write32le(p + 4, 0xe28cc600 | ((off >> 20) & 0xff)); // add ip, pc, #0xNN00000
|
||||||
|
write32le(p + 8, 0xe28cca00 | ((off >> 12) & 0xff)); // add ip, ip, #0xNN000
|
||||||
|
write32le(p + 12, 0xe5bcf000 | (off & 0xfff)); // ldr pc, [ip, #0xNNN]!
|
||||||
p += 16;
|
p += 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s1->plt->reloc) {
|
||||||
|
ElfW_Rel *rel;
|
||||||
|
p = s1->got->data;
|
||||||
|
for_each_elem(s1->plt->reloc, 0, rel, ElfW_Rel) {
|
||||||
|
write32le(p + rel->r_offset, s1->plt->sh_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
void relocate_init(Section *sr) {}
|
ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
||||||
|
|
||||||
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
|
||||||
{
|
{
|
||||||
ElfW(Sym) *sym;
|
ElfW(Sym) *sym;
|
||||||
int sym_index;
|
int sym_index, esym_index;
|
||||||
|
|
||||||
sym_index = ELFW(R_SYM)(rel->r_info);
|
sym_index = ELFW(R_SYM)(rel->r_info);
|
||||||
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||||
@ -182,17 +191,18 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
case R_ARM_PLT32:
|
case R_ARM_PLT32:
|
||||||
{
|
{
|
||||||
int x, is_thumb, is_call, h, blx_avail, is_bl, th_ko;
|
int x, is_thumb, is_call, h, blx_avail, is_bl, th_ko;
|
||||||
x = (*(int *) ptr) & 0xffffff;
|
unsigned code = read32le(ptr);
|
||||||
|
x = code & 0x00ffffff;
|
||||||
#ifdef DEBUG_RELOC
|
#ifdef DEBUG_RELOC
|
||||||
printf ("reloc %d: x=0x%x val=0x%x ", type, x, val);
|
printf ("reloc %d: x=0x%x val=0x%x ", type, x, val);
|
||||||
#endif
|
#endif
|
||||||
(*(int *)ptr) &= 0xff000000;
|
code &= 0xff000000;
|
||||||
if (x & 0x800000)
|
|
||||||
x -= 0x1000000;
|
|
||||||
x <<= 2;
|
x <<= 2;
|
||||||
blx_avail = (TCC_CPU_VERSION >= 5);
|
if (x & 0x2000000)
|
||||||
|
x -= 0x4000000;
|
||||||
|
blx_avail = (CONFIG_TCC_CPUVER >= 5);
|
||||||
is_thumb = val & 1;
|
is_thumb = val & 1;
|
||||||
is_bl = (*(unsigned *) ptr) >> 24 == 0xeb;
|
is_bl = code == 0xeb000000;
|
||||||
is_call = (type == R_ARM_CALL || (type == R_ARM_PC24 && is_bl));
|
is_call = (type == R_ARM_CALL || (type == R_ARM_PC24 && is_bl));
|
||||||
x += val - addr;
|
x += val - addr;
|
||||||
#ifdef DEBUG_RELOC
|
#ifdef DEBUG_RELOC
|
||||||
@ -202,15 +212,15 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
h = x & 2;
|
h = x & 2;
|
||||||
th_ko = (x & 3) && (!blx_avail || !is_call);
|
th_ko = (x & 3) && (!blx_avail || !is_call);
|
||||||
if (th_ko || x >= 0x2000000 || x < -0x2000000)
|
if (th_ko || x >= 0x2000000 || x < -0x2000000)
|
||||||
tcc_error("can't relocate value at %x,%d",addr, type);
|
tcc_error_noabort("can't relocate value at %x,%d",addr, type);
|
||||||
x >>= 2;
|
x >>= 2;
|
||||||
x &= 0xffffff;
|
x &= 0xffffff;
|
||||||
/* Only reached if blx is avail and it is a call */
|
/* Only reached if blx is avail and it is a call */
|
||||||
if (is_thumb) {
|
if (is_thumb) {
|
||||||
x |= h << 24;
|
x |= h << 24;
|
||||||
(*(int *)ptr) = 0xfa << 24; /* bl -> blx */
|
code = 0xfa000000; /* bl -> blx */
|
||||||
}
|
}
|
||||||
(*(int *) ptr) |= x;
|
write32le(ptr, code | x);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
/* Since these relocations only concern Thumb-2 and blx instruction was
|
/* Since these relocations only concern Thumb-2 and blx instruction was
|
||||||
@ -229,8 +239,8 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* Get initial offset */
|
/* Get initial offset */
|
||||||
hi = (*(uint16_t *)ptr);
|
hi = read16le(ptr);
|
||||||
lo = (*(uint16_t *)(ptr+2));
|
lo = read16le(ptr+2);
|
||||||
s = (hi >> 10) & 1;
|
s = (hi >> 10) & 1;
|
||||||
j1 = (lo >> 13) & 1;
|
j1 = (lo >> 13) & 1;
|
||||||
j2 = (lo >> 11) & 1;
|
j2 = (lo >> 11) & 1;
|
||||||
@ -254,24 +264,24 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
int index;
|
int index;
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
char *name, buf[1024];
|
char *name, buf[1024];
|
||||||
Section *text_section;
|
Section *text;
|
||||||
|
|
||||||
name = (char *) symtab_section->link->data + sym->st_name;
|
name = (char *) symtab_section->link->data + sym->st_name;
|
||||||
text_section = s1->sections[sym->st_shndx];
|
text = s1->sections[sym->st_shndx];
|
||||||
/* Modify reloc to target a thumb stub to switch to ARM */
|
/* Modify reloc to target a thumb stub to switch to ARM */
|
||||||
snprintf(buf, sizeof(buf), "%s_from_thumb", name);
|
snprintf(buf, sizeof(buf), "%s_from_thumb", name);
|
||||||
index = put_elf_sym(symtab_section,
|
index = put_elf_sym(symtab_section,
|
||||||
text_section->data_offset + 1,
|
text->data_offset + 1,
|
||||||
sym->st_size, sym->st_info, 0,
|
sym->st_size, sym->st_info, 0,
|
||||||
sym->st_shndx, buf);
|
sym->st_shndx, buf);
|
||||||
to_thumb = 1;
|
to_thumb = 1;
|
||||||
val = text_section->data_offset + 1;
|
val = text->data_offset + 1;
|
||||||
rel->r_info = ELFW(R_INFO)(index, type);
|
rel->r_info = ELFW(R_INFO)(index, type);
|
||||||
/* Create a thumb stub function to switch to ARM mode */
|
/* Create a thumb stub function to switch to ARM mode */
|
||||||
put_elf_reloc(symtab_section, text_section,
|
put_elf_reloc(symtab_section, text,
|
||||||
text_section->data_offset + 4, R_ARM_JUMP24,
|
text->data_offset + 4, R_ARM_JUMP24,
|
||||||
sym_index);
|
sym_index);
|
||||||
p = section_ptr_add(text_section, 8);
|
p = section_ptr_add(text, 8);
|
||||||
write32le(p, 0x4778); /* bx pc */
|
write32le(p, 0x4778); /* bx pc */
|
||||||
write32le(p+2, 0x46c0); /* nop */
|
write32le(p+2, 0x46c0); /* nop */
|
||||||
write32le(p+4, 0xeafffffe); /* b $sym */
|
write32le(p+4, 0xeafffffe); /* b $sym */
|
||||||
@ -291,7 +301,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
- instruction must be a call (bl) or a jump to PLT */
|
- instruction must be a call (bl) or a jump to PLT */
|
||||||
if (!to_thumb || x >= 0x1000000 || x < -0x1000000)
|
if (!to_thumb || x >= 0x1000000 || x < -0x1000000)
|
||||||
if (to_thumb || (val & 2) || (!is_call && !to_plt))
|
if (to_thumb || (val & 2) || (!is_call && !to_plt))
|
||||||
tcc_error("can't relocate value at %x,%d",addr, type);
|
tcc_error_noabort("can't relocate value at %x,%d",addr, type);
|
||||||
|
|
||||||
/* Compute and store final offset */
|
/* Compute and store final offset */
|
||||||
s = (x >> 24) & 1;
|
s = (x >> 24) & 1;
|
||||||
@ -301,11 +311,11 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
j2 = s ^ (i2 ^ 1);
|
j2 = s ^ (i2 ^ 1);
|
||||||
imm10 = (x >> 12) & 0x3ff;
|
imm10 = (x >> 12) & 0x3ff;
|
||||||
imm11 = (x >> 1) & 0x7ff;
|
imm11 = (x >> 1) & 0x7ff;
|
||||||
(*(uint16_t *)ptr) = (uint16_t) ((hi & 0xf800) |
|
write16le(ptr, (hi & 0xf800) |
|
||||||
(s << 10) | imm10);
|
(s << 10) | imm10);
|
||||||
(*(uint16_t *)(ptr+2)) = (uint16_t) ((lo & 0xc000) |
|
write16le(ptr+2, (lo & 0xc000) |
|
||||||
(j1 << 13) | blx_bit | (j2 << 11) |
|
(j1 << 13) | blx_bit | (j2 << 11) |
|
||||||
imm11);
|
imm11);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case R_ARM_MOVT_ABS:
|
case R_ARM_MOVT_ABS:
|
||||||
@ -318,9 +328,23 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
imm4 = (val >> 12) & 0xf;
|
imm4 = (val >> 12) & 0xf;
|
||||||
x = (imm4 << 16) | imm12;
|
x = (imm4 << 16) | imm12;
|
||||||
if (type == R_ARM_THM_MOVT_ABS)
|
if (type == R_ARM_THM_MOVT_ABS)
|
||||||
*(int *)ptr |= x;
|
write32le(ptr, read32le(ptr) | x);
|
||||||
else
|
else
|
||||||
*(int *)ptr += x;
|
add32le(ptr, x);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case R_ARM_MOVT_PREL:
|
||||||
|
case R_ARM_MOVW_PREL_NC:
|
||||||
|
{
|
||||||
|
int insn = read32le(ptr);
|
||||||
|
int addend = ((insn >> 4) & 0xf000) | (insn & 0xfff);
|
||||||
|
|
||||||
|
addend = (addend ^ 0x8000) - 0x8000;
|
||||||
|
val += addend - addr;
|
||||||
|
if (type == R_ARM_MOVT_PREL)
|
||||||
|
val >>= 16;
|
||||||
|
write32le(ptr, (insn & 0xfff0f000) |
|
||||||
|
((val & 0xf000) << 4) | (val & 0xfff));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case R_ARM_THM_MOVT_ABS:
|
case R_ARM_THM_MOVT_ABS:
|
||||||
@ -335,48 +359,68 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
imm4 = (val >> 12) & 0xf;
|
imm4 = (val >> 12) & 0xf;
|
||||||
x = (imm3 << 28) | (imm8 << 16) | (i << 10) | imm4;
|
x = (imm3 << 28) | (imm8 << 16) | (i << 10) | imm4;
|
||||||
if (type == R_ARM_THM_MOVT_ABS)
|
if (type == R_ARM_THM_MOVT_ABS)
|
||||||
*(int *)ptr |= x;
|
write32le(ptr, read32le(ptr) | x);
|
||||||
else
|
else
|
||||||
*(int *)ptr += x;
|
add32le(ptr, x);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case R_ARM_PREL31:
|
case R_ARM_PREL31:
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
x = (*(int *)ptr) & 0x7fffffff;
|
x = read32le(ptr) & 0x7fffffff;
|
||||||
(*(int *)ptr) &= 0x80000000;
|
write32le(ptr, read32le(ptr) & 0x80000000);
|
||||||
x = (x * 2) / 2;
|
x = (x * 2) / 2;
|
||||||
x += val - addr;
|
x += val - addr;
|
||||||
if((x^(x>>1))&0x40000000)
|
if((x^(x>>1))&0x40000000)
|
||||||
tcc_error("can't relocate value at %x,%d",addr, type);
|
tcc_error_noabort("can't relocate value at %x,%d",addr, type);
|
||||||
(*(int *)ptr) |= x & 0x7fffffff;
|
write32le(ptr, read32le(ptr) | (x & 0x7fffffff));
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
case R_ARM_ABS32:
|
case R_ARM_ABS32:
|
||||||
*(int *)ptr += val;
|
case R_ARM_TARGET1:
|
||||||
|
if (s1->output_type & TCC_OUTPUT_DYN) {
|
||||||
|
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
|
||||||
|
qrel->r_offset = rel->r_offset;
|
||||||
|
if (esym_index) {
|
||||||
|
qrel->r_info = ELFW(R_INFO)(esym_index, R_ARM_ABS32);
|
||||||
|
qrel++;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
qrel->r_info = ELFW(R_INFO)(0, R_ARM_RELATIVE);
|
||||||
|
qrel++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
add32le(ptr, val);
|
||||||
return;
|
return;
|
||||||
case R_ARM_REL32:
|
case R_ARM_REL32:
|
||||||
*(int *)ptr += val - addr;
|
add32le(ptr, val - addr);
|
||||||
return;
|
return;
|
||||||
case R_ARM_GOTPC:
|
case R_ARM_GOTPC:
|
||||||
*(int *)ptr += s1->got->sh_addr - addr;
|
add32le(ptr, s1->got->sh_addr - addr);
|
||||||
return;
|
return;
|
||||||
case R_ARM_GOTOFF:
|
case R_ARM_GOTOFF:
|
||||||
*(int *)ptr += val - s1->got->sh_addr;
|
add32le(ptr, val - s1->got->sh_addr);
|
||||||
return;
|
return;
|
||||||
case R_ARM_GOT32:
|
case R_ARM_GOT32:
|
||||||
/* we load the got offset */
|
/* we load the got offset */
|
||||||
*(int *)ptr += s1->sym_attrs[sym_index].got_offset;
|
add32le(ptr, get_sym_attr(s1, sym_index, 0)->got_offset);
|
||||||
|
return;
|
||||||
|
case R_ARM_GOT_PREL:
|
||||||
|
/* we load the pc relative got offset */
|
||||||
|
add32le(ptr, s1->got->sh_addr +
|
||||||
|
get_sym_attr(s1, sym_index, 0)->got_offset -
|
||||||
|
addr);
|
||||||
return;
|
return;
|
||||||
case R_ARM_COPY:
|
case R_ARM_COPY:
|
||||||
return;
|
return;
|
||||||
case R_ARM_V4BX:
|
case R_ARM_V4BX:
|
||||||
/* trade Thumb support for ARMv4 support */
|
/* trade Thumb support for ARMv4 support */
|
||||||
if ((0x0ffffff0 & *(int*)ptr) == 0x012FFF10)
|
if ((0x0ffffff0 & read32le(ptr)) == 0x012FFF10)
|
||||||
*(int*)ptr ^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
|
write32le(ptr, read32le(ptr) ^ 0xE12FFF10 ^ 0xE1A0F000); /* BX Rm -> MOV PC, Rm */
|
||||||
return;
|
return;
|
||||||
case R_ARM_GLOB_DAT:
|
case R_ARM_GLOB_DAT:
|
||||||
case R_ARM_JUMP_SLOT:
|
case R_ARM_JUMP_SLOT:
|
||||||
*(addr_t *)ptr = val;
|
write32le(ptr, val);
|
||||||
return;
|
return;
|
||||||
case R_ARM_NONE:
|
case R_ARM_NONE:
|
||||||
/* Nothing to do. Normally used to indicate a dependency
|
/* Nothing to do. Normally used to indicate a dependency
|
||||||
@ -388,8 +432,38 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
#endif
|
#endif
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
return;
|
return;
|
||||||
|
case R_ARM_TLS_LE32:
|
||||||
|
{
|
||||||
|
ElfW(Sym) *sym;
|
||||||
|
Section *sec;
|
||||||
|
int32_t x;
|
||||||
|
addr_t tls_start = 0, tls_end = 0, tls_align = 1;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||||
|
sec = s1->sections[sym->st_shndx];
|
||||||
|
|
||||||
|
for (i = 1; i < s1->nb_sections; i++) {
|
||||||
|
Section *s = s1->sections[i];
|
||||||
|
if (s->sh_flags & SHF_TLS && s->sh_size) {
|
||||||
|
if (!tls_start || s->sh_addr < tls_start)
|
||||||
|
tls_start = s->sh_addr;
|
||||||
|
if (s->sh_addr + s->sh_size > tls_end)
|
||||||
|
tls_end = s->sh_addr + s->sh_size;
|
||||||
|
if (s->sh_addralign > tls_align)
|
||||||
|
tls_align = s->sh_addralign;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tls_end > tls_start) {
|
||||||
|
x = val - tls_start + 8;
|
||||||
|
} else {
|
||||||
|
x = val - sec->sh_addr - sec->data_offset + 8;
|
||||||
|
}
|
||||||
|
add32le(ptr, x);
|
||||||
|
}
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
|
fprintf(stderr,"FIXME: handle reloc type %d at %x [%p] to %x\n",
|
||||||
type, (unsigned)addr, ptr, (unsigned)val);
|
type, (unsigned)addr, ptr, (unsigned)val);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
406
arm-tok.h
Normal file
406
arm-tok.h
Normal file
@ -0,0 +1,406 @@
|
|||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
/* WARNING: relative order of tokens is important. */
|
||||||
|
|
||||||
|
/* register */
|
||||||
|
|
||||||
|
DEF_ASM(r0)
|
||||||
|
DEF_ASM(r1)
|
||||||
|
DEF_ASM(r2)
|
||||||
|
DEF_ASM(r3)
|
||||||
|
DEF_ASM(r4)
|
||||||
|
DEF_ASM(r5)
|
||||||
|
DEF_ASM(r6)
|
||||||
|
DEF_ASM(r7)
|
||||||
|
DEF_ASM(r8)
|
||||||
|
DEF_ASM(r9)
|
||||||
|
DEF_ASM(r10)
|
||||||
|
DEF_ASM(r11) /* fp */
|
||||||
|
DEF_ASM(r12) /* ip[c] */
|
||||||
|
DEF_ASM(r13) /* sp */
|
||||||
|
DEF_ASM(r14) /* lr */
|
||||||
|
DEF_ASM(r15) /* pc */
|
||||||
|
|
||||||
|
/* synonym register names */
|
||||||
|
|
||||||
|
DEF_ASM(a1) /* argument/result/scratch register 1: alias for r0 */
|
||||||
|
DEF_ASM(a2) /* argument/result/scratch register 2: alias for r1 */
|
||||||
|
DEF_ASM(a3) /* argument/result/scratch register 3: alias for r2 */
|
||||||
|
DEF_ASM(a4) /* argument/result/scratch register 4: alias for r3 */
|
||||||
|
|
||||||
|
DEF_ASM(v1) /* variable register 1: alias for r4 */
|
||||||
|
DEF_ASM(v2) /* variable register 2: alias for r5 */
|
||||||
|
DEF_ASM(v3) /* variable register 3: alias for r6 */
|
||||||
|
DEF_ASM(v4) /* variable register 4: alias for r7 */
|
||||||
|
DEF_ASM(v5) /* ARM state variable register 5: alias for r8 */
|
||||||
|
DEF_ASM(v6) /* ARM state variable register 6: alias for r9 */
|
||||||
|
DEF_ASM(v7) /* ARM state variable register 7: alias for r10 */
|
||||||
|
DEF_ASM(v8) /* ARM state variable register 8: alias for r11 */
|
||||||
|
|
||||||
|
/* special register names */
|
||||||
|
|
||||||
|
DEF_ASM(sb) /* alias for r9 */
|
||||||
|
DEF_ASM(sl) /* alias for r10 */
|
||||||
|
DEF_ASM(fp) /* alias for r11 */
|
||||||
|
DEF_ASM(ip) /* alias for r12 */
|
||||||
|
DEF_ASM(sp) /* alias for r13 */
|
||||||
|
DEF_ASM(lr) /* alias for r14 */
|
||||||
|
DEF_ASM(pc) /* alias for r15 */
|
||||||
|
|
||||||
|
/* coprocessors */
|
||||||
|
|
||||||
|
DEF_ASM(p0)
|
||||||
|
DEF_ASM(p1)
|
||||||
|
DEF_ASM(p2)
|
||||||
|
DEF_ASM(p3)
|
||||||
|
DEF_ASM(p4)
|
||||||
|
DEF_ASM(p5)
|
||||||
|
DEF_ASM(p6)
|
||||||
|
DEF_ASM(p7)
|
||||||
|
DEF_ASM(p8)
|
||||||
|
DEF_ASM(p9)
|
||||||
|
DEF_ASM(p10)
|
||||||
|
DEF_ASM(p11)
|
||||||
|
DEF_ASM(p12)
|
||||||
|
DEF_ASM(p13)
|
||||||
|
DEF_ASM(p14)
|
||||||
|
DEF_ASM(p15)
|
||||||
|
|
||||||
|
/* coprocessor registers */
|
||||||
|
|
||||||
|
DEF_ASM(c0)
|
||||||
|
DEF_ASM(c1)
|
||||||
|
DEF_ASM(c2)
|
||||||
|
DEF_ASM(c3)
|
||||||
|
DEF_ASM(c4)
|
||||||
|
DEF_ASM(c5)
|
||||||
|
DEF_ASM(c6)
|
||||||
|
DEF_ASM(c7)
|
||||||
|
DEF_ASM(c8)
|
||||||
|
DEF_ASM(c9)
|
||||||
|
DEF_ASM(c10)
|
||||||
|
DEF_ASM(c11)
|
||||||
|
DEF_ASM(c12)
|
||||||
|
DEF_ASM(c13)
|
||||||
|
DEF_ASM(c14)
|
||||||
|
DEF_ASM(c15)
|
||||||
|
|
||||||
|
/* single-precision VFP registers */
|
||||||
|
|
||||||
|
DEF_ASM(s0)
|
||||||
|
DEF_ASM(s1)
|
||||||
|
DEF_ASM(s2)
|
||||||
|
DEF_ASM(s3)
|
||||||
|
DEF_ASM(s4)
|
||||||
|
DEF_ASM(s5)
|
||||||
|
DEF_ASM(s6)
|
||||||
|
DEF_ASM(s7)
|
||||||
|
DEF_ASM(s8)
|
||||||
|
DEF_ASM(s9)
|
||||||
|
DEF_ASM(s10)
|
||||||
|
DEF_ASM(s11)
|
||||||
|
DEF_ASM(s12)
|
||||||
|
DEF_ASM(s13)
|
||||||
|
DEF_ASM(s14)
|
||||||
|
DEF_ASM(s15)
|
||||||
|
DEF_ASM(s16)
|
||||||
|
DEF_ASM(s17)
|
||||||
|
DEF_ASM(s18)
|
||||||
|
DEF_ASM(s19)
|
||||||
|
DEF_ASM(s20)
|
||||||
|
DEF_ASM(s21)
|
||||||
|
DEF_ASM(s22)
|
||||||
|
DEF_ASM(s23)
|
||||||
|
DEF_ASM(s24)
|
||||||
|
DEF_ASM(s25)
|
||||||
|
DEF_ASM(s26)
|
||||||
|
DEF_ASM(s27)
|
||||||
|
DEF_ASM(s28)
|
||||||
|
DEF_ASM(s29)
|
||||||
|
DEF_ASM(s30)
|
||||||
|
DEF_ASM(s31)
|
||||||
|
|
||||||
|
/* double-precision VFP registers */
|
||||||
|
|
||||||
|
DEF_ASM(d0)
|
||||||
|
DEF_ASM(d1)
|
||||||
|
DEF_ASM(d2)
|
||||||
|
DEF_ASM(d3)
|
||||||
|
DEF_ASM(d4)
|
||||||
|
DEF_ASM(d5)
|
||||||
|
DEF_ASM(d6)
|
||||||
|
DEF_ASM(d7)
|
||||||
|
DEF_ASM(d8)
|
||||||
|
DEF_ASM(d9)
|
||||||
|
DEF_ASM(d10)
|
||||||
|
DEF_ASM(d11)
|
||||||
|
DEF_ASM(d12)
|
||||||
|
DEF_ASM(d13)
|
||||||
|
DEF_ASM(d14)
|
||||||
|
DEF_ASM(d15)
|
||||||
|
|
||||||
|
/* VFP status registers */
|
||||||
|
|
||||||
|
DEF_ASM(fpsid)
|
||||||
|
DEF_ASM(fpscr)
|
||||||
|
DEF_ASM(fpexc)
|
||||||
|
|
||||||
|
/* VFP magical ARM register */
|
||||||
|
|
||||||
|
DEF_ASM(apsr_nzcv)
|
||||||
|
|
||||||
|
/* data processing directives */
|
||||||
|
|
||||||
|
DEF_ASM(asl)
|
||||||
|
|
||||||
|
/* instructions that have no condition code */
|
||||||
|
|
||||||
|
DEF_ASM(cdp2)
|
||||||
|
DEF_ASM(ldc2)
|
||||||
|
DEF_ASM(ldc2l)
|
||||||
|
DEF_ASM(stc2)
|
||||||
|
DEF_ASM(stc2l)
|
||||||
|
|
||||||
|
#define ARM_INSTRUCTION_GROUP(tok) ((((tok) - TOK_ASM_nopeq) & 0xFFFFFFF0) + TOK_ASM_nopeq)
|
||||||
|
|
||||||
|
/* Note: condition code is 4 bits */
|
||||||
|
#define DEF_ASM_CONDED(x) \
|
||||||
|
DEF(TOK_ASM_ ## x ## eq, #x "eq") \
|
||||||
|
DEF(TOK_ASM_ ## x ## ne, #x "ne") \
|
||||||
|
DEF(TOK_ASM_ ## x ## cs, #x "cs") \
|
||||||
|
DEF(TOK_ASM_ ## x ## cc, #x "cc") \
|
||||||
|
DEF(TOK_ASM_ ## x ## mi, #x "mi") \
|
||||||
|
DEF(TOK_ASM_ ## x ## pl, #x "pl") \
|
||||||
|
DEF(TOK_ASM_ ## x ## vs, #x "vs") \
|
||||||
|
DEF(TOK_ASM_ ## x ## vc, #x "vc") \
|
||||||
|
DEF(TOK_ASM_ ## x ## hi, #x "hi") \
|
||||||
|
DEF(TOK_ASM_ ## x ## ls, #x "ls") \
|
||||||
|
DEF(TOK_ASM_ ## x ## ge, #x "ge") \
|
||||||
|
DEF(TOK_ASM_ ## x ## lt, #x "lt") \
|
||||||
|
DEF(TOK_ASM_ ## x ## gt, #x "gt") \
|
||||||
|
DEF(TOK_ASM_ ## x ## le, #x "le") \
|
||||||
|
DEF(TOK_ASM_ ## x, #x) \
|
||||||
|
DEF(TOK_ASM_ ## x ## rsvd, #x "rsvd")
|
||||||
|
|
||||||
|
/* Note: condition code is 4 bits */
|
||||||
|
#define DEF_ASM_CONDED_WITH_SUFFIX(x, y) \
|
||||||
|
DEF(TOK_ASM_ ## x ## eq ## _ ## y, #x "eq." #y) \
|
||||||
|
DEF(TOK_ASM_ ## x ## ne ## _ ## y, #x "ne." #y) \
|
||||||
|
DEF(TOK_ASM_ ## x ## cs ## _ ## y, #x "cs." #y) \
|
||||||
|
DEF(TOK_ASM_ ## x ## cc ## _ ## y, #x "cc." #y) \
|
||||||
|
DEF(TOK_ASM_ ## x ## mi ## _ ## y, #x "mi." #y) \
|
||||||
|
DEF(TOK_ASM_ ## x ## pl ## _ ## y, #x "pl." #y) \
|
||||||
|
DEF(TOK_ASM_ ## x ## vs ## _ ## y, #x "vs." #y) \
|
||||||
|
DEF(TOK_ASM_ ## x ## vc ## _ ## y, #x "vc." #y) \
|
||||||
|
DEF(TOK_ASM_ ## x ## hi ## _ ## y, #x "hi." #y) \
|
||||||
|
DEF(TOK_ASM_ ## x ## ls ## _ ## y, #x "ls." #y) \
|
||||||
|
DEF(TOK_ASM_ ## x ## ge ## _ ## y, #x "ge." #y) \
|
||||||
|
DEF(TOK_ASM_ ## x ## lt ## _ ## y, #x "lt." #y) \
|
||||||
|
DEF(TOK_ASM_ ## x ## gt ## _ ## y, #x "gt." #y) \
|
||||||
|
DEF(TOK_ASM_ ## x ## le ## _ ## y, #x "le." #y) \
|
||||||
|
DEF(TOK_ASM_ ## x ## _ ## y, #x "." #y) \
|
||||||
|
DEF(TOK_ASM_ ## x ## rsvd ## _ ## y, #x "rsvd." #y)
|
||||||
|
|
||||||
|
#define DEF_ASM_CONDED_VFP_F32_F64(x) \
|
||||||
|
DEF_ASM_CONDED_WITH_SUFFIX(x, f32) \
|
||||||
|
DEF_ASM_CONDED_WITH_SUFFIX(x, f64)
|
||||||
|
|
||||||
|
#define DEF_ASM_CONDED_WITH_TWO_SUFFIXES(x, y, z) \
|
||||||
|
DEF(TOK_ASM_ ## x ## eq ## _ ## y ## _ ## z, #x "eq." #y "." #z) \
|
||||||
|
DEF(TOK_ASM_ ## x ## ne ## _ ## y ## _ ## z, #x "ne." #y "." #z) \
|
||||||
|
DEF(TOK_ASM_ ## x ## cs ## _ ## y ## _ ## z, #x "cs." #y "." #z) \
|
||||||
|
DEF(TOK_ASM_ ## x ## cc ## _ ## y ## _ ## z, #x "cc." #y "." #z) \
|
||||||
|
DEF(TOK_ASM_ ## x ## mi ## _ ## y ## _ ## z, #x "mi." #y "." #z) \
|
||||||
|
DEF(TOK_ASM_ ## x ## pl ## _ ## y ## _ ## z, #x "pl." #y "." #z) \
|
||||||
|
DEF(TOK_ASM_ ## x ## vs ## _ ## y ## _ ## z, #x "vs." #y "." #z) \
|
||||||
|
DEF(TOK_ASM_ ## x ## vc ## _ ## y ## _ ## z, #x "vc." #y "." #z) \
|
||||||
|
DEF(TOK_ASM_ ## x ## hi ## _ ## y ## _ ## z, #x "hi." #y "." #z) \
|
||||||
|
DEF(TOK_ASM_ ## x ## ls ## _ ## y ## _ ## z, #x "ls." #y "." #z) \
|
||||||
|
DEF(TOK_ASM_ ## x ## ge ## _ ## y ## _ ## z, #x "ge." #y "." #z) \
|
||||||
|
DEF(TOK_ASM_ ## x ## lt ## _ ## y ## _ ## z, #x "lt." #y "." #z) \
|
||||||
|
DEF(TOK_ASM_ ## x ## gt ## _ ## y ## _ ## z, #x "gt." #y "." #z) \
|
||||||
|
DEF(TOK_ASM_ ## x ## le ## _ ## y ## _ ## z, #x "le." #y "." #z) \
|
||||||
|
DEF(TOK_ASM_ ## x ## _ ## y ## _ ## z, #x "." #y "." #z) \
|
||||||
|
DEF(TOK_ASM_ ## x ## rsvd ## _ ## y ## _ ## z, #x "rsvd." #y "." #z)
|
||||||
|
|
||||||
|
/* Note: add new tokens after nop (MUST always use DEF_ASM_CONDED) */
|
||||||
|
|
||||||
|
DEF_ASM_CONDED(nop)
|
||||||
|
DEF_ASM_CONDED(wfe)
|
||||||
|
DEF_ASM_CONDED(wfi)
|
||||||
|
DEF_ASM_CONDED(swi)
|
||||||
|
DEF_ASM_CONDED(svc)
|
||||||
|
|
||||||
|
/* misc */
|
||||||
|
DEF_ASM_CONDED(clz)
|
||||||
|
|
||||||
|
/* size conversion */
|
||||||
|
|
||||||
|
DEF_ASM_CONDED(sxtb)
|
||||||
|
DEF_ASM_CONDED(sxth)
|
||||||
|
DEF_ASM_CONDED(uxtb)
|
||||||
|
DEF_ASM_CONDED(uxth)
|
||||||
|
DEF_ASM_CONDED(movt)
|
||||||
|
DEF_ASM_CONDED(movw)
|
||||||
|
|
||||||
|
/* multiplication */
|
||||||
|
|
||||||
|
DEF_ASM_CONDED(mul)
|
||||||
|
DEF_ASM_CONDED(muls)
|
||||||
|
DEF_ASM_CONDED(mla)
|
||||||
|
DEF_ASM_CONDED(mlas)
|
||||||
|
DEF_ASM_CONDED(smull)
|
||||||
|
DEF_ASM_CONDED(smulls)
|
||||||
|
DEF_ASM_CONDED(umull)
|
||||||
|
DEF_ASM_CONDED(umulls)
|
||||||
|
DEF_ASM_CONDED(smlal)
|
||||||
|
DEF_ASM_CONDED(smlals)
|
||||||
|
DEF_ASM_CONDED(umlal)
|
||||||
|
DEF_ASM_CONDED(umlals)
|
||||||
|
DEF_ASM_CONDED(mls)
|
||||||
|
DEF_ASM_CONDED(udiv)
|
||||||
|
DEF_ASM_CONDED(sdiv)
|
||||||
|
|
||||||
|
/* load/store */
|
||||||
|
|
||||||
|
DEF_ASM_CONDED(ldr)
|
||||||
|
DEF_ASM_CONDED(ldrb)
|
||||||
|
DEF_ASM_CONDED(str)
|
||||||
|
DEF_ASM_CONDED(strb)
|
||||||
|
DEF_ASM_CONDED(ldrex)
|
||||||
|
DEF_ASM_CONDED(ldrexb)
|
||||||
|
DEF_ASM_CONDED(ldrexh)
|
||||||
|
DEF_ASM_CONDED(strex)
|
||||||
|
DEF_ASM_CONDED(strexb)
|
||||||
|
DEF_ASM_CONDED(strexh)
|
||||||
|
DEF_ASM_CONDED(ldrh)
|
||||||
|
DEF_ASM_CONDED(ldrsh)
|
||||||
|
DEF_ASM_CONDED(ldrsb)
|
||||||
|
DEF_ASM_CONDED(strh)
|
||||||
|
|
||||||
|
DEF_ASM_CONDED(stmda)
|
||||||
|
DEF_ASM_CONDED(ldmda)
|
||||||
|
DEF_ASM_CONDED(stm)
|
||||||
|
DEF_ASM_CONDED(ldm)
|
||||||
|
DEF_ASM_CONDED(stmia)
|
||||||
|
DEF_ASM_CONDED(ldmia)
|
||||||
|
DEF_ASM_CONDED(stmdb)
|
||||||
|
DEF_ASM_CONDED(ldmdb)
|
||||||
|
DEF_ASM_CONDED(stmib)
|
||||||
|
DEF_ASM_CONDED(ldmib)
|
||||||
|
|
||||||
|
DEF_ASM_CONDED(ldc)
|
||||||
|
DEF_ASM_CONDED(ldcl)
|
||||||
|
DEF_ASM_CONDED(stc)
|
||||||
|
DEF_ASM_CONDED(stcl)
|
||||||
|
|
||||||
|
/* instruction macros */
|
||||||
|
|
||||||
|
DEF_ASM_CONDED(push)
|
||||||
|
DEF_ASM_CONDED(pop)
|
||||||
|
|
||||||
|
/* branches */
|
||||||
|
|
||||||
|
DEF_ASM_CONDED(b)
|
||||||
|
DEF_ASM_CONDED(bl)
|
||||||
|
DEF_ASM_CONDED(bx)
|
||||||
|
DEF_ASM_CONDED(blx)
|
||||||
|
|
||||||
|
/* data processing instructions; order is important */
|
||||||
|
|
||||||
|
DEF_ASM_CONDED(and)
|
||||||
|
DEF_ASM_CONDED(ands)
|
||||||
|
DEF_ASM_CONDED(eor)
|
||||||
|
DEF_ASM_CONDED(eors)
|
||||||
|
DEF_ASM_CONDED(sub)
|
||||||
|
DEF_ASM_CONDED(subs)
|
||||||
|
DEF_ASM_CONDED(rsb)
|
||||||
|
DEF_ASM_CONDED(rsbs)
|
||||||
|
DEF_ASM_CONDED(add)
|
||||||
|
DEF_ASM_CONDED(adds)
|
||||||
|
DEF_ASM_CONDED(adc)
|
||||||
|
DEF_ASM_CONDED(adcs)
|
||||||
|
DEF_ASM_CONDED(sbc)
|
||||||
|
DEF_ASM_CONDED(sbcs)
|
||||||
|
DEF_ASM_CONDED(rsc)
|
||||||
|
DEF_ASM_CONDED(rscs)
|
||||||
|
DEF_ASM_CONDED(tst)
|
||||||
|
DEF_ASM_CONDED(tsts) // necessary here--but not useful to the user
|
||||||
|
DEF_ASM_CONDED(teq)
|
||||||
|
DEF_ASM_CONDED(teqs) // necessary here--but not useful to the user
|
||||||
|
DEF_ASM_CONDED(cmp)
|
||||||
|
DEF_ASM_CONDED(cmps) // necessary here--but not useful to the user
|
||||||
|
DEF_ASM_CONDED(cmn)
|
||||||
|
DEF_ASM_CONDED(cmns) // necessary here--but not useful to the user
|
||||||
|
DEF_ASM_CONDED(orr)
|
||||||
|
DEF_ASM_CONDED(orrs)
|
||||||
|
DEF_ASM_CONDED(mov)
|
||||||
|
DEF_ASM_CONDED(movs)
|
||||||
|
DEF_ASM_CONDED(bic)
|
||||||
|
DEF_ASM_CONDED(bics)
|
||||||
|
DEF_ASM_CONDED(mvn)
|
||||||
|
DEF_ASM_CONDED(mvns)
|
||||||
|
|
||||||
|
DEF_ASM_CONDED(lsl)
|
||||||
|
DEF_ASM_CONDED(lsls)
|
||||||
|
DEF_ASM_CONDED(lsr)
|
||||||
|
DEF_ASM_CONDED(lsrs)
|
||||||
|
DEF_ASM_CONDED(asr)
|
||||||
|
DEF_ASM_CONDED(asrs)
|
||||||
|
DEF_ASM_CONDED(ror)
|
||||||
|
DEF_ASM_CONDED(rors)
|
||||||
|
DEF_ASM_CONDED(rrx)
|
||||||
|
DEF_ASM_CONDED(rrxs)
|
||||||
|
|
||||||
|
DEF_ASM_CONDED(cdp)
|
||||||
|
DEF_ASM_CONDED(mcr)
|
||||||
|
DEF_ASM_CONDED(mrc)
|
||||||
|
|
||||||
|
// Floating point high-level instructions
|
||||||
|
|
||||||
|
DEF_ASM_CONDED(vldr)
|
||||||
|
DEF_ASM_CONDED(vstr)
|
||||||
|
|
||||||
|
DEF_ASM_CONDED_VFP_F32_F64(vmla)
|
||||||
|
DEF_ASM_CONDED_VFP_F32_F64(vmls)
|
||||||
|
DEF_ASM_CONDED_VFP_F32_F64(vnmls)
|
||||||
|
DEF_ASM_CONDED_VFP_F32_F64(vnmla)
|
||||||
|
DEF_ASM_CONDED_VFP_F32_F64(vmul)
|
||||||
|
DEF_ASM_CONDED_VFP_F32_F64(vnmul)
|
||||||
|
DEF_ASM_CONDED_VFP_F32_F64(vadd)
|
||||||
|
DEF_ASM_CONDED_VFP_F32_F64(vsub)
|
||||||
|
DEF_ASM_CONDED_VFP_F32_F64(vdiv)
|
||||||
|
DEF_ASM_CONDED_VFP_F32_F64(vneg)
|
||||||
|
DEF_ASM_CONDED_VFP_F32_F64(vabs)
|
||||||
|
DEF_ASM_CONDED_VFP_F32_F64(vsqrt)
|
||||||
|
DEF_ASM_CONDED_VFP_F32_F64(vcmp)
|
||||||
|
DEF_ASM_CONDED_VFP_F32_F64(vcmpe)
|
||||||
|
DEF_ASM_CONDED_VFP_F32_F64(vmov)
|
||||||
|
|
||||||
|
DEF_ASM_CONDED_WITH_TWO_SUFFIXES(vcvtr, s32, f64)
|
||||||
|
DEF_ASM_CONDED_WITH_TWO_SUFFIXES(vcvtr, s32, f32)
|
||||||
|
DEF_ASM_CONDED_WITH_TWO_SUFFIXES(vcvtr, u32, f64)
|
||||||
|
DEF_ASM_CONDED_WITH_TWO_SUFFIXES(vcvtr, u32, f32)
|
||||||
|
|
||||||
|
DEF_ASM_CONDED_WITH_TWO_SUFFIXES(vcvt, s32, f64)
|
||||||
|
DEF_ASM_CONDED_WITH_TWO_SUFFIXES(vcvt, s32, f32)
|
||||||
|
DEF_ASM_CONDED_WITH_TWO_SUFFIXES(vcvt, u32, f64)
|
||||||
|
DEF_ASM_CONDED_WITH_TWO_SUFFIXES(vcvt, u32, f32)
|
||||||
|
|
||||||
|
DEF_ASM_CONDED_WITH_TWO_SUFFIXES(vcvt, f64, s32)
|
||||||
|
DEF_ASM_CONDED_WITH_TWO_SUFFIXES(vcvt, f32, s32)
|
||||||
|
DEF_ASM_CONDED_WITH_TWO_SUFFIXES(vcvt, f64, u32)
|
||||||
|
DEF_ASM_CONDED_WITH_TWO_SUFFIXES(vcvt, f32, u32)
|
||||||
|
|
||||||
|
DEF_ASM_CONDED_WITH_TWO_SUFFIXES(vcvt, f64, f32)
|
||||||
|
DEF_ASM_CONDED_WITH_TWO_SUFFIXES(vcvt, f32, f64)
|
||||||
|
|
||||||
|
DEF_ASM_CONDED(vpush)
|
||||||
|
DEF_ASM_CONDED(vpop)
|
||||||
|
DEF_ASM_CONDED(vldm)
|
||||||
|
DEF_ASM_CONDED(vldmia)
|
||||||
|
DEF_ASM_CONDED(vldmdb)
|
||||||
|
DEF_ASM_CONDED(vstm)
|
||||||
|
DEF_ASM_CONDED(vstmia)
|
||||||
|
DEF_ASM_CONDED(vstmdb)
|
||||||
|
DEF_ASM_CONDED(vmsr)
|
||||||
|
DEF_ASM_CONDED(vmrs)
|
||||||
2276
arm64-asm.c
Normal file
2276
arm64-asm.c
Normal file
File diff suppressed because it is too large
Load Diff
1026
arm64-gen.c
1026
arm64-gen.c
File diff suppressed because it is too large
Load Diff
228
arm64-link.c
228
arm64-link.c
@ -12,7 +12,7 @@
|
|||||||
#define R_NUM R_AARCH64_NUM
|
#define R_NUM R_AARCH64_NUM
|
||||||
|
|
||||||
#define ELF_START_ADDR 0x00400000
|
#define ELF_START_ADDR 0x00400000
|
||||||
#define ELF_PAGE_SIZE 0x1000
|
#define ELF_PAGE_SIZE 0x10000
|
||||||
|
|
||||||
#define PCRELATIVE_DLLPLT 1
|
#define PCRELATIVE_DLLPLT 1
|
||||||
#define RELOCATE_DLLPLT 1
|
#define RELOCATE_DLLPLT 1
|
||||||
@ -21,9 +21,10 @@
|
|||||||
|
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
|
|
||||||
|
#ifdef NEED_RELOC_TYPE
|
||||||
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
|
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
|
||||||
relocations, returns -1. */
|
relocations, returns -1. */
|
||||||
int code_reloc (int reloc_type)
|
ST_FUNC int code_reloc (int reloc_type)
|
||||||
{
|
{
|
||||||
switch (reloc_type) {
|
switch (reloc_type) {
|
||||||
case R_AARCH64_ABS32:
|
case R_AARCH64_ABS32:
|
||||||
@ -37,6 +38,13 @@ int code_reloc (int reloc_type)
|
|||||||
case R_AARCH64_ADD_ABS_LO12_NC:
|
case R_AARCH64_ADD_ABS_LO12_NC:
|
||||||
case R_AARCH64_ADR_GOT_PAGE:
|
case R_AARCH64_ADR_GOT_PAGE:
|
||||||
case R_AARCH64_LD64_GOT_LO12_NC:
|
case R_AARCH64_LD64_GOT_LO12_NC:
|
||||||
|
case R_AARCH64_LDST128_ABS_LO12_NC:
|
||||||
|
case R_AARCH64_LDST64_ABS_LO12_NC:
|
||||||
|
case R_AARCH64_LDST32_ABS_LO12_NC:
|
||||||
|
case R_AARCH64_LDST16_ABS_LO12_NC:
|
||||||
|
case R_AARCH64_LDST8_ABS_LO12_NC:
|
||||||
|
case R_AARCH64_TLSLE_ADD_TPREL_HI12:
|
||||||
|
case R_AARCH64_TLSLE_ADD_TPREL_LO12:
|
||||||
case R_AARCH64_GLOB_DAT:
|
case R_AARCH64_GLOB_DAT:
|
||||||
case R_AARCH64_COPY:
|
case R_AARCH64_COPY:
|
||||||
return 0;
|
return 0;
|
||||||
@ -44,17 +52,17 @@ int code_reloc (int reloc_type)
|
|||||||
case R_AARCH64_JUMP26:
|
case R_AARCH64_JUMP26:
|
||||||
case R_AARCH64_CALL26:
|
case R_AARCH64_CALL26:
|
||||||
case R_AARCH64_JUMP_SLOT:
|
case R_AARCH64_JUMP_SLOT:
|
||||||
|
case R_AARCH64_CONDBR19:
|
||||||
|
case R_AARCH64_TSTBR14:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
tcc_error ("Unknown relocation type: %d", reloc_type);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns an enumerator to describe whether and when the relocation needs a
|
/* Returns an enumerator to describe whether and when the relocation needs a
|
||||||
GOT and/or PLT entry to be created. See tcc.h for a description of the
|
GOT and/or PLT entry to be created. See tcc.h for a description of the
|
||||||
different values. */
|
different values. */
|
||||||
int gotplt_entry_type (int reloc_type)
|
ST_FUNC int gotplt_entry_type (int reloc_type)
|
||||||
{
|
{
|
||||||
switch (reloc_type) {
|
switch (reloc_type) {
|
||||||
case R_AARCH64_PREL32:
|
case R_AARCH64_PREL32:
|
||||||
@ -64,9 +72,18 @@ int gotplt_entry_type (int reloc_type)
|
|||||||
case R_AARCH64_MOVW_UABS_G3:
|
case R_AARCH64_MOVW_UABS_G3:
|
||||||
case R_AARCH64_ADR_PREL_PG_HI21:
|
case R_AARCH64_ADR_PREL_PG_HI21:
|
||||||
case R_AARCH64_ADD_ABS_LO12_NC:
|
case R_AARCH64_ADD_ABS_LO12_NC:
|
||||||
|
case R_AARCH64_LDST128_ABS_LO12_NC:
|
||||||
|
case R_AARCH64_LDST64_ABS_LO12_NC:
|
||||||
|
case R_AARCH64_LDST32_ABS_LO12_NC:
|
||||||
|
case R_AARCH64_LDST16_ABS_LO12_NC:
|
||||||
|
case R_AARCH64_LDST8_ABS_LO12_NC:
|
||||||
case R_AARCH64_GLOB_DAT:
|
case R_AARCH64_GLOB_DAT:
|
||||||
case R_AARCH64_JUMP_SLOT:
|
case R_AARCH64_JUMP_SLOT:
|
||||||
case R_AARCH64_COPY:
|
case R_AARCH64_COPY:
|
||||||
|
case R_AARCH64_CONDBR19:
|
||||||
|
case R_AARCH64_TSTBR14:
|
||||||
|
case R_AARCH64_TLSLE_ADD_TPREL_HI12:
|
||||||
|
case R_AARCH64_TLSLE_ADD_TPREL_LO12:
|
||||||
return NO_GOTPLT_ENTRY;
|
return NO_GOTPLT_ENTRY;
|
||||||
|
|
||||||
case R_AARCH64_ABS32:
|
case R_AARCH64_ABS32:
|
||||||
@ -79,20 +96,16 @@ int gotplt_entry_type (int reloc_type)
|
|||||||
case R_AARCH64_LD64_GOT_LO12_NC:
|
case R_AARCH64_LD64_GOT_LO12_NC:
|
||||||
return ALWAYS_GOTPLT_ENTRY;
|
return ALWAYS_GOTPLT_ENTRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
tcc_error ("Unknown relocation type: %d", reloc_type);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef NEED_BUILD_GOT
|
||||||
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
|
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
|
||||||
{
|
{
|
||||||
Section *plt = s1->plt;
|
Section *plt = s1->plt;
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
unsigned plt_offset;
|
unsigned plt_offset;
|
||||||
|
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL)
|
|
||||||
tcc_error("DLLs unimplemented!");
|
|
||||||
|
|
||||||
if (plt->data_offset == 0) {
|
if (plt->data_offset == 0) {
|
||||||
section_ptr_add(plt, 32);
|
section_ptr_add(plt, 32);
|
||||||
}
|
}
|
||||||
@ -118,58 +131,103 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
|||||||
|
|
||||||
if (p < p_end) {
|
if (p < p_end) {
|
||||||
uint64_t plt = s1->plt->sh_addr;
|
uint64_t plt = s1->plt->sh_addr;
|
||||||
uint64_t got = s1->got->sh_addr;
|
uint64_t got = s1->got->sh_addr + 16;
|
||||||
uint64_t off = (got >> 12) - (plt >> 12);
|
uint64_t off = (got >> 12) - (plt >> 12);
|
||||||
if ((off + ((uint32_t)1 << 20)) >> 21)
|
if ((off + ((uint32_t)1 << 20)) >> 21)
|
||||||
tcc_error("Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", off, got, plt);
|
tcc_error_noabort("Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", (long)off, (long)got, (long)plt);
|
||||||
write32le(p, 0xa9bf7bf0); // stp x16,x30,[sp,#-16]!
|
write32le(p, ARM64_STP_X_PRE | ARM64_RT(16) | ARM64_RT2(30) |
|
||||||
write32le(p + 4, (0x90000010 | // adrp x16,...
|
ARM64_RN(31) | ARM64_IMM7(-2)); // stp x16,x30,[sp,#-16]!
|
||||||
|
write32le(p + 4, (ARM64_ADRP | ARM64_RD(16) | // adrp x16,...
|
||||||
(off & 0x1ffffc) << 3 | (off & 3) << 29));
|
(off & 0x1ffffc) << 3 | (off & 3) << 29));
|
||||||
write32le(p + 8, (0xf9400211 | // ldr x17,[x16,#...]
|
write32le(p + 8, (ARM64_LDR_X | ARM64_RT(17) | ARM64_RN(16) | // ldr x17,[x16,#...]
|
||||||
(got & 0xff8) << 7));
|
(got & 0xff8) << 7));
|
||||||
write32le(p + 12, (0x91000210 | // add x16,x16,#...
|
write32le(p + 12, (ARM64_ADD_IMM | ARM64_SF(1) | ARM64_RD(16) | ARM64_RN(16) | // add x16,x16,#...
|
||||||
(got & 0xfff) << 10));
|
(got & 0xfff) << 10));
|
||||||
write32le(p + 16, 0xd61f0220); // br x17
|
write32le(p + 16, ARM64_BR | ARM64_RN(17)); // br x17
|
||||||
write32le(p + 20, 0xd503201f); // nop
|
write32le(p + 20, ARM64_NOP); // nop
|
||||||
write32le(p + 24, 0xd503201f); // nop
|
write32le(p + 24, ARM64_NOP); // nop
|
||||||
write32le(p + 28, 0xd503201f); // nop
|
write32le(p + 28, ARM64_NOP); // nop
|
||||||
p += 32;
|
p += 32;
|
||||||
|
got = s1->got->sh_addr;
|
||||||
while (p < p_end) {
|
while (p < p_end) {
|
||||||
uint64_t pc = plt + (p - s1->plt->data);
|
uint64_t pc = plt + (p - s1->plt->data);
|
||||||
uint64_t addr = got + read64le(p);
|
uint64_t addr = got + read64le(p);
|
||||||
uint64_t off = (addr >> 12) - (pc >> 12);
|
uint64_t off = (addr >> 12) - (pc >> 12);
|
||||||
if ((off + ((uint32_t)1 << 20)) >> 21)
|
if ((off + ((uint32_t)1 << 20)) >> 21)
|
||||||
tcc_error("Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", off, addr, pc);
|
tcc_error_noabort("Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", (long)off, (long)addr, (long)pc);
|
||||||
write32le(p, (0x90000010 | // adrp x16,...
|
write32le(p, (ARM64_ADRP | ARM64_RD(16) | // adrp x16,...
|
||||||
(off & 0x1ffffc) << 3 | (off & 3) << 29));
|
(off & 0x1ffffc) << 3 | (off & 3) << 29));
|
||||||
write32le(p + 4, (0xf9400211 | // ldr x17,[x16,#...]
|
write32le(p + 4, (ARM64_LDR_X | ARM64_RT(17) | ARM64_RN(16) | // ldr x17,[x16,#...]
|
||||||
(addr & 0xff8) << 7));
|
(addr & 0xff8) << 7));
|
||||||
write32le(p + 8, (0x91000210 | // add x16,x16,#...
|
write32le(p + 8, (ARM64_ADD_IMM | ARM64_SF(1) | ARM64_RD(16) | ARM64_RN(16) | // add x16,x16,#...
|
||||||
(addr & 0xfff) << 10));
|
(addr & 0xfff) << 10));
|
||||||
write32le(p + 12, 0xd61f0220); // br x17
|
write32le(p + 12, ARM64_BR | ARM64_RN(17)); // br x17
|
||||||
p += 16;
|
p += 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s1->plt->reloc) {
|
||||||
|
ElfW_Rel *rel;
|
||||||
|
p = s1->got->data;
|
||||||
|
for_each_elem(s1->plt->reloc, 0, rel, ElfW_Rel) {
|
||||||
|
write64le(p + rel->r_offset, s1->plt->sh_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
void relocate_init(Section *sr) {}
|
ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
||||||
|
|
||||||
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
|
||||||
{
|
{
|
||||||
int sym_index = ELFW(R_SYM)(rel->r_info);
|
int sym_index = ELFW(R_SYM)(rel->r_info), esym_index;
|
||||||
#ifdef DEBUG_RELOC
|
#ifdef DEBUG_RELOC
|
||||||
ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case R_AARCH64_ABS64:
|
case R_AARCH64_ABS64:
|
||||||
write64le(ptr, val);
|
if ((s1->output_type & TCC_OUTPUT_DYN)) {
|
||||||
|
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
|
||||||
|
qrel->r_offset = rel->r_offset;
|
||||||
|
if (esym_index) {
|
||||||
|
qrel->r_info = ELFW(R_INFO)(esym_index, R_AARCH64_ABS64);
|
||||||
|
qrel->r_addend = rel->r_addend;
|
||||||
|
qrel++;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
qrel->r_info = ELFW(R_INFO)(0, R_AARCH64_RELATIVE);
|
||||||
|
qrel->r_addend = read64le(ptr) + val;
|
||||||
|
qrel++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
add64le(ptr, val);
|
||||||
return;
|
return;
|
||||||
case R_AARCH64_ABS32:
|
case R_AARCH64_ABS32:
|
||||||
write32le(ptr, val);
|
if (s1->output_type & TCC_OUTPUT_DYN) {
|
||||||
|
/* XXX: this logic may depend on TCC's codegen
|
||||||
|
now TCC uses R_AARCH64_RELATIVE even for a 64bit pointer */
|
||||||
|
qrel->r_offset = rel->r_offset;
|
||||||
|
qrel->r_info = ELFW(R_INFO)(0, R_AARCH64_RELATIVE);
|
||||||
|
/* Use sign extension! */
|
||||||
|
qrel->r_addend = (int)read32le(ptr) + val;
|
||||||
|
qrel++;
|
||||||
|
}
|
||||||
|
add32le(ptr, val);
|
||||||
return;
|
return;
|
||||||
case R_AARCH64_PREL32:
|
case R_AARCH64_PREL32:
|
||||||
write32le(ptr, val - addr);
|
if (s1->output_type == TCC_OUTPUT_DLL) {
|
||||||
|
/* DLL relocation */
|
||||||
|
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
|
||||||
|
if (esym_index) {
|
||||||
|
qrel->r_offset = rel->r_offset;
|
||||||
|
qrel->r_info = ELFW(R_INFO)(esym_index, R_AARCH64_PREL32);
|
||||||
|
/* Use sign extension! */
|
||||||
|
qrel->r_addend = (int)read32le(ptr) + rel->r_addend;
|
||||||
|
qrel++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
add32le(ptr, val - addr);
|
||||||
return;
|
return;
|
||||||
case R_AARCH64_MOVW_UABS_G0_NC:
|
case R_AARCH64_MOVW_UABS_G0_NC:
|
||||||
write32le(ptr, ((read32le(ptr) & 0xffe0001f) |
|
write32le(ptr, ((read32le(ptr) & 0xffe0001f) |
|
||||||
@ -189,35 +247,106 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
return;
|
return;
|
||||||
case R_AARCH64_ADR_PREL_PG_HI21: {
|
case R_AARCH64_ADR_PREL_PG_HI21: {
|
||||||
uint64_t off = (val >> 12) - (addr >> 12);
|
uint64_t off = (val >> 12) - (addr >> 12);
|
||||||
|
#ifdef TCC_TARGET_PE
|
||||||
|
/* Weak undefined symbols resolve to address 0 on PE. ADRP cannot
|
||||||
|
encode that from the default 64-bit image base, so materialize
|
||||||
|
zero directly and let the paired ADD handle any low addend. */
|
||||||
|
if ((off + ((uint64_t)1 << 20)) >> 21) {
|
||||||
|
ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||||
|
if (sym->st_shndx == SHN_UNDEF
|
||||||
|
&& ELFW(ST_BIND)(sym->st_info) == STB_WEAK) {
|
||||||
|
write32le(ptr, 0xd2800000 | (read32le(ptr) & 0x1f));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tcc_error_noabort("R_AARCH64_ADR_PREL_PG_HI21 relocation failed");
|
||||||
|
}
|
||||||
|
#else
|
||||||
if ((off + ((uint64_t)1 << 20)) >> 21)
|
if ((off + ((uint64_t)1 << 20)) >> 21)
|
||||||
tcc_error("R_AARCH64_ADR_PREL_PG_HI21 relocation failed");
|
tcc_error_noabort("R_AARCH64_ADR_PREL_PG_HI21 relocation failed");
|
||||||
|
#endif
|
||||||
write32le(ptr, ((read32le(ptr) & 0x9f00001f) |
|
write32le(ptr, ((read32le(ptr) & 0x9f00001f) |
|
||||||
(off & 0x1ffffc) << 3 | (off & 3) << 29));
|
(off & 0x1ffffc) << 3 | (off & 3) << 29));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case R_AARCH64_ADD_ABS_LO12_NC:
|
case R_AARCH64_ADD_ABS_LO12_NC:
|
||||||
|
case R_AARCH64_LDST8_ABS_LO12_NC:
|
||||||
write32le(ptr, ((read32le(ptr) & 0xffc003ff) |
|
write32le(ptr, ((read32le(ptr) & 0xffc003ff) |
|
||||||
(val & 0xfff) << 10));
|
(val & 0xfff) << 10));
|
||||||
return;
|
return;
|
||||||
|
case R_AARCH64_LDST16_ABS_LO12_NC:
|
||||||
|
write32le(ptr, ((read32le(ptr) & 0xffc003ff) |
|
||||||
|
(val & 0xffe) << 9));
|
||||||
|
return;
|
||||||
|
case R_AARCH64_LDST32_ABS_LO12_NC:
|
||||||
|
write32le(ptr, ((read32le(ptr) & 0xffc003ff) |
|
||||||
|
(val & 0xffc) << 8));
|
||||||
|
return;
|
||||||
|
case R_AARCH64_LDST64_ABS_LO12_NC:
|
||||||
|
write32le(ptr, ((read32le(ptr) & 0xffc003ff) |
|
||||||
|
(val & 0xff8) << 7));
|
||||||
|
return;
|
||||||
|
case R_AARCH64_LDST128_ABS_LO12_NC:
|
||||||
|
write32le(ptr, ((read32le(ptr) & 0xffc003ff) |
|
||||||
|
(val & 0xff0) << 6));
|
||||||
|
return;
|
||||||
|
case R_AARCH64_CONDBR19:
|
||||||
|
/* Conditional branch: 19-bit signed offset, bits 23:5 */
|
||||||
|
#ifdef DEBUG_RELOC
|
||||||
|
printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr, val,
|
||||||
|
(char *) symtab_section->link->data + sym->st_name);
|
||||||
|
#endif
|
||||||
|
if (((val - addr) + ((uint64_t)1 << 20)) & ~(uint64_t)0x1ffffc)
|
||||||
|
tcc_error_noabort("R_AARCH64_CONDBR19 relocation failed"
|
||||||
|
" (val=%lx, addr=%lx)", (long)val, (long)addr);
|
||||||
|
write32le(ptr, ((read32le(ptr) & 0xff00001f) |
|
||||||
|
(((val - addr) >> 2 & 0x7ffff) << 5)));
|
||||||
|
return;
|
||||||
|
case R_AARCH64_TSTBR14:
|
||||||
|
/* Test and branch: 14-bit signed offset, bits 20:5 */
|
||||||
|
#ifdef DEBUG_RELOC
|
||||||
|
printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr, val,
|
||||||
|
(char *) symtab_section->link->data + sym->st_name);
|
||||||
|
#endif
|
||||||
|
if (((val - addr) + ((uint64_t)1 << 15)) & ~(uint64_t)0xfffc)
|
||||||
|
tcc_error_noabort("R_AARCH64_TSTBR14 relocation failed"
|
||||||
|
" (val=%lx, addr=%lx)", (long)val, (long)addr);
|
||||||
|
write32le(ptr, ((read32le(ptr) & 0xfff8001f) |
|
||||||
|
(((val - addr) >> 2 & 0x3fff) << 5)));
|
||||||
|
return;
|
||||||
case R_AARCH64_JUMP26:
|
case R_AARCH64_JUMP26:
|
||||||
case R_AARCH64_CALL26:
|
case R_AARCH64_CALL26:
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
#ifdef DEBUG_RELOC
|
#ifdef DEBUG_RELOC
|
||||||
printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr, val,
|
printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr, val,
|
||||||
(char *) symtab_section->link->data + sym->st_name);
|
(char *) symtab_section->link->data + sym->st_name);
|
||||||
#endif
|
#endif
|
||||||
if (((val - addr) + ((uint64_t)1 << 27)) & ~(uint64_t)0xffffffc)
|
if (((val - addr) + ((uint64_t)1 << 27)) & ~(uint64_t)0xffffffc) {
|
||||||
tcc_error("R_AARCH64_(JUMP|CALL)26 relocation failed"
|
#ifdef TCC_TARGET_PE
|
||||||
" (val=%lx, addr=%lx)", val, addr);
|
ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||||
|
if (sym->st_shndx == SHN_UNDEF
|
||||||
|
&& ELFW(ST_BIND)(sym->st_info) == STB_WEAK) {
|
||||||
|
write32le(ptr, ARM64_NOP); /* nop */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
name = (char *)symtab_section->link->data +
|
||||||
|
((ElfW(Sym) *)symtab_section->data)[sym_index].st_name;
|
||||||
|
tcc_error_noabort("R_AARCH64_(JUMP|CALL)26 relocation failed"
|
||||||
|
" for '%s' (val=%lx, addr=%lx)",
|
||||||
|
name, (long)val, (long)addr);
|
||||||
|
}
|
||||||
write32le(ptr, (0x14000000 |
|
write32le(ptr, (0x14000000 |
|
||||||
(uint32_t)(type == R_AARCH64_CALL26) << 31 |
|
(uint32_t)(type == R_AARCH64_CALL26) << 31 |
|
||||||
((val - addr) >> 2 & 0x3ffffff)));
|
((val - addr) >> 2 & 0x3ffffff)));
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
case R_AARCH64_ADR_GOT_PAGE: {
|
case R_AARCH64_ADR_GOT_PAGE: {
|
||||||
uint64_t off =
|
uint64_t off =
|
||||||
(((s1->got->sh_addr +
|
(((s1->got->sh_addr +
|
||||||
s1->sym_attrs[sym_index].got_offset) >> 12) - (addr >> 12));
|
get_sym_attr(s1, sym_index, 0)->got_offset) >> 12) - (addr >> 12));
|
||||||
if ((off + ((uint64_t)1 << 20)) >> 21)
|
if ((off + ((uint64_t)1 << 20)) >> 21)
|
||||||
tcc_error("R_AARCH64_ADR_GOT_PAGE relocation failed");
|
tcc_error_noabort("R_AARCH64_ADR_GOT_PAGE relocation failed");
|
||||||
write32le(ptr, ((read32le(ptr) & 0x9f00001f) |
|
write32le(ptr, ((read32le(ptr) & 0x9f00001f) |
|
||||||
(off & 0x1ffffc) << 3 | (off & 3) << 29));
|
(off & 0x1ffffc) << 3 | (off & 3) << 29));
|
||||||
return;
|
return;
|
||||||
@ -226,7 +355,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
write32le(ptr,
|
write32le(ptr,
|
||||||
((read32le(ptr) & 0xfff803ff) |
|
((read32le(ptr) & 0xfff803ff) |
|
||||||
((s1->got->sh_addr +
|
((s1->got->sh_addr +
|
||||||
s1->sym_attrs[sym_index].got_offset) & 0xff8) << 7));
|
get_sym_attr(s1, sym_index, 0)->got_offset) & 0xff8) << 7));
|
||||||
return;
|
return;
|
||||||
case R_AARCH64_COPY:
|
case R_AARCH64_COPY:
|
||||||
return;
|
return;
|
||||||
@ -240,6 +369,27 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
#endif
|
#endif
|
||||||
write64le(ptr, val - rel->r_addend);
|
write64le(ptr, val - rel->r_addend);
|
||||||
return;
|
return;
|
||||||
|
case R_AARCH64_TLSLE_ADD_TPREL_HI12:
|
||||||
|
case R_AARCH64_TLSLE_ADD_TPREL_LO12: {
|
||||||
|
addr_t tls_start = 0;
|
||||||
|
int i;
|
||||||
|
for (i = 1; i < s1->nb_sections; i++) {
|
||||||
|
Section *s = s1->sections[i];
|
||||||
|
if (s->sh_flags & SHF_TLS && s->sh_size) {
|
||||||
|
if (!tls_start || s->sh_addr < tls_start)
|
||||||
|
tls_start = s->sh_addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* glibc arm64: tp points to tcbhead_t (DTV), TLS data starts after it */
|
||||||
|
int64_t tp_offset = val - tls_start + 16;
|
||||||
|
int64_t imm;
|
||||||
|
if (type == R_AARCH64_TLSLE_ADD_TPREL_HI12)
|
||||||
|
imm = (tp_offset >> 12) & 0xfff;
|
||||||
|
else
|
||||||
|
imm = tp_offset & 0xfff;
|
||||||
|
write32le(ptr, ((read32le(ptr) & 0xffc003ff) | (imm << 10)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
case R_AARCH64_RELATIVE:
|
case R_AARCH64_RELATIVE:
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
add32le(ptr, val - s1->pe_imagebase);
|
add32le(ptr, val - s1->pe_imagebase);
|
||||||
|
|||||||
840
arm64-tok.h
Normal file
840
arm64-tok.h
Normal file
@ -0,0 +1,840 @@
|
|||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
/* ARM64 (AArch64) assembler token definitions for TCC */
|
||||||
|
|
||||||
|
/* General purpose registers - 64-bit */
|
||||||
|
DEF_ASM(x0)
|
||||||
|
DEF_ASM(x1)
|
||||||
|
DEF_ASM(x2)
|
||||||
|
DEF_ASM(x3)
|
||||||
|
DEF_ASM(x4)
|
||||||
|
DEF_ASM(x5)
|
||||||
|
DEF_ASM(x6)
|
||||||
|
DEF_ASM(x7)
|
||||||
|
DEF_ASM(x8)
|
||||||
|
DEF_ASM(x9)
|
||||||
|
DEF_ASM(x10)
|
||||||
|
DEF_ASM(x11)
|
||||||
|
DEF_ASM(x12)
|
||||||
|
DEF_ASM(x13)
|
||||||
|
DEF_ASM(x14)
|
||||||
|
DEF_ASM(x15)
|
||||||
|
DEF_ASM(x16)
|
||||||
|
DEF_ASM(x17)
|
||||||
|
DEF_ASM(x18)
|
||||||
|
DEF_ASM(x19)
|
||||||
|
DEF_ASM(x20)
|
||||||
|
DEF_ASM(x21)
|
||||||
|
DEF_ASM(x22)
|
||||||
|
DEF_ASM(x23)
|
||||||
|
DEF_ASM(x24)
|
||||||
|
DEF_ASM(x25)
|
||||||
|
DEF_ASM(x26)
|
||||||
|
DEF_ASM(x27)
|
||||||
|
DEF_ASM(x28)
|
||||||
|
DEF_ASM(x29)
|
||||||
|
DEF_ASM(x30)
|
||||||
|
|
||||||
|
/* General purpose registers - 32-bit */
|
||||||
|
DEF_ASM(w0)
|
||||||
|
DEF_ASM(w1)
|
||||||
|
DEF_ASM(w2)
|
||||||
|
DEF_ASM(w3)
|
||||||
|
DEF_ASM(w4)
|
||||||
|
DEF_ASM(w5)
|
||||||
|
DEF_ASM(w6)
|
||||||
|
DEF_ASM(w7)
|
||||||
|
DEF_ASM(w8)
|
||||||
|
DEF_ASM(w9)
|
||||||
|
DEF_ASM(w10)
|
||||||
|
DEF_ASM(w11)
|
||||||
|
DEF_ASM(w12)
|
||||||
|
DEF_ASM(w13)
|
||||||
|
DEF_ASM(w14)
|
||||||
|
DEF_ASM(w15)
|
||||||
|
DEF_ASM(w16)
|
||||||
|
DEF_ASM(w17)
|
||||||
|
DEF_ASM(w18)
|
||||||
|
DEF_ASM(w19)
|
||||||
|
DEF_ASM(w20)
|
||||||
|
DEF_ASM(w21)
|
||||||
|
DEF_ASM(w22)
|
||||||
|
DEF_ASM(w23)
|
||||||
|
DEF_ASM(w24)
|
||||||
|
DEF_ASM(w25)
|
||||||
|
DEF_ASM(w26)
|
||||||
|
DEF_ASM(w27)
|
||||||
|
DEF_ASM(w28)
|
||||||
|
DEF_ASM(w29)
|
||||||
|
DEF_ASM(w30)
|
||||||
|
|
||||||
|
/* Special registers */
|
||||||
|
DEF_ASM(sp)
|
||||||
|
DEF_ASM(xzr)
|
||||||
|
DEF_ASM(wzr)
|
||||||
|
|
||||||
|
/* SIMD/FP registers - 128-bit views */
|
||||||
|
DEF_ASM(v0)
|
||||||
|
DEF_ASM(v1)
|
||||||
|
DEF_ASM(v2)
|
||||||
|
DEF_ASM(v3)
|
||||||
|
DEF_ASM(v4)
|
||||||
|
DEF_ASM(v5)
|
||||||
|
DEF_ASM(v6)
|
||||||
|
DEF_ASM(v7)
|
||||||
|
DEF_ASM(v8)
|
||||||
|
DEF_ASM(v9)
|
||||||
|
DEF_ASM(v10)
|
||||||
|
DEF_ASM(v11)
|
||||||
|
DEF_ASM(v12)
|
||||||
|
DEF_ASM(v13)
|
||||||
|
DEF_ASM(v14)
|
||||||
|
DEF_ASM(v15)
|
||||||
|
DEF_ASM(v16)
|
||||||
|
DEF_ASM(v17)
|
||||||
|
DEF_ASM(v18)
|
||||||
|
DEF_ASM(v19)
|
||||||
|
DEF_ASM(v20)
|
||||||
|
DEF_ASM(v21)
|
||||||
|
DEF_ASM(v22)
|
||||||
|
DEF_ASM(v23)
|
||||||
|
DEF_ASM(v24)
|
||||||
|
DEF_ASM(v25)
|
||||||
|
DEF_ASM(v26)
|
||||||
|
DEF_ASM(v27)
|
||||||
|
DEF_ASM(v28)
|
||||||
|
DEF_ASM(v29)
|
||||||
|
DEF_ASM(v30)
|
||||||
|
DEF_ASM(v31)
|
||||||
|
|
||||||
|
/* SIMD/FP registers - 64-bit views (double) */
|
||||||
|
DEF_ASM(d0)
|
||||||
|
DEF_ASM(d1)
|
||||||
|
DEF_ASM(d2)
|
||||||
|
DEF_ASM(d3)
|
||||||
|
DEF_ASM(d4)
|
||||||
|
DEF_ASM(d5)
|
||||||
|
DEF_ASM(d6)
|
||||||
|
DEF_ASM(d7)
|
||||||
|
DEF_ASM(d8)
|
||||||
|
DEF_ASM(d9)
|
||||||
|
DEF_ASM(d10)
|
||||||
|
DEF_ASM(d11)
|
||||||
|
DEF_ASM(d12)
|
||||||
|
DEF_ASM(d13)
|
||||||
|
DEF_ASM(d14)
|
||||||
|
DEF_ASM(d15)
|
||||||
|
DEF_ASM(d16)
|
||||||
|
DEF_ASM(d17)
|
||||||
|
DEF_ASM(d18)
|
||||||
|
DEF_ASM(d19)
|
||||||
|
DEF_ASM(d20)
|
||||||
|
DEF_ASM(d21)
|
||||||
|
DEF_ASM(d22)
|
||||||
|
DEF_ASM(d23)
|
||||||
|
DEF_ASM(d24)
|
||||||
|
DEF_ASM(d25)
|
||||||
|
DEF_ASM(d26)
|
||||||
|
DEF_ASM(d27)
|
||||||
|
DEF_ASM(d28)
|
||||||
|
DEF_ASM(d29)
|
||||||
|
DEF_ASM(d30)
|
||||||
|
DEF_ASM(d31)
|
||||||
|
|
||||||
|
/* SIMD/FP registers - 32-bit views (single) */
|
||||||
|
DEF_ASM(s0)
|
||||||
|
DEF_ASM(s1)
|
||||||
|
DEF_ASM(s2)
|
||||||
|
DEF_ASM(s3)
|
||||||
|
DEF_ASM(s4)
|
||||||
|
DEF_ASM(s5)
|
||||||
|
DEF_ASM(s6)
|
||||||
|
DEF_ASM(s7)
|
||||||
|
DEF_ASM(s8)
|
||||||
|
DEF_ASM(s9)
|
||||||
|
DEF_ASM(s10)
|
||||||
|
DEF_ASM(s11)
|
||||||
|
DEF_ASM(s12)
|
||||||
|
DEF_ASM(s13)
|
||||||
|
DEF_ASM(s14)
|
||||||
|
DEF_ASM(s15)
|
||||||
|
DEF_ASM(s16)
|
||||||
|
DEF_ASM(s17)
|
||||||
|
DEF_ASM(s18)
|
||||||
|
DEF_ASM(s19)
|
||||||
|
DEF_ASM(s20)
|
||||||
|
DEF_ASM(s21)
|
||||||
|
DEF_ASM(s22)
|
||||||
|
DEF_ASM(s23)
|
||||||
|
DEF_ASM(s24)
|
||||||
|
DEF_ASM(s25)
|
||||||
|
DEF_ASM(s26)
|
||||||
|
DEF_ASM(s27)
|
||||||
|
DEF_ASM(s28)
|
||||||
|
DEF_ASM(s29)
|
||||||
|
DEF_ASM(s30)
|
||||||
|
DEF_ASM(s31)
|
||||||
|
|
||||||
|
/* SIMD/FP registers - 16-bit views (half) */
|
||||||
|
DEF_ASM(h0)
|
||||||
|
DEF_ASM(h1)
|
||||||
|
DEF_ASM(h2)
|
||||||
|
DEF_ASM(h3)
|
||||||
|
DEF_ASM(h4)
|
||||||
|
DEF_ASM(h5)
|
||||||
|
DEF_ASM(h6)
|
||||||
|
DEF_ASM(h7)
|
||||||
|
DEF_ASM(h8)
|
||||||
|
DEF_ASM(h9)
|
||||||
|
DEF_ASM(h10)
|
||||||
|
DEF_ASM(h11)
|
||||||
|
DEF_ASM(h12)
|
||||||
|
DEF_ASM(h13)
|
||||||
|
DEF_ASM(h14)
|
||||||
|
DEF_ASM(h15)
|
||||||
|
DEF_ASM(h16)
|
||||||
|
DEF_ASM(h17)
|
||||||
|
DEF_ASM(h18)
|
||||||
|
DEF_ASM(h19)
|
||||||
|
DEF_ASM(h20)
|
||||||
|
DEF_ASM(h21)
|
||||||
|
DEF_ASM(h22)
|
||||||
|
DEF_ASM(h23)
|
||||||
|
DEF_ASM(h24)
|
||||||
|
DEF_ASM(h25)
|
||||||
|
DEF_ASM(h26)
|
||||||
|
DEF_ASM(h27)
|
||||||
|
DEF_ASM(h28)
|
||||||
|
DEF_ASM(h29)
|
||||||
|
DEF_ASM(h30)
|
||||||
|
DEF_ASM(h31)
|
||||||
|
|
||||||
|
/* SIMD/FP registers - 8-bit views (byte) */
|
||||||
|
DEF_ASM(b0)
|
||||||
|
DEF_ASM(b1)
|
||||||
|
DEF_ASM(b2)
|
||||||
|
DEF_ASM(b3)
|
||||||
|
DEF_ASM(b4)
|
||||||
|
DEF_ASM(b5)
|
||||||
|
DEF_ASM(b6)
|
||||||
|
DEF_ASM(b7)
|
||||||
|
DEF_ASM(b8)
|
||||||
|
DEF_ASM(b9)
|
||||||
|
DEF_ASM(b10)
|
||||||
|
DEF_ASM(b11)
|
||||||
|
DEF_ASM(b12)
|
||||||
|
DEF_ASM(b13)
|
||||||
|
DEF_ASM(b14)
|
||||||
|
DEF_ASM(b15)
|
||||||
|
DEF_ASM(b16)
|
||||||
|
DEF_ASM(b17)
|
||||||
|
DEF_ASM(b18)
|
||||||
|
DEF_ASM(b19)
|
||||||
|
DEF_ASM(b20)
|
||||||
|
DEF_ASM(b21)
|
||||||
|
DEF_ASM(b22)
|
||||||
|
DEF_ASM(b23)
|
||||||
|
DEF_ASM(b24)
|
||||||
|
DEF_ASM(b25)
|
||||||
|
DEF_ASM(b26)
|
||||||
|
DEF_ASM(b27)
|
||||||
|
DEF_ASM(b28)
|
||||||
|
DEF_ASM(b29)
|
||||||
|
DEF_ASM(b30)
|
||||||
|
DEF_ASM(b31)
|
||||||
|
|
||||||
|
/* Condition codes */
|
||||||
|
DEF_ASM(eq)
|
||||||
|
DEF_ASM(ne)
|
||||||
|
DEF_ASM(cs)
|
||||||
|
DEF_ASM(hs)
|
||||||
|
DEF_ASM(cc)
|
||||||
|
DEF_ASM(lo)
|
||||||
|
DEF_ASM(mi)
|
||||||
|
DEF_ASM(pl)
|
||||||
|
DEF_ASM(vs)
|
||||||
|
DEF_ASM(vc)
|
||||||
|
DEF_ASM(hi)
|
||||||
|
DEF_ASM(ls)
|
||||||
|
DEF_ASM(ge)
|
||||||
|
DEF_ASM(lt)
|
||||||
|
DEF_ASM(gt)
|
||||||
|
DEF_ASM(le)
|
||||||
|
DEF_ASM(al)
|
||||||
|
|
||||||
|
/* Data processing - arithmetic (no condition suffixes for ARM64) */
|
||||||
|
DEF_ASM(add)
|
||||||
|
DEF_ASM(adds)
|
||||||
|
DEF_ASM(sub)
|
||||||
|
DEF_ASM(subs)
|
||||||
|
DEF_ASM(cmn)
|
||||||
|
DEF_ASM(cmp)
|
||||||
|
DEF_ASM(neg)
|
||||||
|
DEF_ASM(negs)
|
||||||
|
DEF_ASM(adc)
|
||||||
|
DEF_ASM(adcs)
|
||||||
|
DEF_ASM(sbc)
|
||||||
|
DEF_ASM(sbcs)
|
||||||
|
DEF_ASM(ngc)
|
||||||
|
DEF_ASM(ngcs)
|
||||||
|
|
||||||
|
/* Data processing - bitwise */
|
||||||
|
DEF_ASM(and)
|
||||||
|
DEF_ASM(ands)
|
||||||
|
DEF_ASM(bic)
|
||||||
|
DEF_ASM(bics)
|
||||||
|
DEF_ASM(orr)
|
||||||
|
DEF_ASM(orn)
|
||||||
|
DEF_ASM(eor)
|
||||||
|
DEF_ASM(eon)
|
||||||
|
DEF_ASM(mvn)
|
||||||
|
DEF_ASM(mov)
|
||||||
|
|
||||||
|
/* Shifts */
|
||||||
|
DEF_ASM(lsl)
|
||||||
|
DEF_ASM(lsr)
|
||||||
|
DEF_ASM(asr)
|
||||||
|
DEF_ASM(ror)
|
||||||
|
|
||||||
|
/* Multiply/divide */
|
||||||
|
DEF_ASM(mul)
|
||||||
|
DEF_ASM(madd)
|
||||||
|
DEF_ASM(msub)
|
||||||
|
DEF_ASM(smaddl)
|
||||||
|
DEF_ASM(smsubl)
|
||||||
|
DEF_ASM(umaddl)
|
||||||
|
DEF_ASM(umsubl)
|
||||||
|
DEF_ASM(smulh)
|
||||||
|
DEF_ASM(umulh)
|
||||||
|
DEF_ASM(udiv)
|
||||||
|
DEF_ASM(sdiv)
|
||||||
|
|
||||||
|
/* Moves */
|
||||||
|
DEF_ASM(movz)
|
||||||
|
DEF_ASM(movn)
|
||||||
|
DEF_ASM(movk)
|
||||||
|
|
||||||
|
/* Compare/test */
|
||||||
|
DEF_ASM(tst)
|
||||||
|
DEF_ASM(teq)
|
||||||
|
|
||||||
|
/* Branch instructions */
|
||||||
|
DEF_ASM(b)
|
||||||
|
DEF_ASM(bl)
|
||||||
|
DEF_ASM(br)
|
||||||
|
DEF_ASM(blr)
|
||||||
|
DEF_ASM(ret)
|
||||||
|
DEF_ASM(cbz)
|
||||||
|
DEF_ASM(cbnz)
|
||||||
|
DEF_ASM(tbz)
|
||||||
|
DEF_ASM(tbnz)
|
||||||
|
|
||||||
|
/* Conditional branches */
|
||||||
|
DEF_ASM(beq)
|
||||||
|
DEF_ASM(bne)
|
||||||
|
DEF_ASM(bcs)
|
||||||
|
DEF_ASM(bhs)
|
||||||
|
DEF_ASM(bcc)
|
||||||
|
DEF_ASM(blo)
|
||||||
|
DEF_ASM(bmi)
|
||||||
|
DEF_ASM(bpl)
|
||||||
|
DEF_ASM(bvs)
|
||||||
|
DEF_ASM(bvc)
|
||||||
|
DEF_ASM(bhi)
|
||||||
|
DEF_ASM(bls)
|
||||||
|
DEF_ASM(bge)
|
||||||
|
DEF_ASM(blt)
|
||||||
|
DEF_ASM(bgt)
|
||||||
|
DEF_ASM(ble)
|
||||||
|
|
||||||
|
/* Conditional select */
|
||||||
|
DEF_ASM(csel)
|
||||||
|
DEF_ASM(csinc)
|
||||||
|
DEF_ASM(csinv)
|
||||||
|
DEF_ASM(csneg)
|
||||||
|
|
||||||
|
/* Load/Store */
|
||||||
|
DEF_ASM(ldr)
|
||||||
|
DEF_ASM(ldrb)
|
||||||
|
DEF_ASM(ldrh)
|
||||||
|
DEF_ASM(ldrsb)
|
||||||
|
DEF_ASM(ldrsh)
|
||||||
|
DEF_ASM(ldrsw)
|
||||||
|
DEF_ASM(str)
|
||||||
|
DEF_ASM(strb)
|
||||||
|
DEF_ASM(strh)
|
||||||
|
|
||||||
|
/* Load/Store - pair */
|
||||||
|
DEF_ASM(ldp)
|
||||||
|
DEF_ASM(stp)
|
||||||
|
DEF_ASM(ldpsw)
|
||||||
|
|
||||||
|
/* Address generation */
|
||||||
|
DEF_ASM(adr)
|
||||||
|
DEF_ASM(adrp)
|
||||||
|
|
||||||
|
/* System instructions */
|
||||||
|
DEF_ASM(mrs)
|
||||||
|
DEF_ASM(msr)
|
||||||
|
DEF_ASM(nop)
|
||||||
|
DEF_ASM(wfi)
|
||||||
|
DEF_ASM(wfe)
|
||||||
|
DEF_ASM(sev)
|
||||||
|
DEF_ASM(sevl)
|
||||||
|
DEF_ASM(isb)
|
||||||
|
DEF_ASM(dsb)
|
||||||
|
DEF_ASM(dmb)
|
||||||
|
|
||||||
|
/* Hints */
|
||||||
|
DEF_ASM(yield)
|
||||||
|
DEF_ASM(clrex)
|
||||||
|
|
||||||
|
/* Push/pop */
|
||||||
|
DEF_ASM(push)
|
||||||
|
DEF_ASM(pop)
|
||||||
|
|
||||||
|
/* Floating point */
|
||||||
|
DEF_ASM(fmov)
|
||||||
|
DEF_ASM(fadd)
|
||||||
|
DEF_ASM(fsub)
|
||||||
|
DEF_ASM(fmul)
|
||||||
|
DEF_ASM(fnmul)
|
||||||
|
DEF_ASM(fdiv)
|
||||||
|
DEF_ASM(fmax)
|
||||||
|
DEF_ASM(fmin)
|
||||||
|
DEF_ASM(fmaxnm)
|
||||||
|
DEF_ASM(fminnm)
|
||||||
|
DEF_ASM(fsqrt)
|
||||||
|
DEF_ASM(fabs)
|
||||||
|
DEF_ASM(fneg)
|
||||||
|
DEF_ASM(frintn)
|
||||||
|
DEF_ASM(frintp)
|
||||||
|
DEF_ASM(frintm)
|
||||||
|
DEF_ASM(frintz)
|
||||||
|
DEF_ASM(frinta)
|
||||||
|
DEF_ASM(frintx)
|
||||||
|
DEF_ASM(frinti)
|
||||||
|
DEF_ASM(fcmp)
|
||||||
|
DEF_ASM(fcmpe)
|
||||||
|
DEF_ASM(fccmp)
|
||||||
|
DEF_ASM(fccmpe)
|
||||||
|
DEF_ASM(fcvts)
|
||||||
|
DEF_ASM(fcvtd)
|
||||||
|
DEF_ASM(fcvth)
|
||||||
|
DEF_ASM(fcvtx)
|
||||||
|
DEF_ASM(scvtf)
|
||||||
|
DEF_ASM(ucvtf)
|
||||||
|
DEF_ASM(fcvtns)
|
||||||
|
DEF_ASM(fcvtnu)
|
||||||
|
DEF_ASM(fcvtps)
|
||||||
|
DEF_ASM(fcvtpu)
|
||||||
|
|
||||||
|
/* SIMD instructions */
|
||||||
|
DEF_ASM(addv)
|
||||||
|
DEF_ASM(faddp)
|
||||||
|
DEF_ASM(fmaxp)
|
||||||
|
DEF_ASM(fminp)
|
||||||
|
DEF_ASM(fmaxnmp)
|
||||||
|
DEF_ASM(fminnmp)
|
||||||
|
DEF_ASM(addp)
|
||||||
|
DEF_ASM(bif)
|
||||||
|
DEF_ASM(bit)
|
||||||
|
DEF_ASM(bsl)
|
||||||
|
DEF_ASM(dup)
|
||||||
|
DEF_ASM(ext)
|
||||||
|
DEF_ASM(ins)
|
||||||
|
DEF_ASM(movi)
|
||||||
|
DEF_ASM(mvni)
|
||||||
|
DEF_ASM(not)
|
||||||
|
DEF_ASM(shl)
|
||||||
|
DEF_ASM(shll)
|
||||||
|
DEF_ASM(shll2)
|
||||||
|
DEF_ASM(sli)
|
||||||
|
DEF_ASM(sri)
|
||||||
|
DEF_ASM(sqshl)
|
||||||
|
DEF_ASM(sqshlu)
|
||||||
|
DEF_ASM(srshl)
|
||||||
|
DEF_ASM(sshll)
|
||||||
|
DEF_ASM(sshll2)
|
||||||
|
DEF_ASM(sshr)
|
||||||
|
DEF_ASM(ushll)
|
||||||
|
DEF_ASM(ushll2)
|
||||||
|
DEF_ASM(ushr)
|
||||||
|
|
||||||
|
/* Misc */
|
||||||
|
DEF_ASM(bfm)
|
||||||
|
DEF_ASM(sbfm)
|
||||||
|
DEF_ASM(ubfm)
|
||||||
|
DEF_ASM(extr)
|
||||||
|
DEF_ASM(crc32b)
|
||||||
|
DEF_ASM(crc32h)
|
||||||
|
DEF_ASM(crc32w)
|
||||||
|
DEF_ASM(crc32x)
|
||||||
|
DEF_ASM(crc32cb)
|
||||||
|
DEF_ASM(crc32ch)
|
||||||
|
DEF_ASM(crc32cw)
|
||||||
|
DEF_ASM(crc32cx)
|
||||||
|
DEF_ASM(rev)
|
||||||
|
DEF_ASM(rev16)
|
||||||
|
DEF_ASM(rev32)
|
||||||
|
DEF_ASM(rev64)
|
||||||
|
DEF_ASM(clz)
|
||||||
|
DEF_ASM(cls)
|
||||||
|
DEF_ASM(rbit)
|
||||||
|
|
||||||
|
/* Exception generating */
|
||||||
|
DEF_ASM(svc)
|
||||||
|
DEF_ASM(hvc)
|
||||||
|
DEF_ASM(smc)
|
||||||
|
DEF_ASM(brk)
|
||||||
|
DEF_ASM(hlt)
|
||||||
|
DEF_ASM(dcps1)
|
||||||
|
DEF_ASM(dcps2)
|
||||||
|
DEF_ASM(dcps3)
|
||||||
|
|
||||||
|
/* Conditional branches */
|
||||||
|
DEF_ASM(b_eq)
|
||||||
|
DEF_ASM(b_ne)
|
||||||
|
DEF_ASM(b_cs)
|
||||||
|
DEF_ASM(b_cc)
|
||||||
|
DEF_ASM(b_mi)
|
||||||
|
DEF_ASM(b_pl)
|
||||||
|
DEF_ASM(b_vs)
|
||||||
|
DEF_ASM(b_vc)
|
||||||
|
DEF_ASM(b_hi)
|
||||||
|
DEF_ASM(b_ls)
|
||||||
|
DEF_ASM(b_ge)
|
||||||
|
DEF_ASM(b_lt)
|
||||||
|
DEF_ASM(b_gt)
|
||||||
|
DEF_ASM(b_le)
|
||||||
|
|
||||||
|
/* LD/ST exclusive */
|
||||||
|
DEF_ASM(ldxr)
|
||||||
|
DEF_ASM(ldxrb)
|
||||||
|
DEF_ASM(ldxrh)
|
||||||
|
DEF_ASM(stxr)
|
||||||
|
DEF_ASM(stxrb)
|
||||||
|
DEF_ASM(stxrh)
|
||||||
|
DEF_ASM(ldaxr)
|
||||||
|
DEF_ASM(ldaxrb)
|
||||||
|
DEF_ASM(ldaxrh)
|
||||||
|
DEF_ASM(stlxr)
|
||||||
|
DEF_ASM(stlxrb)
|
||||||
|
DEF_ASM(stlxrh)
|
||||||
|
|
||||||
|
/* LD/ST acquire-release */
|
||||||
|
DEF_ASM(ldar)
|
||||||
|
DEF_ASM(ldarb)
|
||||||
|
DEF_ASM(ldarh)
|
||||||
|
DEF_ASM(stlr)
|
||||||
|
DEF_ASM(stlrb)
|
||||||
|
DEF_ASM(stlrh)
|
||||||
|
DEF_ASM(ldalr)
|
||||||
|
DEF_ASM(ldalrb)
|
||||||
|
DEF_ASM(ldalrh)
|
||||||
|
DEF_ASM(stllr)
|
||||||
|
DEF_ASM(stllrb)
|
||||||
|
DEF_ASM(stllrh)
|
||||||
|
|
||||||
|
/* LD/ST unscaled immediate */
|
||||||
|
DEF_ASM(ldur)
|
||||||
|
DEF_ASM(ldurb)
|
||||||
|
DEF_ASM(ldurh)
|
||||||
|
DEF_ASM(ldursb)
|
||||||
|
DEF_ASM(ldursh)
|
||||||
|
DEF_ASM(ldursw)
|
||||||
|
DEF_ASM(stur)
|
||||||
|
DEF_ASM(sturb)
|
||||||
|
DEF_ASM(sturh)
|
||||||
|
|
||||||
|
/* Vector load/store */
|
||||||
|
DEF_ASM(ld1)
|
||||||
|
DEF_ASM(st1)
|
||||||
|
DEF_ASM(ld2)
|
||||||
|
DEF_ASM(st2)
|
||||||
|
DEF_ASM(ld3)
|
||||||
|
DEF_ASM(st3)
|
||||||
|
DEF_ASM(ld4)
|
||||||
|
DEF_ASM(st4)
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
/* ARM64 instruction opcode constants and encoding helpers */
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
/* Data processing - immediate */
|
||||||
|
#define ARM64_ADD_IMM 0x11000000U
|
||||||
|
#define ARM64_ADDS_IMM 0x2B000000U
|
||||||
|
#define ARM64_SUB_IMM 0x51000000U
|
||||||
|
#define ARM64_SUBS_IMM 0x6B000000U
|
||||||
|
|
||||||
|
/* Data processing - register */
|
||||||
|
#define ARM64_ADD_REG 0x0B000000U
|
||||||
|
#define ARM64_ADDS_REG 0x2B000000U
|
||||||
|
#define ARM64_SUB_REG 0x4B000000U
|
||||||
|
#define ARM64_SUBS_REG 0x6B000000U
|
||||||
|
#define ARM64_AND_REG 0x0A000000U
|
||||||
|
#define ARM64_ANDS_REG 0x6A000000U
|
||||||
|
#define ARM64_ORR_REG 0x2A000000U
|
||||||
|
#define ARM64_EOR_REG 0x4A000000U
|
||||||
|
#define ARM64_MUL_REG 0x1B000000U /* Base opcode, Rm/Rn/Rd must be filled in */
|
||||||
|
|
||||||
|
/* Move wide immediate */
|
||||||
|
#define ARM64_MOVZ 0x52800000U
|
||||||
|
#define ARM64_MOVN 0x12800000U
|
||||||
|
#define ARM64_MOVK 0xF2800000U
|
||||||
|
/* ARM64_MOVI_W/X removed: MOVI is a SIMD&FP instruction, not general-purpose */
|
||||||
|
/* Use MOVZ/MOVN/MOVK for general-purpose, or SIMD MOVI variants (0x0F000400, etc.) */
|
||||||
|
|
||||||
|
/* MOVZ/MOVN 64-bit base opcodes */
|
||||||
|
#define ARM64_MOVZ64 0xD2800000U /* MOVZ (64-bit), use with ARM64_HW() */
|
||||||
|
#define ARM64_MOVN64 0x92800000U /* MOVN (64-bit), use with ARM64_HW() */
|
||||||
|
|
||||||
|
/* Move wide immediate shift field (LSL #0/16/32/48 encoded as hw*16) */
|
||||||
|
#define ARM64_HW(v) (((uint32_t)(v) & 3) << 21)
|
||||||
|
|
||||||
|
/* Load/store register (unsigned immediate) */
|
||||||
|
#define ARM64_LDR_X 0xF9400000U
|
||||||
|
#define ARM64_LDR_W 0xB9400000U
|
||||||
|
#define ARM64_LDR_B 0x39400000U
|
||||||
|
#define ARM64_LDR_H 0x79400000U
|
||||||
|
#define ARM64_LDR_D 0xFD400000U
|
||||||
|
#define ARM64_LDR_S 0xBD400000U
|
||||||
|
#define ARM64_STR_X 0xF9000000U
|
||||||
|
#define ARM64_STR_W 0xB9000000U
|
||||||
|
#define ARM64_STR_B 0x39000000U
|
||||||
|
#define ARM64_STR_H 0x79000000U
|
||||||
|
#define ARM64_STR_D 0xFD000000U
|
||||||
|
#define ARM64_STR_S 0xBD000000U
|
||||||
|
|
||||||
|
/* Load/store register (unscaled immediate) */
|
||||||
|
#define ARM64_LDUR_X 0xF8400000U
|
||||||
|
#define ARM64_LDUR_W 0xB8400000U
|
||||||
|
#define ARM64_LDUR_B 0x38400000U
|
||||||
|
#define ARM64_LDUR_H 0x78400000U
|
||||||
|
#define ARM64_STUR_X 0xF8000000U
|
||||||
|
#define ARM64_STUR_W 0xB8000000U
|
||||||
|
#define ARM64_STUR_B 0x38000000U
|
||||||
|
#define ARM64_STUR_H 0x78000000U
|
||||||
|
|
||||||
|
/* Load/store register (register offset) */
|
||||||
|
#define ARM64_LDR_X_REG 0xF8606800U
|
||||||
|
#define ARM64_LDR_W_REG 0xB8606800U
|
||||||
|
#define ARM64_LDR_B_REG 0x38606800U
|
||||||
|
#define ARM64_LDR_H_REG 0x78606800U
|
||||||
|
#define ARM64_STR_X_REG 0xF8206800U
|
||||||
|
#define ARM64_STR_W_REG 0xB8206800U
|
||||||
|
#define ARM64_STR_B_REG 0x38206800U
|
||||||
|
#define ARM64_STR_H_REG 0x78206800U
|
||||||
|
|
||||||
|
/* Load/store (pre/post-indexed) */
|
||||||
|
#define ARM64_STR_X_PRE 0xF8000000U /* STR X pre-indexed base */
|
||||||
|
#define ARM64_LDR_X_POST 0xF8400000U /* LDR X post-indexed base */
|
||||||
|
|
||||||
|
/* SIMD load/store (unsigned immediate) */
|
||||||
|
#define ARM64_LDR_SCALAR 0x3D400000U /* Base for scalar load (size built dynamically) */
|
||||||
|
#define ARM64_LDR_S_VEC 0xBD400000U
|
||||||
|
#define ARM64_LDR_D_VEC 0xFD400000U
|
||||||
|
#define ARM64_LDR_Q_VEC 0x3DC00000U
|
||||||
|
#define ARM64_STR_SCALAR 0x3D000000U /* Base for scalar store (size built dynamically) */
|
||||||
|
#define ARM64_STR_S_VEC 0xBD000000U
|
||||||
|
#define ARM64_STR_D_VEC 0xFD000000U
|
||||||
|
#define ARM64_STR_Q_VEC 0x3D800000U
|
||||||
|
|
||||||
|
/* SIMD load/store (unscaled immediate) */
|
||||||
|
#define ARM64_LDUR_S_SIMD 0xBC400000U
|
||||||
|
#define ARM64_LDUR_D_SIMD 0xFC400000U
|
||||||
|
#define ARM64_LDUR_Q_SIMD 0x3C400000U
|
||||||
|
#define ARM64_STUR_S_SIMD 0xBC000000U
|
||||||
|
#define ARM64_STUR_D_SIMD 0xFC000000U
|
||||||
|
#define ARM64_STUR_Q_SIMD 0x3C000000U
|
||||||
|
|
||||||
|
/* SIMD load/store (register offset) */
|
||||||
|
#define ARM64_LDR_S_REG 0xBC606800U
|
||||||
|
#define ARM64_LDR_D_REG 0xFC606800U
|
||||||
|
#define ARM64_LDR_Q_REG 0x3C606800U
|
||||||
|
#define ARM64_STR_S_REG 0xBC206800U
|
||||||
|
#define ARM64_STR_D_REG 0xFC206800U
|
||||||
|
#define ARM64_STR_Q_REG 0x3C206800U
|
||||||
|
|
||||||
|
/* Load/store pair */
|
||||||
|
#define ARM64_LDP_X 0xA9400000U
|
||||||
|
#define ARM64_LDP_X_PRE 0xA9C00000U
|
||||||
|
#define ARM64_LDP_X_POST 0xA8C00000U
|
||||||
|
#define ARM64_STP_X 0xA9000000U
|
||||||
|
#define ARM64_STP_X_PRE 0xA9800000U
|
||||||
|
#define ARM64_STP_X_POST 0xA8800000U
|
||||||
|
#define ARM64_LDP_D 0x6D400000U
|
||||||
|
#define ARM64_LDP_D_PRE 0x6DC00000U
|
||||||
|
#define ARM64_LDP_D_POST 0x6CC00000U
|
||||||
|
#define ARM64_STP_D 0x6D000000U
|
||||||
|
#define ARM64_STP_D_PRE 0x6D800000U
|
||||||
|
#define ARM64_STP_D_POST 0x6C800000U
|
||||||
|
|
||||||
|
/* Branch instructions */
|
||||||
|
#define ARM64_B 0x14000000U
|
||||||
|
#define ARM64_BL 0x94000000U
|
||||||
|
#define ARM64_BR 0xD61F0000U
|
||||||
|
#define ARM64_BLR 0xD63F0000U
|
||||||
|
#define ARM64_RET 0xD65F0000U
|
||||||
|
|
||||||
|
/* Conditional branch */
|
||||||
|
#define ARM64_B_COND 0x54000000U
|
||||||
|
|
||||||
|
/* Compare and branch */
|
||||||
|
#define ARM64_CBZ 0x34000000U
|
||||||
|
#define ARM64_CBNZ 0x35000000U
|
||||||
|
|
||||||
|
/* System instructions */
|
||||||
|
#define ARM64_NOP 0xD503201FU
|
||||||
|
#define ARM64_ISB 0xD50330DFU
|
||||||
|
#define ARM64_DSB 0xD503309FU
|
||||||
|
#define ARM64_DMB 0xD50330BFU
|
||||||
|
#define ARM64_MRS 0xD5380000U
|
||||||
|
#define ARM64_MSR 0xD5180000U
|
||||||
|
#define ARM64_MRS_FPCR 0xD53B4400U
|
||||||
|
#define ARM64_MRS_FPSR 0xD53B4420U
|
||||||
|
#define ARM64_MSR_FPCR 0xD51B4400U
|
||||||
|
#define ARM64_MSR_FPSR 0xD51B4420U
|
||||||
|
|
||||||
|
/* Shifts (register) */
|
||||||
|
#define ARM64_LSL_REG 0x1AC02000U
|
||||||
|
#define ARM64_LSR_REG 0x1AC02400U
|
||||||
|
#define ARM64_ASR_REG 0x1AC02800U
|
||||||
|
#define ARM64_ROR_REG 0x1AC02C00U
|
||||||
|
|
||||||
|
/* Shifts (immediate - UBFM/SBFM) */
|
||||||
|
#define ARM64_LSL_IMM 0xD3400000U
|
||||||
|
#define ARM64_LSR_IMM 0xD3400000U
|
||||||
|
#define ARM64_LSR_IMM_32 0x53000000U /* 32-bit LSR base */
|
||||||
|
#define ARM64_ASR_IMM 0x93400000U
|
||||||
|
|
||||||
|
/* Shifted register encoding for ORR/AND/EOR */
|
||||||
|
#define ARM64_SHIFT_LSL(imm) (((uint32_t)(imm) & 63) << 10)
|
||||||
|
#define ARM64_SHIFT_LSR(imm) (0x00200000U | (((uint32_t)(imm) & 63) << 10))
|
||||||
|
#define ARM64_SHIFT_ASR(imm) (0x00400000U | (((uint32_t)(imm) & 63) << 10))
|
||||||
|
#define ARM64_SHIFT_ROR(imm) (0x00600000U | (((uint32_t)(imm) & 63) << 10))
|
||||||
|
|
||||||
|
/* UBFM/SBFM immediate fields (for LSL/LSR/ASR immediate aliases) */
|
||||||
|
#define ARM64_IMM_R(r) (((uint32_t)(r) & 0x3F) << 16)
|
||||||
|
#define ARM64_IMM_S(s) (((uint32_t)(s) & 0x3F) << 10)
|
||||||
|
|
||||||
|
/* Extended register encoding */
|
||||||
|
#define ARM64_EXTEND_LSL(lsl) (((uint32_t)(lsl) & 7) << 10)
|
||||||
|
|
||||||
|
/* MOV (register) - ORR with zero register */
|
||||||
|
#define ARM64_MOV_REG 0x2A0003E0U
|
||||||
|
|
||||||
|
/* Address generation */
|
||||||
|
#define ARM64_ADRP 0x90000000U
|
||||||
|
#define ARM64_ADR 0x10000000U
|
||||||
|
|
||||||
|
/* Logical immediate */
|
||||||
|
#define ARM64_AND_IMM 0x12000000U
|
||||||
|
#define ARM64_ORR_IMM_BASE 0x32000000U
|
||||||
|
#define ARM64_EOR_IMM 0x52000000U
|
||||||
|
#define ARM64_ANDS_IMM 0x72000000U
|
||||||
|
#define ARM64_ORR_IMM 0x320003E0U /* ORR immediate alias with Rn = XZR/WZR */
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
/* ARM64 instruction encoding helper macros */
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
/* Register field encodings */
|
||||||
|
#define ARM64_RD(r) ((uint32_t)(r) & 0x1FU)
|
||||||
|
#define ARM64_RN(r) (((uint32_t)(r) & 0x1FU) << 5)
|
||||||
|
#define ARM64_RM(r) (((uint32_t)(r) & 0x1FU) << 16)
|
||||||
|
#define ARM64_RT(r) ((uint32_t)(r) & 0x1FU)
|
||||||
|
#define ARM64_RT2(r) (((uint32_t)(r) & 0x1FU) << 10)
|
||||||
|
|
||||||
|
/* Immediate field encodings */
|
||||||
|
#define ARM64_IMM12(v) (((uint32_t)(v) & 0xFFFU) << 10)
|
||||||
|
#define ARM64_IMM7(v) (((uint32_t)(v) & 0x7FU) << 15)
|
||||||
|
#define ARM64_IMM14(v) (((uint32_t)(v) & 0x3FFFU) << 5)
|
||||||
|
#define ARM64_IMM16(v) (((uint32_t)(v) & 0xFFFFU) << 5)
|
||||||
|
#define ARM64_IMM_HW(v, hw) (((uint32_t)(v) & 0xFFFFU) << 5 | (((hw) & 3) << 21))
|
||||||
|
|
||||||
|
/* Shift and size encodings */
|
||||||
|
#define ARM64_SIZE(s) (((uint32_t)(s) & 3) << 30)
|
||||||
|
#define ARM64_SF(s) (((uint32_t)(s) & 1) << 31)
|
||||||
|
#define ARM64_S(v) (((uint32_t)(v) & 1) << 29)
|
||||||
|
#define ARM64_N(v) (((uint32_t)(v) & 1) << 22)
|
||||||
|
#define ARM64_SH(v) (((uint32_t)(v) & 1) << 22)
|
||||||
|
|
||||||
|
/* Condition code encoding */
|
||||||
|
#define ARM64_COND(c) ((uint32_t)(c) & 0xFU)
|
||||||
|
|
||||||
|
/* Branch offset encoding */
|
||||||
|
#define ARM64_OFFSET26(v) (((uint32_t)(v) >> 2) & 0x3FFFFFFU)
|
||||||
|
#define ARM64_OFFSET19(v) (((uint32_t)(v) >> 2) & 0x7FFFFU)
|
||||||
|
#define ARM64_OFFSET14(v) (((uint32_t)(v) >> 2) & 0x3FFFU)
|
||||||
|
|
||||||
|
/* Special register field (for MRS/MSR) */
|
||||||
|
#undef ARM64_SYSREG
|
||||||
|
#define ARM64_SYSREG(op0, op1, crn, crm, op2) \
|
||||||
|
((((op0) & 3) << 19) | (((op1) & 7) << 16) | \
|
||||||
|
(((crn) & 15) << 12) | (((crm) & 15) << 8) | (((op2) & 7) << 5))
|
||||||
|
|
||||||
|
/* Barrier option encoding */
|
||||||
|
#define ARM64_ISB_OPTION(opt) (((uint32_t)(opt) & 0xFU) << 8)
|
||||||
|
#define ARM64_DSB_OPTION(opt) (((uint32_t)(opt) & 0xFU) << 8)
|
||||||
|
#define ARM64_DMB_OPTION(opt) (((uint32_t)(opt) & 0xFU) << 8)
|
||||||
|
|
||||||
|
/* Additional opcodes for code generator - VERIFIED */
|
||||||
|
/* Note: Many of these are specific instances, not general templates */
|
||||||
|
|
||||||
|
/* Floating-point move - VERIFIED */
|
||||||
|
#define ARM64_FMOV_D_S 0x1E604000U /* FMOV Dd,Dn (scalar) */
|
||||||
|
#define ARM64_FMOV_X_D 0x9E660000U /* FMOV Xd,Dn (general to FP) */
|
||||||
|
#define ARM64_FMOV_W_S 0x1E260000U /* FMOV Wd,Sn (general to FP) */
|
||||||
|
/* ARM64_FMOV_S_D removed: 0x4EA01C00 is SIMD vector, not scalar FMOV */
|
||||||
|
/* Use 0x1E204000 for FMOV Sd,Sn or 0x1E604000 variant for cross-size */
|
||||||
|
|
||||||
|
/* FMOV variants for code generator */
|
||||||
|
#define ARM64_FMOV_SCALAR 0x1E604000U /* FMOV Dd, Dn (scalar FP) */
|
||||||
|
#define ARM64_FMOV_XD 0x9E660000U /* FMOV Xd, Dn (FP to GP 64-bit) */
|
||||||
|
#define ARM64_FMOV_WS 0x1E260000U /* FMOV Wd, Sn (FP to GP 32-bit) */
|
||||||
|
|
||||||
|
/* MOV vector (ORR vector register alias) */
|
||||||
|
#define ARM64_MOV_V16B 0x4EA01C00U /* MOV Vd.16B, Vn.16B (ORR vector, Rm=Rn alias) */
|
||||||
|
|
||||||
|
/* Load/Store SIMD&FP - Base opcodes (register fields must be filled in) */
|
||||||
|
#define ARM64_STR_Q_PRE 0x3C800000U /* STR Q pre-index base */
|
||||||
|
#define ARM64_LDR_Q_POST 0x3CC00000U /* LDR Q post-index base */
|
||||||
|
|
||||||
|
/* LDPSW - Base opcode (register fields must be filled in) */
|
||||||
|
/* Use gen_ldst_pair() with appropriate mode for LDPSW */
|
||||||
|
/* Base encodings: 0x68C00000 (post), 0x69400000 (offset), 0x69C00000 (pre) */
|
||||||
|
|
||||||
|
/* ARM64_LDR_S_SIMD removed: 0x0D00801C is not a standard encoding */
|
||||||
|
/* Use ARM64_LDR_S (0xBD400000) for scalar S or ARM64_LDR_S_VEC for SIMD */
|
||||||
|
|
||||||
|
/* MOV between SIMD and general - Use UMOV/SMOV instead */
|
||||||
|
/* ARM64_MOV_V_D removed: 0x4E083C00 is UMOV/SMOV encoding */
|
||||||
|
/* Use appropriate UMOV/SMOV base: 0x0E002C00/0x0E003C00 (32-bit) */
|
||||||
|
/* or 0x4E002C00/0x4E003C00 (64-bit) */
|
||||||
|
|
||||||
|
/* Verified from previous section */
|
||||||
|
#define ARM64_FCMP 0x1E202008U /* FCMP with zero */
|
||||||
|
#define ARM64_SDIV 0x1AC00C00U /* SDIV (32-bit) */
|
||||||
|
|
||||||
|
/* EXTR (Extract) */
|
||||||
|
#define ARM64_EXTR 0x13800000U /* EXTR Wd, Wn, Wm, #imm (32-bit) */
|
||||||
|
#define ARM64_EXTR64 0x93C00000U /* EXTR Xd, Xn, Xm, #imm (64-bit) */
|
||||||
|
|
||||||
|
/* ARM64_MUL removed - use ARM64_MUL_REG with gen_dp_reg() */
|
||||||
|
|
||||||
|
/* ORR shifted - Base opcodes (register fields must be filled in) */
|
||||||
|
#define ARM64_ORR_REG_LSL 0x2A000000U /* ORR (shifted register) base */
|
||||||
|
/* ARM64_ORR_REG_LSL32 removed: use ARM64_ORR_REG_LSL with SF=1 */
|
||||||
|
/* ARM64_ORR_REG_MOV is duplicate of ARM64_MOV_REG */
|
||||||
|
|
||||||
|
/* LSR immediate - These are UBFM encodings, use gen_shift() instead */
|
||||||
|
/* Base UBFM encodings: 0x53000000 (W), 0xD3400000 (X) */
|
||||||
|
/* gen_shift() handles immr/imms encoding for LSR/LSL/ASR */
|
||||||
|
/* ARM64_LSR_W_8, ARM64_LSR_X_8, ARM64_LSR_X_16, ARM64_LSR_X_24 removed */
|
||||||
|
/* They are specific instances, not templates */
|
||||||
|
|
||||||
|
/* SUB shifted - Base opcode (use gen_sub_reg or asm handler) */
|
||||||
|
#define ARM64_SUB_REG_LSL 0xCB000000U /* SUB (shifted register) base */
|
||||||
|
|
||||||
|
/* Duplicates removed: ARM64_LDP_X, ARM64_B, ARM64_BL, ARM64_BR, ARM64_NOP */
|
||||||
|
/* These are already defined in their respective sections above */
|
||||||
85
c67-gen.c
85
c67-gen.c
@ -56,7 +56,7 @@
|
|||||||
#define RC_C67_B12 0x04000000
|
#define RC_C67_B12 0x04000000
|
||||||
#define RC_C67_B13 0x08000000
|
#define RC_C67_B13 0x08000000
|
||||||
#define RC_IRET RC_C67_A4 /* function return: integer register */
|
#define RC_IRET RC_C67_A4 /* function return: integer register */
|
||||||
#define RC_LRET RC_C67_A5 /* function return: second integer register */
|
#define RC_IRE2 RC_C67_A5 /* function return: second integer register */
|
||||||
#define RC_FRET RC_C67_A4 /* function return: float register */
|
#define RC_FRET RC_C67_A4 /* function return: float register */
|
||||||
|
|
||||||
/* pretty names for the registers */
|
/* pretty names for the registers */
|
||||||
@ -89,7 +89,7 @@ enum {
|
|||||||
|
|
||||||
/* return registers for function */
|
/* return registers for function */
|
||||||
#define REG_IRET TREG_C67_A4 /* single word int return register */
|
#define REG_IRET TREG_C67_A4 /* single word int return register */
|
||||||
#define REG_LRET TREG_C67_A5 /* second word return register (for long long) */
|
#define REG_IRE2 TREG_C67_A5 /* second word return register (for long long) */
|
||||||
#define REG_FRET TREG_C67_A4 /* float return register */
|
#define REG_FRET TREG_C67_A4 /* float return register */
|
||||||
|
|
||||||
/* defined if function parameters must be evaluated in reverse order */
|
/* defined if function parameters must be evaluated in reverse order */
|
||||||
@ -108,13 +108,20 @@ enum {
|
|||||||
/* maximum alignment (for aligned attribute support) */
|
/* maximum alignment (for aligned attribute support) */
|
||||||
#define MAX_ALIGN 8
|
#define MAX_ALIGN 8
|
||||||
|
|
||||||
|
#undef CONFIG_TCC_BCHECK
|
||||||
|
|
||||||
/******************************************************/
|
/******************************************************/
|
||||||
#else /* ! TARGET_DEFS_ONLY */
|
#else /* ! TARGET_DEFS_ONLY */
|
||||||
/******************************************************/
|
/******************************************************/
|
||||||
|
#define USING_GLOBALS
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
|
|
||||||
|
ST_DATA const char * const target_machine_defs =
|
||||||
|
"__C67__\0"
|
||||||
|
;
|
||||||
|
|
||||||
ST_DATA const int reg_classes[NB_REGS] = {
|
ST_DATA const int reg_classes[NB_REGS] = {
|
||||||
/* eax */ RC_INT | RC_FLOAT | RC_EAX,
|
/* eax */ RC_INT | RC_FLOAT | RC_EAX,
|
||||||
// only allow even regs for floats (allow for doubles)
|
// only allow even regs for floats (allow for doubles)
|
||||||
/* ecx */ RC_INT | RC_ECX,
|
/* ecx */ RC_INT | RC_ECX,
|
||||||
/* edx */ RC_INT | RC_INT_BSIDE | RC_FLOAT | RC_EDX,
|
/* edx */ RC_INT | RC_INT_BSIDE | RC_FLOAT | RC_EDX,
|
||||||
@ -226,11 +233,6 @@ void gsym_addr(int t, int a)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void gsym(int t)
|
|
||||||
{
|
|
||||||
gsym_addr(t, ind);
|
|
||||||
}
|
|
||||||
|
|
||||||
// these are regs that tcc doesn't really know about,
|
// these are regs that tcc doesn't really know about,
|
||||||
// but assign them unique values so the mapping routines
|
// but assign them unique values so the mapping routines
|
||||||
// can distinguish them
|
// can distinguish them
|
||||||
@ -369,7 +371,7 @@ int C67_map_D12(char *s)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void C67_asm(char *s, int a, int b, int c)
|
void C67_asm(const char *s, int a, int b, int c)
|
||||||
{
|
{
|
||||||
BOOL xpath;
|
BOOL xpath;
|
||||||
|
|
||||||
@ -1944,8 +1946,9 @@ void gfunc_call(int nb_args)
|
|||||||
// parameters are loaded and restored upon return (or if/when needed).
|
// parameters are loaded and restored upon return (or if/when needed).
|
||||||
|
|
||||||
/* generate function prolog of type 't' */
|
/* generate function prolog of type 't' */
|
||||||
void gfunc_prolog(CType * func_type)
|
void gfunc_prolog(Sym *func_sym)
|
||||||
{
|
{
|
||||||
|
CType *func_type = &func_sym->type;
|
||||||
int addr, align, size, func_call, i;
|
int addr, align, size, func_call, i;
|
||||||
Sym *sym;
|
Sym *sym;
|
||||||
CType *type;
|
CType *type;
|
||||||
@ -1955,8 +1958,6 @@ void gfunc_prolog(CType * func_type)
|
|||||||
addr = 8;
|
addr = 8;
|
||||||
/* if the function returns a structure, then add an
|
/* if the function returns a structure, then add an
|
||||||
implicit pointer parameter */
|
implicit pointer parameter */
|
||||||
func_vt = sym->type;
|
|
||||||
func_var = (sym->f.func_type == FUNC_ELLIPSIS);
|
|
||||||
if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
|
if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
|
||||||
func_vc = addr;
|
func_vc = addr;
|
||||||
addr += 4;
|
addr += 4;
|
||||||
@ -1967,7 +1968,7 @@ void gfunc_prolog(CType * func_type)
|
|||||||
/* define parameters */
|
/* define parameters */
|
||||||
while ((sym = sym->next) != NULL) {
|
while ((sym = sym->next) != NULL) {
|
||||||
type = &sym->type;
|
type = &sym->type;
|
||||||
sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), addr);
|
gfunc_set_param(sym, addr, 0);
|
||||||
size = type_size(type, &align);
|
size = type_size(type, &align);
|
||||||
size = (size + 3) & ~3;
|
size = (size + 3) & ~3;
|
||||||
|
|
||||||
@ -2035,6 +2036,16 @@ void gfunc_epilog(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ST_FUNC void gen_fill_nops(int bytes)
|
||||||
|
{
|
||||||
|
if ((bytes & 3))
|
||||||
|
tcc_error("alignment of code section not multiple of 4");
|
||||||
|
while (bytes > 0) {
|
||||||
|
C67_NOP(4);
|
||||||
|
bytes -= 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* generate a jump to a label */
|
/* generate a jump to a label */
|
||||||
int gjmp(int t)
|
int gjmp(int t)
|
||||||
{
|
{
|
||||||
@ -2067,15 +2078,13 @@ void gjmp_addr(int a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* generate a test. set 'inv' to invert test. Stack entry is popped */
|
/* generate a test. set 'inv' to invert test. Stack entry is popped */
|
||||||
int gtst(int inv, int t)
|
ST_FUNC int gjmp_cond(int op, int t)
|
||||||
{
|
{
|
||||||
int ind1, n;
|
int ind1;
|
||||||
int v, *p;
|
int inv = op & 1;
|
||||||
|
if (nocode_wanted)
|
||||||
|
return t;
|
||||||
|
|
||||||
v = vtop->r & VT_VALMASK;
|
|
||||||
if (nocode_wanted) {
|
|
||||||
;
|
|
||||||
} else if (v == VT_CMP) {
|
|
||||||
/* fast case : can jump directly since flags are set */
|
/* fast case : can jump directly since flags are set */
|
||||||
// C67 uses B2 sort of as flags register
|
// C67 uses B2 sort of as flags register
|
||||||
ind1 = ind;
|
ind1 = ind;
|
||||||
@ -2093,16 +2102,18 @@ int gtst(int inv, int t)
|
|||||||
C67_NOP(5);
|
C67_NOP(5);
|
||||||
t = ind1; //return where we need to patch
|
t = ind1; //return where we need to patch
|
||||||
|
|
||||||
} else if (v == VT_JMP || v == VT_JMPI) {
|
return t;
|
||||||
/* && or || optimization */
|
}
|
||||||
if ((v & 1) == inv) {
|
|
||||||
|
ST_FUNC int gjmp_append(int n0, int t)
|
||||||
|
{
|
||||||
|
if (n0) {
|
||||||
|
int n = n0, *p;
|
||||||
/* insert vtop->c jump list in t */
|
/* insert vtop->c jump list in t */
|
||||||
|
|
||||||
// I guess the idea is to traverse to the
|
// I guess the idea is to traverse to the
|
||||||
// null at the end of the list and store t
|
// null at the end of the list and store t
|
||||||
// there
|
// there
|
||||||
|
|
||||||
n = vtop->c.i;
|
|
||||||
while (n != 0) {
|
while (n != 0) {
|
||||||
p = (int *) (cur_text_section->data + n);
|
p = (int *) (cur_text_section->data + n);
|
||||||
|
|
||||||
@ -2112,14 +2123,8 @@ int gtst(int inv, int t)
|
|||||||
}
|
}
|
||||||
*p |= (t & 0xffff) << 7;
|
*p |= (t & 0xffff) << 7;
|
||||||
*(p + 1) |= ((t >> 16) & 0xffff) << 7;
|
*(p + 1) |= ((t >> 16) & 0xffff) << 7;
|
||||||
t = vtop->c.i;
|
t = n0;
|
||||||
|
|
||||||
} else {
|
|
||||||
t = gjmp(t);
|
|
||||||
gsym(vtop->c.i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
vtop--;
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2195,10 +2200,8 @@ void gen_opi(int op)
|
|||||||
ALWAYS_ASSERT(FALSE);
|
ALWAYS_ASSERT(FALSE);
|
||||||
|
|
||||||
vtop--;
|
vtop--;
|
||||||
if (op >= TOK_ULT && op <= TOK_GT) {
|
if (op >= TOK_ULT && op <= TOK_GT)
|
||||||
vtop->r = VT_CMP;
|
vset_VT_CMP(0x80);
|
||||||
vtop->c.i = op;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case '-':
|
case '-':
|
||||||
case TOK_SUBC1: /* sub with carry generation */
|
case TOK_SUBC1: /* sub with carry generation */
|
||||||
@ -2257,7 +2260,7 @@ void gen_opi(int op)
|
|||||||
call_func:
|
call_func:
|
||||||
vswap();
|
vswap();
|
||||||
/* call generic idiv function */
|
/* call generic idiv function */
|
||||||
vpush_global_sym(&func_old_type, t);
|
vpush_helper_func(t);
|
||||||
vrott(3);
|
vrott(3);
|
||||||
gfunc_call(2);
|
gfunc_call(2);
|
||||||
vpushi(0);
|
vpushi(0);
|
||||||
@ -2354,7 +2357,7 @@ void gen_opf(int op)
|
|||||||
} else {
|
} else {
|
||||||
ALWAYS_ASSERT(FALSE);
|
ALWAYS_ASSERT(FALSE);
|
||||||
}
|
}
|
||||||
vtop->r = VT_CMP; // tell TCC that result is in "flags" actually B2
|
vset_VT_CMP(0x80);
|
||||||
} else {
|
} else {
|
||||||
if (op == '+') {
|
if (op == '+') {
|
||||||
if ((ft & VT_BTYPE) == VT_DOUBLE) {
|
if ((ft & VT_BTYPE) == VT_DOUBLE) {
|
||||||
@ -2388,18 +2391,18 @@ void gen_opf(int op)
|
|||||||
// must call intrinsic DP floating point divide
|
// must call intrinsic DP floating point divide
|
||||||
vswap();
|
vswap();
|
||||||
/* call generic idiv function */
|
/* call generic idiv function */
|
||||||
vpush_global_sym(&func_old_type, TOK__divd);
|
vpush_helper_func(TOK__divd);
|
||||||
vrott(3);
|
vrott(3);
|
||||||
gfunc_call(2);
|
gfunc_call(2);
|
||||||
vpushi(0);
|
vpushi(0);
|
||||||
vtop->r = REG_FRET;
|
vtop->r = REG_FRET;
|
||||||
vtop->r2 = REG_LRET;
|
vtop->r2 = REG_IRE2;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// must call intrinsic SP floating point divide
|
// must call intrinsic SP floating point divide
|
||||||
vswap();
|
vswap();
|
||||||
/* call generic idiv function */
|
/* call generic idiv function */
|
||||||
vpush_global_sym(&func_old_type, TOK__divf);
|
vpush_helper_func(TOK__divf);
|
||||||
vrott(3);
|
vrott(3);
|
||||||
gfunc_call(2);
|
gfunc_call(2);
|
||||||
vpushi(0);
|
vpushi(0);
|
||||||
|
|||||||
14
c67-link.c
14
c67-link.c
@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
|
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
|
||||||
relocations, returns -1. */
|
relocations, returns -1. */
|
||||||
int code_reloc (int reloc_type)
|
ST_FUNC int code_reloc (int reloc_type)
|
||||||
{
|
{
|
||||||
switch (reloc_type) {
|
switch (reloc_type) {
|
||||||
case R_C60_32:
|
case R_C60_32:
|
||||||
@ -39,15 +39,13 @@ int code_reloc (int reloc_type)
|
|||||||
case R_C60_PLT32:
|
case R_C60_PLT32:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
tcc_error ("Unknown relocation type: %d", reloc_type);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns an enumerator to describe whether and when the relocation needs a
|
/* Returns an enumerator to describe whether and when the relocation needs a
|
||||||
GOT and/or PLT entry to be created. See tcc.h for a description of the
|
GOT and/or PLT entry to be created. See tcc.h for a description of the
|
||||||
different values. */
|
different values. */
|
||||||
int gotplt_entry_type (int reloc_type)
|
ST_FUNC int gotplt_entry_type (int reloc_type)
|
||||||
{
|
{
|
||||||
switch (reloc_type) {
|
switch (reloc_type) {
|
||||||
case R_C60_32:
|
case R_C60_32:
|
||||||
@ -64,14 +62,12 @@ int gotplt_entry_type (int reloc_type)
|
|||||||
case R_C60_GOT32:
|
case R_C60_GOT32:
|
||||||
return ALWAYS_GOTPLT_ENTRY;
|
return ALWAYS_GOTPLT_ENTRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
tcc_error ("Unknown relocation type: %d", reloc_type);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
|
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
|
||||||
{
|
{
|
||||||
tcc_error("C67 got not implemented");
|
tcc_error_noabort("C67 got not implemented");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,9 +91,7 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void relocate_init(Section *sr) {}
|
ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
||||||
|
|
||||||
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
|
||||||
{
|
{
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case R_C60_32:
|
case R_C60_32:
|
||||||
|
|||||||
787
configure
vendored
787
configure
vendored
@ -27,9 +27,9 @@ mandir=""
|
|||||||
infodir=""
|
infodir=""
|
||||||
sysroot=""
|
sysroot=""
|
||||||
cross_prefix=""
|
cross_prefix=""
|
||||||
|
os_release=""
|
||||||
cc="gcc"
|
cc="gcc"
|
||||||
ar="ar"
|
ar="ar"
|
||||||
strip="strip"
|
|
||||||
bigendian="no"
|
bigendian="no"
|
||||||
mingw32="no"
|
mingw32="no"
|
||||||
LIBSUF=".a"
|
LIBSUF=".a"
|
||||||
@ -40,224 +40,145 @@ tcc_libpaths=""
|
|||||||
tcc_crtprefix=""
|
tcc_crtprefix=""
|
||||||
tcc_elfinterp=""
|
tcc_elfinterp=""
|
||||||
triplet=
|
triplet=
|
||||||
tcc_lddir=
|
|
||||||
confvars=
|
confvars=
|
||||||
suggest="yes"
|
suggest="yes"
|
||||||
cpu=
|
|
||||||
cpuver=
|
|
||||||
gcc_major=0
|
gcc_major=0
|
||||||
gcc_minor=0
|
gcc_minor=0
|
||||||
|
cc_name="gcc"
|
||||||
|
ar_set=
|
||||||
|
cpu=
|
||||||
|
cpuver=
|
||||||
|
dwarf=
|
||||||
|
targetos=
|
||||||
|
build_cross=
|
||||||
|
quiet=
|
||||||
|
|
||||||
# OS specific
|
# use CC/AR from environment when set
|
||||||
targetos=`uname`
|
test -n "$CC" && cc="$CC"
|
||||||
case $targetos in
|
test -n "$AR" && ar="$AR"
|
||||||
Darwin)
|
|
||||||
confvars="$confvars OSX"
|
# set default CFLAGS if unset in environment
|
||||||
DLLSUF=".dylib"
|
test -z "$CFLAGS" && CFLAGS="-Wall -O2"
|
||||||
;;
|
|
||||||
MINGW*|MSYS*|CYGWIN*)
|
|
||||||
mingw32=yes
|
|
||||||
;;
|
|
||||||
DragonFly|OpenBSD|FreeBSD|NetBSD)
|
|
||||||
confvars="$confvars ldl=no"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# find source path
|
# find source path
|
||||||
source_path=${0%configure}
|
source_path=${0%configure}
|
||||||
source_path=${source_path%/}
|
source_path=${source_path%/}
|
||||||
source_path_used="yes"
|
|
||||||
if test -z "$source_path" -o "$source_path" = "." ; then
|
# $1: --OPTNAME=VALUE [, $2: NAME to assign-to instead of OPTNAME]
|
||||||
source_path=`pwd`
|
assign_opt() {
|
||||||
source_path_used="no"
|
set -- "${2:-${1%%=*}}" "${1#*=}" # [--OPT]NAME VALUE
|
||||||
fi
|
eval ${1#--}=\$2 # no risk of IFS/glob in [OPT]NAME
|
||||||
|
}
|
||||||
|
|
||||||
|
# succeed if $1 doesn't IFS-split funny (globs, spaces, ...)
|
||||||
|
good_split() {
|
||||||
|
set -- "$1" $1
|
||||||
|
test $# = 2 && test "$1" = "$2"
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1: NAME[=VALUE] succeed if confvars has NAME or NAME=* element
|
||||||
|
confvars_has() {
|
||||||
|
! case " $confvars " in *" ${1%%=*} "* | *" ${1%%=*}="*)
|
||||||
|
false
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# [multiple] NAME or NAME=VAL
|
||||||
|
confvars_set() {
|
||||||
|
for cv; do
|
||||||
|
good_split "$cv" || { echo "configure: ERROR: bad config '$cv'"; exit 1; }
|
||||||
|
confvars_has "$cv" && echo "configure: WARNING: duplicate config '$cv'"
|
||||||
|
confvars="$confvars $cv"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
for opt do
|
for opt do
|
||||||
eval opt=\"$opt\"
|
eval opt=\"$opt\"
|
||||||
case "$opt" in
|
case "$opt" in
|
||||||
--prefix=*) prefix=`echo $opt | cut -d '=' -f 2`
|
--prefix=*) assign_opt "$opt"
|
||||||
;;
|
;;
|
||||||
--exec-prefix=*) execprefix=`echo $opt | cut -d '=' -f 2`
|
--exec-prefix=*) assign_opt "$opt" execprefix
|
||||||
;;
|
;;
|
||||||
--tccdir=*) tccdir=`echo $opt | cut -d '=' -f 2`
|
--tccdir=*) assign_opt "$opt"
|
||||||
;;
|
;;
|
||||||
--bindir=*) bindir=`echo $opt | cut -d '=' -f 2`
|
--bindir=*) assign_opt "$opt"
|
||||||
;;
|
;;
|
||||||
--libdir=*) libdir=`echo $opt | cut -d '=' -f 2`
|
--libdir=*) assign_opt "$opt"
|
||||||
;;
|
;;
|
||||||
--includedir=*) includedir=`echo $opt | cut -d '=' -f 2`
|
--includedir=*) assign_opt "$opt"
|
||||||
;;
|
;;
|
||||||
--sharedir=*) sharedir=`echo $opt | cut -d '=' -f 2`
|
--sharedir=*) assign_opt "$opt"
|
||||||
;;
|
;;
|
||||||
--mandir=*) mandir=`echo $opt | cut -d '=' -f 2`
|
--mandir=*) assign_opt "$opt"
|
||||||
;;
|
;;
|
||||||
--infodir=*) infodir=`echo $opt | cut -d '=' -f 2`
|
--infodir=*) assign_opt "$opt"
|
||||||
;;
|
;;
|
||||||
--docdir=*) docdir=`echo $opt | cut -d '=' -f 2`
|
--docdir=*) assign_opt "$opt"
|
||||||
;;
|
;;
|
||||||
--sysroot=*) sysroot=`echo $opt | cut -d '=' -f 2`
|
--sysroot=*) assign_opt "$opt"
|
||||||
;;
|
;;
|
||||||
--source-path=*) source_path=`echo $opt | cut -d '=' -f 2`
|
--targetos=*) assign_opt "$opt"
|
||||||
;;
|
;;
|
||||||
--cross-prefix=*) cross_prefix=`echo $opt | cut -d '=' -f 2`
|
--source-path=*) assign_opt "$opt" source_path
|
||||||
;;
|
;;
|
||||||
--cc=*) cc=`echo $opt | cut -d '=' -f 2`
|
--cross-prefix=*) assign_opt "$opt" cross_prefix
|
||||||
;;
|
;;
|
||||||
--ar=*) ar=`echo $opt | cut -d '=' -f 2`
|
--os-release=*) assign_opt "$opt" os_release
|
||||||
;;
|
;;
|
||||||
--extra-cflags=*) CFLAGS="${opt#--extra-cflags=}"
|
--cc=*) assign_opt "$opt"
|
||||||
;;
|
;;
|
||||||
--extra-ldflags=*) LDFLAGS="${opt#--extra-ldflags=}"
|
--ar=*) assign_opt "$opt" ; ar_set="yes"
|
||||||
;;
|
;;
|
||||||
--extra-libs=*) extralibs="${opt#--extra-libs=}"
|
--extra-cflags=*) assign_opt "$opt" CFLAGS
|
||||||
;;
|
;;
|
||||||
--sysincludepaths=*) tcc_sysincludepaths=`echo $opt | cut -d '=' -f 2`
|
--extra-ldflags=*) assign_opt "$opt" LDFLAGS
|
||||||
;;
|
;;
|
||||||
--libpaths=*) tcc_libpaths=`echo $opt | cut -d '=' -f 2`
|
--extra-libs=*) assign_opt "$opt" extralibs
|
||||||
;;
|
;;
|
||||||
--crtprefix=*) tcc_crtprefix=`echo $opt | cut -d '=' -f 2`
|
--sysincludepaths=*) assign_opt "$opt" tcc_sysincludepaths
|
||||||
;;
|
;;
|
||||||
--elfinterp=*) tcc_elfinterp=`echo $opt | cut -d '=' -f 2`
|
--libpaths=*) assign_opt "$opt" tcc_libpaths
|
||||||
;;
|
;;
|
||||||
--triplet=*) triplet=`echo $opt | cut -d '=' -f 2`
|
--crtprefix=*) assign_opt "$opt" tcc_crtprefix
|
||||||
;;
|
;;
|
||||||
--cpu=*) cpu=`echo $opt | cut -d '=' -f 2`
|
--elfinterp=*) assign_opt "$opt" tcc_elfinterp
|
||||||
;;
|
;;
|
||||||
--enable-cross) confvars="$confvars cross"
|
--triplet=*) assign_opt "$opt"
|
||||||
;;
|
;;
|
||||||
--disable-static) confvars="$confvars static=no"
|
--cpu=*) assign_opt "$opt"
|
||||||
;;
|
;;
|
||||||
--enable-static) confvars="$confvars static"
|
--dwarf=*) confvars_set "dwarf=${opt#*=}"
|
||||||
;;
|
;;
|
||||||
--disable-rpath) confvars="$confvars rpath=no"
|
--enable-cross) confvars_set cross
|
||||||
;;
|
;;
|
||||||
--strip-binaries) confvars="$confvars strip"
|
--disable-static) confvars_set static=no
|
||||||
;;
|
;;
|
||||||
--with-libgcc) confvars="$confvars libgcc"
|
--enable-static) confvars_set static
|
||||||
;;
|
;;
|
||||||
--with-selinux) confvars="$confvars selinux"
|
--disable-rpath) confvars_set rpath=no
|
||||||
;;
|
;;
|
||||||
--config-mingw32*) mingw32=$(echo "$opt=yes" | cut -d '=' -f 2)
|
--debug) confvars_set debug
|
||||||
;;
|
;;
|
||||||
--config-*) confvars="$confvars ${opt#--config-}"; suggest="no"
|
--with-selinux) confvars_set selinux
|
||||||
|
;;
|
||||||
|
--tcc-switches=*) assign_opt "$opt" tcc_switches
|
||||||
|
;;
|
||||||
|
--config-mingw32) mingw32=yes
|
||||||
|
;;
|
||||||
|
--config-mingw32=*) assign_opt "$opt" mingw32
|
||||||
|
;;
|
||||||
|
--config-*) confvars_set "${opt#--config-}"; suggest="no"
|
||||||
;;
|
;;
|
||||||
--help|-h) show_help="yes"
|
--help|-h) show_help="yes"
|
||||||
;;
|
;;
|
||||||
|
-q) quiet=yes
|
||||||
|
;;
|
||||||
*) echo "configure: WARNING: unrecognized option $opt"
|
*) echo "configure: WARNING: unrecognized option $opt"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
if test -z "$cpu" ; then
|
show_help() {
|
||||||
if test -n "$ARCH" ; then
|
|
||||||
cpu="$ARCH"
|
|
||||||
else
|
|
||||||
cpu=`uname -m`
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
case "$cpu" in
|
|
||||||
x86|i386|i486|i586|i686|i86pc|BePC|i686-AT386)
|
|
||||||
cpu="i386"
|
|
||||||
;;
|
|
||||||
x86_64|amd64|x86-64)
|
|
||||||
cpu="x86_64"
|
|
||||||
;;
|
|
||||||
arm*)
|
|
||||||
case "$cpu" in
|
|
||||||
arm|armv4l)
|
|
||||||
cpuver=4
|
|
||||||
;;
|
|
||||||
armv5tel|armv5tejl)
|
|
||||||
cpuver=5
|
|
||||||
;;
|
|
||||||
armv6j|armv6l)
|
|
||||||
cpuver=6
|
|
||||||
;;
|
|
||||||
armv7a|armv7l)
|
|
||||||
cpuver=7
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
cpu="arm"
|
|
||||||
;;
|
|
||||||
aarch64)
|
|
||||||
cpu="aarch64"
|
|
||||||
;;
|
|
||||||
alpha)
|
|
||||||
cpu="alpha"
|
|
||||||
;;
|
|
||||||
"Power Macintosh"|ppc|ppc64)
|
|
||||||
cpu="ppc"
|
|
||||||
;;
|
|
||||||
mips)
|
|
||||||
cpu="mips"
|
|
||||||
;;
|
|
||||||
s390)
|
|
||||||
cpu="s390"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Unsupported CPU"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Checking for CFLAGS
|
|
||||||
if test -z "$CFLAGS"; then
|
|
||||||
CFLAGS="-Wall -g -O2"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$mingw32" = "yes" ; then
|
|
||||||
if test "$source_path_used" = "no"; then
|
|
||||||
source_path="."
|
|
||||||
fi
|
|
||||||
if test "$cc" = gcc; then
|
|
||||||
test -z "$LDFLAGS" && LDFLAGS="-static"
|
|
||||||
fi
|
|
||||||
test -z "$prefix" && prefix="C:/Program Files/tcc"
|
|
||||||
test -z "$tccdir" && tccdir="${prefix}"
|
|
||||||
test -z "$bindir" && bindir="${tccdir}"
|
|
||||||
test -z "$docdir" && docdir="${tccdir}/doc"
|
|
||||||
test -z "$libdir" && libdir="${tccdir}/libtcc"
|
|
||||||
confvars="$confvars WIN32"
|
|
||||||
LIBSUF=".lib"
|
|
||||||
EXESUF=".exe"
|
|
||||||
DLLSUF=".dll"
|
|
||||||
else
|
|
||||||
if test -z "$prefix" ; then
|
|
||||||
prefix="/usr/local"
|
|
||||||
fi
|
|
||||||
if test -z "$sharedir" ; then
|
|
||||||
sharedir="${prefix}/share"
|
|
||||||
fi
|
|
||||||
if test x"$execprefix" = x""; then
|
|
||||||
execprefix="${prefix}"
|
|
||||||
fi
|
|
||||||
if test x"$libdir" = x""; then
|
|
||||||
libdir="${execprefix}/lib"
|
|
||||||
fi
|
|
||||||
if test x"$bindir" = x""; then
|
|
||||||
bindir="${execprefix}/bin"
|
|
||||||
fi
|
|
||||||
if test x"$docdir" = x""; then
|
|
||||||
docdir="${sharedir}/doc"
|
|
||||||
fi
|
|
||||||
if test x"$mandir" = x""; then
|
|
||||||
mandir="${sharedir}/man"
|
|
||||||
fi
|
|
||||||
if test x"$infodir" = x""; then
|
|
||||||
infodir="${sharedir}/info"
|
|
||||||
fi
|
|
||||||
if test x"$tccdir" = x""; then
|
|
||||||
tccdir="${libdir}/tcc"
|
|
||||||
fi
|
|
||||||
if test x"$includedir" = x""; then
|
|
||||||
includedir="${prefix}/include"
|
|
||||||
fi
|
|
||||||
fi # mingw32
|
|
||||||
|
|
||||||
if test x"$show_help" = "xyes" ; then
|
|
||||||
cat << EOF
|
cat << EOF
|
||||||
Usage: configure [options]
|
Usage: configure [options]
|
||||||
Options: [defaults in brackets after descriptions]
|
Options: [defaults in brackets after descriptions]
|
||||||
@ -275,103 +196,346 @@ Standard options:
|
|||||||
--docdir=DIR documentation in DIR [SHAREDIR/doc/tcc]
|
--docdir=DIR documentation in DIR [SHAREDIR/doc/tcc]
|
||||||
--mandir=DIR man documentation in DIR [SHAREDIR/man]
|
--mandir=DIR man documentation in DIR [SHAREDIR/man]
|
||||||
--infodir=DIR info documentation in DIR [SHAREDIR/info]
|
--infodir=DIR info documentation in DIR [SHAREDIR/info]
|
||||||
|
-q be quiet
|
||||||
|
|
||||||
Advanced options (experts only):
|
Advanced options (experts only):
|
||||||
--source-path=PATH path of source code [$source_path]
|
--source-path=PATH path of source code [$source_path]
|
||||||
--cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]
|
--sysroot=PREFIX prepend PREFIX to library/include paths [$sysroot]
|
||||||
--sysroot=PREFIX prepend PREFIX to library/include paths []
|
|
||||||
--cc=CC use C compiler CC [$cc]
|
--cc=CC use C compiler CC [$cc]
|
||||||
--ar=AR create archives using AR [$ar]
|
--ar=AR create archives using AR [$ar]
|
||||||
--extra-cflags= specify compiler flags [$CFLAGS]
|
--extra-cflags= specify compiler flags [$CFLAGS]
|
||||||
--extra-ldflags= specify linker options []
|
--extra-ldflags= specify linker options [$LDFLAGS]
|
||||||
--cpu=CPU CPU [$cpu]
|
|
||||||
--strip-binaries strip symbol tables from resulting binaries
|
--debug include debug info with resulting binaries
|
||||||
--disable-static make libtcc.so instead of libtcc.a
|
--disable-static make libtcc.so instead of libtcc.a
|
||||||
--enable-static make libtcc.a instead of libtcc.dll (win32)
|
--enable-static make libtcc.a instead of libtcc.dll (win32)
|
||||||
--disable-rpath disable use of -rpath with the above
|
--disable-rpath disable use of -rpath with libtcc.so
|
||||||
--with-libgcc use libgcc_s.so.1 instead of libtcc1.a
|
--with-selinux use mmap for executable memory (tcc -run)
|
||||||
--enable-cross build cross compilers
|
--enable-cross build all cross compilers (see also 'make help')
|
||||||
--with-selinux use mmap for executable memory (with tcc -run)
|
|
||||||
--sysincludepaths=... specify system include paths, colon separated
|
--sysincludepaths=... specify system include paths, colon separated
|
||||||
--libpaths=... specify system library paths, colon separated
|
--libpaths=... specify system library paths, colon separated
|
||||||
--crtprefix=... specify locations of crt?.o, colon separated
|
--crtprefix=... specify locations of crt?.o, colon separated
|
||||||
--elfinterp=... specify elf interpreter
|
--elfinterp=... specify elf interpreter
|
||||||
--triplet=... specify system library/include directory triplet
|
--triplet=... specify system library/include directory triplet
|
||||||
--config-uClibc,-musl,-mingw32... enable system specific configurations
|
--tcc-switches=... specify implicit switches passed to tcc
|
||||||
|
|
||||||
|
--config-uClibc,-musl enable system specific configurations
|
||||||
|
--config-mingw32[=yes|no] build on windows using msys, busybox, etc.
|
||||||
|
--config-backtrace=no disable stack backtraces (with -run or -bt)
|
||||||
|
--config-bcheck=no disable bounds checker (-b)
|
||||||
|
--config-predefs=no do not compile tccdefs.h, instead just include
|
||||||
|
--config-new_macho=no|yes force apple object format (autodetect osx <= 10)
|
||||||
|
--config-new_dtags=yes use new ELF DTAGs (DT_RUNPATH instead of DT_RPATH)
|
||||||
|
--config-codesign=no do not use codesign on apple to sign executables
|
||||||
|
--config-dwarf=x use dwarf debug info instead of stabs (x=2..5)
|
||||||
|
--config-pie let tcc generate position independent executables
|
||||||
|
|
||||||
|
Cross build options (experimental):
|
||||||
|
--cpu=CPU target CPU [$cpu]
|
||||||
|
--targetos=... target OS (Darwin,WIN32,Android/Termux) [$targetos]
|
||||||
|
--os-release=x.y.z target os release x.y.z [$os_release] (with BSD systems)
|
||||||
|
--cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]
|
||||||
EOF
|
EOF
|
||||||
#echo "NOTE: The object files are build at the place where configure is launched"
|
|
||||||
exit 1
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
default() # set variable unless already set and not empty
|
||||||
|
{
|
||||||
|
test -n "$2" && eval : \${$1:=\$2} # ': ${foo:=$2}'
|
||||||
|
}
|
||||||
|
|
||||||
|
default_conf() # add one config to confvars unless already present
|
||||||
|
{
|
||||||
|
confvars_has "$1" || confvars_set "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
if test -z "${source_path#.}" ; then
|
||||||
|
source_path=$(pwd)
|
||||||
|
source_path_used="no"
|
||||||
|
else
|
||||||
|
source_path_used="yes"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cc="${cross_prefix}${cc}"
|
# OS specific
|
||||||
ar="${cross_prefix}${ar}"
|
buildos=$(uname)
|
||||||
strip="${cross_prefix}${strip}"
|
cpu_sys=$(uname -m)
|
||||||
|
default os_release "$(uname -r)"
|
||||||
|
|
||||||
if test -z "$cross_prefix" ; then
|
case $buildos in
|
||||||
CONFTEST=./conftest$EXESUF
|
Windows_NT|MINGW*|MSYS*|CYGWIN*)
|
||||||
if ! $cc -o $CONFTEST $source_path/conftest.c 2>/dev/null ; then
|
buildos="WIN32"
|
||||||
|
case "$MSYSTEM" in
|
||||||
|
MINGW32) cpu_sys=i386 ;;
|
||||||
|
MINGW64) cpu_sys=x86_64 ;;
|
||||||
|
CLANGARM64|MINGW_ARM64) cpu_sys=arm64 ;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
Linux)
|
||||||
|
if test "$(uname -o)" = "Android"; then
|
||||||
|
buildos=Android
|
||||||
|
if test -n "$TERMUX_VERSION"; then
|
||||||
|
buildos=Termux
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if test "$mingw32" = "yes"; then
|
||||||
|
default targetos WIN32
|
||||||
|
else
|
||||||
|
default targetos "$buildos"
|
||||||
|
fi
|
||||||
|
|
||||||
|
default cpu "$cpu_sys"
|
||||||
|
|
||||||
|
# check for crpss build
|
||||||
|
if test "$cpu" != "$cpu_sys" ||
|
||||||
|
test "$targetos" != "$buildos" ||
|
||||||
|
test -n "$cross_prefix"
|
||||||
|
then
|
||||||
|
build_cross="yes"
|
||||||
|
cc="${cross_prefix}${cc}"
|
||||||
|
ar="${cross_prefix}${ar}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$cpu" in
|
||||||
|
x86|i386|i486|i586|i686|i86pc|BePC|i686-AT386)
|
||||||
|
cpu="i386"
|
||||||
|
;;
|
||||||
|
x86_64|amd64|x86-64)
|
||||||
|
cpu="x86_64"
|
||||||
|
;;
|
||||||
|
evbarm)
|
||||||
|
case "`uname -p`" in
|
||||||
|
aarch64|arm64)
|
||||||
|
cpu="arm64"
|
||||||
|
;;
|
||||||
|
earmv*)
|
||||||
|
cpu="arm"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
aarch64|arm64|evbarm)
|
||||||
|
cpu="arm64"
|
||||||
|
;;
|
||||||
|
arm*)
|
||||||
|
case "$cpu" in
|
||||||
|
arm|armv4l)
|
||||||
|
cpuver=4
|
||||||
|
;;
|
||||||
|
armv5tel|armv5tejl)
|
||||||
|
cpuver=5
|
||||||
|
;;
|
||||||
|
armv6j|armv6l)
|
||||||
|
cpuver=6
|
||||||
|
;;
|
||||||
|
armv7|armv7a|armv7l)
|
||||||
|
cpuver=7
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
cpu="arm"
|
||||||
|
;;
|
||||||
|
alpha)
|
||||||
|
cpu="alpha"
|
||||||
|
;;
|
||||||
|
"Power Macintosh"|ppc|ppc64)
|
||||||
|
cpu="ppc"
|
||||||
|
;;
|
||||||
|
mips)
|
||||||
|
cpu="mips"
|
||||||
|
;;
|
||||||
|
s390)
|
||||||
|
cpu="s390"
|
||||||
|
;;
|
||||||
|
riscv64)
|
||||||
|
cpu="riscv64"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unsupported CPU"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
case $targetos in
|
||||||
|
Darwin)
|
||||||
|
confvars_set OSX dwarf=4
|
||||||
|
default_conf "codesign"
|
||||||
|
DLLSUF=".dylib"
|
||||||
|
if test -z "$build_cross"; then
|
||||||
|
cc=`command -v cc`
|
||||||
|
cc=`readlink $cc || echo clang`
|
||||||
|
tcc_usrinclude="`xcrun --show-sdk-path`/usr/include"
|
||||||
|
default tcc_sysincludepaths "{B}/include:$tcc_usrinclude"
|
||||||
|
if test "${confvars%new_macho*}" = "${confvars}"; then
|
||||||
|
# if new_macho was not specified and (known) ver <= 10, use old (=no)
|
||||||
|
osxver=$(sw_vers -productVersion 2>/dev/null) # X.Y.Z
|
||||||
|
osxver=${osxver%%.*} # major version (or empty on sw_vers error)
|
||||||
|
[ "${osxver:-11}" -ge 11 ] || confvars_set new_macho=no
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# on OSX M1 with --cpu=x86_64, build a tcc to run under rosetta entirely
|
||||||
|
if test "$cpu" = x86_64 && test "$cpu_sys" = arm64; then
|
||||||
|
CFLAGS="$CFLAGS -arch $cpu"
|
||||||
|
LDFLAGS="$LDFLAGS -arch $cpu"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
DragonFly|OpenBSD|FreeBSD|NetBSD)
|
||||||
|
confvars_set BSD ldl=no
|
||||||
|
;;
|
||||||
|
Android|Termux)
|
||||||
|
if test "$targetos" = "Termux"; then
|
||||||
|
targetos=Android
|
||||||
|
default sysroot "/data/data/com.termux/files/usr"
|
||||||
|
else
|
||||||
|
default sysroot "/usr"
|
||||||
|
fi
|
||||||
|
default prefix "${sysroot}"
|
||||||
|
confvars_set Android new_dtags rpath=no dwarf=4
|
||||||
|
test "${cpu}" != "i386" && confvars_set pie
|
||||||
|
default_conf "static=no"
|
||||||
|
case "$cpu" in
|
||||||
|
arm) default triplet "arm-linux-androideabi"; cpuver=7 ;;
|
||||||
|
arm64) default triplet "aarch64-linux-android" ;;
|
||||||
|
x86_64) default triplet "x86_64-linux-android" ;;
|
||||||
|
i386) default triplet "i686-linux-android" ;;
|
||||||
|
esac
|
||||||
|
test "${cpu%64}" != "${cpu}" && S="64" || S=""
|
||||||
|
default tcc_sysincludepaths "{B}/include:{R}/include:{R}/include/${triplet}"
|
||||||
|
default tcc_libpaths "{B}:{R}/lib:/system/lib${S}"
|
||||||
|
default tcc_crtprefix "{R}/lib"
|
||||||
|
default tcc_elfinterp "/system/bin/linker${S}"
|
||||||
|
default tcc_switches "-Wl,-rpath=$sysroot/lib"
|
||||||
|
;;
|
||||||
|
WIN32)
|
||||||
|
mingw32="yes"
|
||||||
|
confvars="WIN32 $confvars" # WIN32 intentionally first (commit 729918ef)
|
||||||
|
default prefix "C:/Program Files/tcc"
|
||||||
|
default tccdir "${prefix}"
|
||||||
|
default bindir "${tccdir}"
|
||||||
|
default docdir "${tccdir}/doc"
|
||||||
|
default libdir "${tccdir}/libtcc"
|
||||||
|
# set tccdir at runtime from executable path
|
||||||
|
test "$tccdir" = "$bindir" && tccdir_auto="yes"
|
||||||
|
# chech $cc to avoid mingw gcc dependencies such as 'libgcc_s_dw2-1.dll'
|
||||||
|
# (no confirmed $cc_name yet, and also will never have if cross compiling)
|
||||||
|
test "${cc%gcc*}" = "$cc" || default LDFLAGS "-static"
|
||||||
|
LIBSUF=".lib"
|
||||||
|
EXESUF=".exe"
|
||||||
|
DLLSUF=".dll"
|
||||||
|
if test "$source_path_used" = "no"; then
|
||||||
|
source_path="."
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if test "$mingw32" = "no"; then
|
||||||
|
default prefix "/usr/local"
|
||||||
|
default execprefix "${prefix}"
|
||||||
|
default libdir "${execprefix}/lib"
|
||||||
|
default bindir "${execprefix}/bin"
|
||||||
|
default tccdir "${libdir}/tcc"
|
||||||
|
default includedir "${prefix}/include"
|
||||||
|
default sharedir "${prefix}/share"
|
||||||
|
default docdir "${sharedir}/doc"
|
||||||
|
default mandir "${sharedir}/man"
|
||||||
|
default infodir "${sharedir}/info"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test x"$show_help" = "xyes" ; then
|
||||||
|
show_help
|
||||||
|
fi
|
||||||
|
|
||||||
|
CONFTEST=./conftest$EXESUF
|
||||||
|
if test -z "$cross_prefix" \
|
||||||
|
&& $cc -o $CONFTEST "$source_path/conftest.c" \
|
||||||
|
&& $CONFTEST 2>/dev/null; then
|
||||||
|
cc_name="$($CONFTEST compiler)"
|
||||||
|
gcc_major="$($CONFTEST version)"
|
||||||
|
gcc_minor="$($CONFTEST minor)"
|
||||||
|
else
|
||||||
|
if test -z "$build_cross"; then
|
||||||
echo "configure: error: '$cc' failed to compile conftest.c."
|
echo "configure: error: '$cc' failed to compile conftest.c."
|
||||||
else
|
|
||||||
gcc_major="$($CONFTEST version)"
|
|
||||||
gcc_minor="$($CONFTEST minor)"
|
|
||||||
fi
|
fi
|
||||||
|
if test "${cc%tcc*}" != "$cc"; then
|
||||||
|
cc_name="tcc"
|
||||||
|
elif test "${cc%clang*}" != "$cc"; then
|
||||||
|
cc_name="clang"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -z "$build_cross"; then
|
||||||
bigendian="$($CONFTEST bigendian)"
|
bigendian="$($CONFTEST bigendian)"
|
||||||
|
_triplet="$($CONFTEST triplet)"
|
||||||
if test "$mingw32" = "no" ; then
|
if test "$mingw32" = "no" ; then
|
||||||
|
if test -z "$triplet" && test -n "$_triplet"; then
|
||||||
if test -z "$triplet"; then
|
if test -f "/usr/lib/$_triplet/crti.o"; then
|
||||||
tt="$($CONFTEST triplet)"
|
triplet="$_triplet"
|
||||||
if test -n "$tt" -a -f "/usr/lib/$tt/crti.o" ; then
|
|
||||||
triplet="$tt"
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test -z "$triplet"; then
|
if test -z "$triplet"; then
|
||||||
if test $cpu = "x86_64" -o $cpu = "aarch64" ; then
|
case $cpu in x86_64|arm64|riscv64)
|
||||||
if test -f "/usr/lib64/crti.o" ; then
|
if test -f "/usr/lib64/crti.o" ; then
|
||||||
tcc_lddir="lib64"
|
default tcc_libpaths "{B}:/usr/lib64"
|
||||||
|
default tcc_crtprefix "/usr/lib64"
|
||||||
fi
|
fi
|
||||||
fi
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "$cpu" = "arm" ; then
|
|
||||||
if test "${triplet%eabihf}" != "$triplet" ; then
|
|
||||||
confvars="$confvars arm_eabihf"
|
|
||||||
elif test "${triplet%eabi}" != "$triplet" ; then
|
|
||||||
confvars="$confvars arm_eabi"
|
|
||||||
fi
|
|
||||||
if grep -s -q "^Features.* \(vfp\|iwmmxt\) " /proc/cpuinfo ; then
|
|
||||||
confvars="$confvars arm_vfp"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$suggest" = "yes"; then
|
if test "$suggest" = "yes"; then
|
||||||
if test -f "/lib/ld-uClibc.so.0" ; then
|
if test -f "/lib/ld-uClibc.so.0" ; then
|
||||||
echo "Perhaps you want ./configure --config-uClibc"
|
echo "Perhaps you want ./configure --config-uClibc"
|
||||||
fi
|
fi
|
||||||
if test -f "/lib/ld-musl-$cpu.so.1"; then
|
if test -f "/lib/ld-musl-${cpu}.so.1"; then
|
||||||
echo "Perhaps you want ./configure --config-musl"
|
echo "Perhaps you want ./configure --config-musl"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
# if cross compiling, cannot launch a program, so make a static guess
|
# can only make guesses about compiler and target
|
||||||
case $cpu in
|
case $cpu in
|
||||||
ppc|mips|s390) bigendian=yes;;
|
ppc|mips|s390) bigendian=yes;;
|
||||||
esac
|
esac
|
||||||
|
case $targetos in
|
||||||
|
Linux)
|
||||||
|
default triplet "${cpu}-linux-gnu"
|
||||||
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "$bigendian" = "yes" ; then
|
if test "$bigendian" = "yes" ; then
|
||||||
confvars="$confvars BIGENDIAN"
|
confvars_set BIGENDIAN
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$cpu" = "arm"; then
|
||||||
|
if test "${triplet%eabihf}" != "$triplet" ; then
|
||||||
|
confvars_set arm_eabihf arm_vfp
|
||||||
|
elif test "${triplet%eabi}" != "$triplet" ; then
|
||||||
|
confvars_set arm_eabi arm_vfp
|
||||||
|
elif test -z "$build_cross"; then
|
||||||
|
if test "${_triplet%eabihf}" != "$_triplet" ; then
|
||||||
|
confvars_set arm_eabihf arm_vfp
|
||||||
|
elif test "${_triplet%eabi}" != "$_triplet" ; then
|
||||||
|
confvars_set arm_eabi arm_vfp
|
||||||
|
elif grep -s -q "^Features.* \(vfp\|iwmmxt\) " /proc/cpuinfo ; then
|
||||||
|
confvars_set arm_vfp
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test -z "$build_cross"; then
|
||||||
|
if grep -s -q "^Features.* \(idiv\)" /proc/cpuinfo ; then
|
||||||
|
confvars_set arm_idiv
|
||||||
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# a final configuration tuning
|
# a final configuration tuning
|
||||||
if ! echo "$cc" | grep -q "tcc"; then
|
if test "$cc_name" != "tcc"; then
|
||||||
OPT1="-Wdeclaration-after-statement -fno-strict-aliasing"
|
OPT1="-Wdeclaration-after-statement" #-fno-strict-aliasing
|
||||||
# we want -Wno- but gcc does not always reject unknown -Wno- options
|
# we want -Wno- but gcc does not always reject unknown -Wno- options
|
||||||
OPT2="-Wpointer-sign -Wsign-compare -Wunused-result"
|
if test "$cc_name" = "clang"; then
|
||||||
if echo "$cc" | grep -q "clang"; then
|
OPT2= #"-Wstring-plus-int"
|
||||||
OPT1="$OPT1 -fheinous-gnu-extensions"
|
else
|
||||||
OPT2="$OPT2 -Wstring-plus-int"
|
OPT2="-Wunused-result"
|
||||||
fi
|
fi
|
||||||
$cc $OPT1 $OPT2 -o a.out -c -xc - < /dev/null > cc_msg.txt 2>&1
|
$cc $OPT1 $OPT2 -o a.out -c -xc - < /dev/null > cc_msg.txt 2>&1
|
||||||
for o in $OPT1; do # enable these options
|
for o in $OPT1; do # enable these options
|
||||||
@ -383,10 +547,13 @@ if ! echo "$cc" | grep -q "tcc"; then
|
|||||||
# cat cc_msg.txt
|
# cat cc_msg.txt
|
||||||
# echo $CFLAGS
|
# echo $CFLAGS
|
||||||
rm -f cc_msg.txt a.out
|
rm -f cc_msg.txt a.out
|
||||||
|
else # cc is tcc
|
||||||
|
test "$ar_set" || ar="$cc -ar"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
fcho() { if test -n "$2"; then echo "$1$2"; fi }
|
fcho() { if test -n "$2"; then echo "$1$2"; fi }
|
||||||
|
|
||||||
|
if test -z "$quiet"; then
|
||||||
fcho "Binary directory " "$bindir"
|
fcho "Binary directory " "$bindir"
|
||||||
fcho "TinyCC directory " "$tccdir"
|
fcho "TinyCC directory " "$tccdir"
|
||||||
fcho "Library directory " "$libdir"
|
fcho "Library directory " "$libdir"
|
||||||
@ -396,12 +563,21 @@ fcho "Info directory " "$infodir"
|
|||||||
fcho "Doc directory " "$docdir"
|
fcho "Doc directory " "$docdir"
|
||||||
fcho "Target root prefix " "$sysroot"
|
fcho "Target root prefix " "$sysroot"
|
||||||
echo "Source path $source_path"
|
echo "Source path $source_path"
|
||||||
|
echo "Build OS $(uname -m -s)"
|
||||||
echo "C compiler $cc ($gcc_major.$gcc_minor)"
|
echo "C compiler $cc ($gcc_major.$gcc_minor)"
|
||||||
echo "Target OS $targetos"
|
echo "Target OS $targetos"
|
||||||
echo "CPU $cpu"
|
echo "CPU $cpu"
|
||||||
fcho "Triplet " "$triplet"
|
fcho "Triplet " "$triplet"
|
||||||
|
fcho "Libs " "$tcc_libpaths"
|
||||||
|
fcho "Sysinclude " "$tcc_sysincludepaths"
|
||||||
|
fcho "Crt " "$tcc_crtprefix"
|
||||||
|
fcho "Elfinterp " "$tcc_elfinterp"
|
||||||
|
fcho "Switches " "$tcc_switches"
|
||||||
fcho "Config " "${confvars# }"
|
fcho "Config " "${confvars# }"
|
||||||
echo "Creating config.mak and config.h"
|
echo "Creating config.mak and config.h"
|
||||||
|
fi
|
||||||
|
|
||||||
|
version=$(head "$source_path/VERSION")
|
||||||
|
|
||||||
cat >config.mak <<EOF
|
cat >config.mak <<EOF
|
||||||
# Automatically generated by configure - do not modify
|
# Automatically generated by configure - do not modify
|
||||||
@ -414,69 +590,21 @@ mandir=\$(DESTDIR)$mandir
|
|||||||
infodir=\$(DESTDIR)$infodir
|
infodir=\$(DESTDIR)$infodir
|
||||||
docdir=\$(DESTDIR)$docdir
|
docdir=\$(DESTDIR)$docdir
|
||||||
CC=$cc
|
CC=$cc
|
||||||
|
CC_NAME=$cc_name
|
||||||
GCC_MAJOR=$gcc_major
|
GCC_MAJOR=$gcc_major
|
||||||
GCC_MINOR=$gcc_minor
|
GCC_MINOR=$gcc_minor
|
||||||
AR=$ar
|
AR=$ar
|
||||||
STRIP=$strip -s -R .comment -R .note
|
|
||||||
CFLAGS=$CFLAGS
|
|
||||||
LDFLAGS=$LDFLAGS
|
|
||||||
LIBSUF=$LIBSUF
|
LIBSUF=$LIBSUF
|
||||||
EXESUF=$EXESUF
|
EXESUF=$EXESUF
|
||||||
DLLSUF=$DLLSUF
|
DLLSUF=$DLLSUF
|
||||||
|
CFLAGS=$CFLAGS
|
||||||
|
LDFLAGS=$LDFLAGS
|
||||||
|
ARCH=$cpu
|
||||||
|
TARGETOS=$targetos
|
||||||
|
BUILDOS=$buildos
|
||||||
|
VERSION=$version
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
print_inc() {
|
|
||||||
if test -n "$2"; then
|
|
||||||
echo "#ifndef $1" >> $TMPH
|
|
||||||
echo "# define $1 \"$2\"" >> $TMPH
|
|
||||||
echo "#endif" >> $TMPH
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
print_mak() {
|
|
||||||
if test -n "$2"; then
|
|
||||||
echo "NATIVE_DEFINES+=-D$1=\"\\\"$2\\\"\"" >> config.mak
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
print_mak_int() {
|
|
||||||
if test -n "$2"; then
|
|
||||||
echo "NATIVE_DEFINES+=-D$1=$2" >> config.mak
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "/* Automatically generated by configure - do not modify */" > $TMPH
|
|
||||||
|
|
||||||
print_inc CONFIG_SYSROOT "$sysroot"
|
|
||||||
print_inc CONFIG_TCCDIR "$tccdir"
|
|
||||||
print_mak CONFIG_TCC_SYSINCLUDEPATHS "$tcc_sysincludepaths"
|
|
||||||
print_mak CONFIG_TCC_LIBPATHS "$tcc_libpaths"
|
|
||||||
print_mak CONFIG_TCC_CRTPREFIX "$tcc_crtprefix"
|
|
||||||
print_mak CONFIG_TCC_ELFINTERP "$tcc_elfinterp"
|
|
||||||
print_mak CONFIG_LDDIR "$tcc_lddir"
|
|
||||||
print_mak CONFIG_TRIPLET "$triplet"
|
|
||||||
print_mak_int TCC_CPU_VERSION "$cpuver"
|
|
||||||
|
|
||||||
if test "$cpu" = "aarch64" ; then
|
|
||||||
echo "ARCH=arm64" >> config.mak
|
|
||||||
else
|
|
||||||
echo "ARCH=$cpu" >> config.mak
|
|
||||||
fi
|
|
||||||
echo "TARGETOS=$targetos" >> config.mak
|
|
||||||
|
|
||||||
for v in $confvars ; do
|
|
||||||
if test "${v%=*}" = "$v"; then
|
|
||||||
echo "CONFIG_$v=yes" >> config.mak
|
|
||||||
else
|
|
||||||
echo "CONFIG_$v" >> config.mak
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
version=`head $source_path/VERSION`
|
|
||||||
echo "VERSION = $version" >> config.mak
|
|
||||||
echo "#define TCC_VERSION \"$version\"" >> $TMPH
|
|
||||||
echo "@set VERSION $version" > config.texi
|
|
||||||
|
|
||||||
if test "$source_path_used" = "yes" ; then
|
if test "$source_path_used" = "yes" ; then
|
||||||
case $source_path in
|
case $source_path in
|
||||||
/*) echo "TOPSRC=$source_path";;
|
/*) echo "TOPSRC=$source_path";;
|
||||||
@ -486,18 +614,127 @@ else
|
|||||||
echo 'TOPSRC=$(TOP)' >>config.mak
|
echo 'TOPSRC=$(TOP)' >>config.mak
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# $1: macro name, $2: val to set - quoted [, $3: non-empty for #ifndef]
|
||||||
|
print_str() {
|
||||||
|
if test -n "$2"; then
|
||||||
|
test -n "$3" && echo "#ifndef $1" >> $TMPH
|
||||||
|
echo "#define $1 \"$2\"" >> $TMPH
|
||||||
|
test -n "$3" && echo "#endif" >> $TMPH
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1: macro name, $2: val to set [, $3: non-empty for #ifndef]
|
||||||
|
print_num() {
|
||||||
|
if test -n "$2"; then
|
||||||
|
test -n "$3" && echo "#ifndef $1" >> $TMPH
|
||||||
|
echo "#define $1 $2" >> $TMPH
|
||||||
|
test -n "$3" && echo "#endif" >> $TMPH
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
cat >$TMPH <<EOF
|
||||||
|
/* Automatically generated by configure - do not modify */
|
||||||
|
|
||||||
|
#define TCC_VERSION "$version"
|
||||||
|
|
||||||
|
#define CC_NAME CC_$cc_name
|
||||||
|
#define GCC_MAJOR $gcc_major
|
||||||
|
#define GCC_MINOR $gcc_minor
|
||||||
|
|
||||||
|
#if !(TCC_TARGET_I386 || TCC_TARGET_X86_64 || TCC_TARGET_ARM\
|
||||||
|
|| TCC_TARGET_ARM64 || TCC_TARGET_RISCV64 || TCC_TARGET_C67)
|
||||||
|
EOF
|
||||||
|
|
||||||
|
predefs=1
|
||||||
|
# options that are applied only to the native tcc
|
||||||
|
for v in $cpu $confvars ; do
|
||||||
|
if test "${v%=*}" = "$v"; then
|
||||||
|
v="$v=yes"
|
||||||
|
fi
|
||||||
|
R="CONFIG_$v"
|
||||||
|
echo "$R" >> config.mak
|
||||||
|
case "$R" in
|
||||||
|
# CPU
|
||||||
|
CONFIG_i386=yes) print_num TCC_TARGET_I386 1 ;;
|
||||||
|
CONFIG_x86_64=yes) print_num TCC_TARGET_X86_64 1 ;;
|
||||||
|
CONFIG_arm64=yes) print_num TCC_TARGET_ARM64 1 ;;
|
||||||
|
CONFIG_riscv64=yes) print_num TCC_TARGET_RISCV64 1 ;;
|
||||||
|
CONFIG_arm=yes) print_num TCC_TARGET_ARM 1
|
||||||
|
print_num CONFIG_TCC_CPUVER "$cpuver" ;;
|
||||||
|
CONFIG_arm_eabihf=yes) print_num TCC_ARM_EABI 1
|
||||||
|
print_num TCC_ARM_HARDFLOAT 1 ;;
|
||||||
|
CONFIG_arm_eabi=yes) print_num TCC_ARM_EABI 1 ;;
|
||||||
|
CONFIG_arm_vfp=yes) print_num TCC_ARM_VFP 1 ;;
|
||||||
|
CONFIG_arm_idiv=yes) print_num __ARM_FEATURE_IDIV 1 ;;
|
||||||
|
# OS
|
||||||
|
CONFIG_WIN32=yes) print_num TCC_TARGET_PE 1 ;;
|
||||||
|
CONFIG_OSX=yes) print_num TCC_TARGET_MACHO 1 ;;
|
||||||
|
CONFIG_Android=yes) print_num TARGETOS_ANDROID 1 ;;
|
||||||
|
CONFIG_BSD=yes) print_num TARGETOS_$targetos 1
|
||||||
|
case "$targetos" in
|
||||||
|
FreeBSD) default tcc_elfinterp "/libexec/ld-elf.so.1";;
|
||||||
|
FreeBSD_kernel)
|
||||||
|
case "$cpu" in
|
||||||
|
x86_64) default tcc_elfinterp "/lib/ld-kfreebsd-x86-64.so.1";;
|
||||||
|
*) default tcc_elfinterp "/lib/ld.so.1";;
|
||||||
|
esac ;;
|
||||||
|
DragonFly) default tcc_elfinterp "/usr/libexec/ld-elf.so.2";;
|
||||||
|
NetBSD) default tcc_elfinterp "/usr/libexec/ld.elf_so";;
|
||||||
|
OpenBSD) default tcc_elfinterp "/usr/libexec/ld.so";;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
CONFIG_uClibc=yes) print_num CONFIG_TCC_UCLIBC 1
|
||||||
|
default tcc_elfinterp "/lib/ld-uClibc.so.0"
|
||||||
|
;;
|
||||||
|
CONFIG_musl=yes) print_num CONFIG_TCC_MUSL 1
|
||||||
|
case "$cpu" in
|
||||||
|
arm64) default tcc_elfinterp "/lib/ld-musl-aarch64.so.1";;
|
||||||
|
*) default tcc_elfinterp "/lib/ld-musl-${cpu}.so.1";;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
# other
|
||||||
|
CONFIG_selinux=yes) print_num CONFIG_SELINUX 1 ;;
|
||||||
|
CONFIG_pie=yes) print_num CONFIG_TCC_PIE 1 ;;
|
||||||
|
CONFIG_pic=yes) print_num CONFIG_TCC_PIC 1 ;;
|
||||||
|
CONFIG_new_dtags=yes) print_num CONFIG_NEW_DTAGS 1 ;;
|
||||||
|
CONFIG_codesign=yes) print_num CONFIG_CODESIGN 1 ;;
|
||||||
|
CONFIG_new_macho=no) print_num CONFIG_NEW_MACHO 0 ;;
|
||||||
|
CONFIG_bcheck=no) print_num CONFIG_TCC_BCHECK 0 ;;
|
||||||
|
CONFIG_backtrace=no) print_num CONFIG_TCC_BACKTRACE 0 ;;
|
||||||
|
CONFIG_dwarf=*) print_num CONFIG_DWARF_VERSION ${R#*=} ;;
|
||||||
|
CONFIG_semlock=*) print_num CONFIG_TCC_SEMLOCK ${R#*=} ;;
|
||||||
|
CONFIG_predefs=no) predefs=0 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
print_str CONFIG_TCC_SYSINCLUDEPATHS "$tcc_sysincludepaths"
|
||||||
|
print_str CONFIG_TCC_LIBPATHS "$tcc_libpaths"
|
||||||
|
print_str CONFIG_TCC_CRTPREFIX "$tcc_crtprefix"
|
||||||
|
print_str CONFIG_TCC_ELFINTERP "$tcc_elfinterp"
|
||||||
|
print_str CONFIG_TCC_SWITCHES "$tcc_switches"
|
||||||
|
print_str CONFIG_TRIPLET "$triplet"
|
||||||
|
print_str CONFIG_OS_RELEASE "$os_release"
|
||||||
|
echo "#endif" >> $TMPH && echo >> $TMPH
|
||||||
|
|
||||||
|
print_str CONFIG_SYSROOT "$sysroot" x
|
||||||
|
test "$tccdir_auto" = "yes" || print_str CONFIG_TCCDIR "$tccdir" x
|
||||||
|
print_num CONFIG_TCC_PREDEFS "$predefs"
|
||||||
|
|
||||||
diff $TMPH config.h >/dev/null 2>&1
|
diff $TMPH config.h >/dev/null 2>&1
|
||||||
if test $? -ne 0 ; then
|
if test $? -ne 0 ; then
|
||||||
mv -f $TMPH config.h
|
mv -f $TMPH config.h
|
||||||
else
|
elif test -z "$quiet"; then
|
||||||
echo "config.h is unchanged"
|
echo "config.h is unchanged"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo "@set VERSION $version" > config.texi
|
||||||
|
|
||||||
rm -f $TMPN* $CONFTEST
|
rm -f $TMPN* $CONFTEST
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# build tree in object directory if source path is different from current one
|
# build tree in object directory if source path is different from current one
|
||||||
|
|
||||||
|
use_cp=
|
||||||
fn_makelink()
|
fn_makelink()
|
||||||
{
|
{
|
||||||
tgt=$1/$2
|
tgt=$1/$2
|
||||||
@ -514,13 +751,15 @@ fn_makelink()
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
ln -sfn $tgt $2 || ( echo "ln failed. Using cp instead."; cp -f $1/$2 $2 )
|
test -n "$use_cp" || ln -sfn "$tgt" $2 ||
|
||||||
|
{ use_cp=yes; echo "ln failed. Using cp instead."; }
|
||||||
|
test -z "$use_cp" || cp -f "$1/$2" $2
|
||||||
}
|
}
|
||||||
|
|
||||||
if test "$source_path_used" = "yes" ; then
|
if test "$source_path_used" = "yes" ; then
|
||||||
FILES="Makefile lib/Makefile tests/Makefile tests/tests2/Makefile tests/pp/Makefile"
|
FILES="Makefile lib/Makefile tests/Makefile tests/tests2/Makefile tests/pp/Makefile"
|
||||||
for f in $FILES ; do
|
for f in $FILES ; do
|
||||||
fn_makelink $source_path $f
|
fn_makelink "$source_path" $f
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
263
conftest.c
263
conftest.c
@ -1,4 +1,182 @@
|
|||||||
|
/* ----------------------------------------------------------------------- */
|
||||||
|
/* with -D C2STR: convert tccdefs.h to C-strings */
|
||||||
|
|
||||||
|
#if C2STR
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* replace native host macros by compile-time versions */
|
||||||
|
const char *platform_macros[] = {
|
||||||
|
"__i386__", "TCC_TARGET_I386",
|
||||||
|
"__x86_64__", "TCC_TARGET_X86_64",
|
||||||
|
"_WIN32", "TCC_TARGET_PE",
|
||||||
|
"__arm__", "TCC_TARGET_ARM",
|
||||||
|
"__ARM_EABI__", "TCC_ARM_EABI",
|
||||||
|
"__aarch64__", "TCC_TARGET_ARM64",
|
||||||
|
"__riscv", "TCC_TARGET_RISCV64",
|
||||||
|
"__APPLE__", "TCC_TARGET_MACHO",
|
||||||
|
"__FreeBSD__", "TARGETOS_FreeBSD",
|
||||||
|
"__FreeBSD_kernel__", "TARGETOS_FreeBSD_kernel",
|
||||||
|
"__OpenBSD__", "TARGETOS_OpenBSD",
|
||||||
|
"__NetBSD__", "TARGETOS_NetBSD",
|
||||||
|
"__linux__", "TARGETOS_Linux",
|
||||||
|
"__ANDROID__", "TARGETOS_ANDROID",
|
||||||
|
|
||||||
|
"__SIZEOF_POINTER__", "PTR_SIZE",
|
||||||
|
"__SIZEOF_LONG__", "LONG_SIZE",
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
int isid(int c)
|
||||||
|
{
|
||||||
|
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
|
||||||
|
|| (c >= '0' && c <= '9') || c == '_';
|
||||||
|
}
|
||||||
|
|
||||||
|
int isspc(int c)
|
||||||
|
{
|
||||||
|
return (unsigned char)c <= ' ' && c != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char l[1000], l2[1000], *p, *q, *p0;
|
||||||
|
FILE *fp, *op;
|
||||||
|
int c, e, f, s, cmt, cmt_n;
|
||||||
|
const char *r;
|
||||||
|
|
||||||
|
if (argc < 3)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
fp = fopen(argv[1], "rb");
|
||||||
|
op = fopen(argv[2], "wb");
|
||||||
|
if (!fp || !op) {
|
||||||
|
fprintf(stderr, "c2str: file error\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmt = cmt_n = 0;
|
||||||
|
for (;;) {
|
||||||
|
p = l;
|
||||||
|
append:
|
||||||
|
if (fgets(p, sizeof l - (p - l), fp)) {
|
||||||
|
p = strchr(p, 0);
|
||||||
|
while (p > l && isspc(p[-1]))
|
||||||
|
--p;
|
||||||
|
*p = 0;
|
||||||
|
} else if (p == l)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* check for continuation */
|
||||||
|
if (p > l && p[-1] == '\\') {
|
||||||
|
p[-1] = ' ';
|
||||||
|
goto append;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* count & skip leading spaces */
|
||||||
|
p = l, q = l2, f = 0;
|
||||||
|
while (*p && isspc(*p))
|
||||||
|
++p, ++f;
|
||||||
|
|
||||||
|
/* handle comments */
|
||||||
|
if (p[0] == '/' && cmt == 0) {
|
||||||
|
if (p[1] == '*')
|
||||||
|
cmt = 2;
|
||||||
|
if (p[1] == '/')
|
||||||
|
cmt = 1;
|
||||||
|
}
|
||||||
|
if (cmt) {
|
||||||
|
fprintf(op, "%s", l);
|
||||||
|
if (++cmt_n == 1)
|
||||||
|
fprintf(op, " (converted, do not edit this file)");
|
||||||
|
fprintf(op, "\n");
|
||||||
|
if (cmt == 1)
|
||||||
|
cmt = 0;
|
||||||
|
if (cmt == 2) {
|
||||||
|
p = strchr(l, 0);
|
||||||
|
if (p >= l + 2 && p[-1] == '/' && p[-2] == '*')
|
||||||
|
cmt = 0;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f < 4) {
|
||||||
|
do {
|
||||||
|
/* replace machine/os macros by compile-time counterparts */
|
||||||
|
for (e = f = 0; (r = platform_macros[f]); f += 2) {
|
||||||
|
c = strlen(r);
|
||||||
|
/* remove 'defined' */
|
||||||
|
//e = memcmp(p, "defined ", 8) ? 0 : 8;
|
||||||
|
if (0 == memcmp(p + e, r, c)) {
|
||||||
|
p += e + c;
|
||||||
|
q = strchr(strcpy(q, platform_macros[f + 1]), 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (r)
|
||||||
|
continue;
|
||||||
|
} while (!!(*q++ = *p++));
|
||||||
|
/* output as is */
|
||||||
|
fprintf(op, "%s\n", l2);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
s = e = f = 0, p0 = p;
|
||||||
|
for (;;) {
|
||||||
|
c = *p++;
|
||||||
|
|
||||||
|
if (isspc(c)) {
|
||||||
|
s = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c == '/' && (p[0] == '/' || p[0] == '*'))
|
||||||
|
c = 0; /* trailing comment detected */
|
||||||
|
else if (s && q > l2
|
||||||
|
&& ((isid(q[-1]) && isid(c))
|
||||||
|
// keep space after macro name
|
||||||
|
|| (q >= l2 + 2
|
||||||
|
&& l2[0] == '#'
|
||||||
|
&& l2[1] == 'd'
|
||||||
|
&& f < 2 && !e
|
||||||
|
)))
|
||||||
|
*q++ = ' ', ++f;
|
||||||
|
s = 0;
|
||||||
|
|
||||||
|
if (c == '(')
|
||||||
|
++e;
|
||||||
|
if (c == ')')
|
||||||
|
--e;
|
||||||
|
if (c == '\\' || c == '\"')
|
||||||
|
*q++ = '\\';
|
||||||
|
*q++ = c;
|
||||||
|
if (c == 0)
|
||||||
|
break;
|
||||||
|
p0 = p;
|
||||||
|
}
|
||||||
|
/* output with quotes */
|
||||||
|
fprintf(op, " \"%s\\n\"%s\n", l2, p0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
fclose(op);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------- */
|
||||||
|
/* get some information from the host compiler for configure */
|
||||||
|
|
||||||
|
#elif 1
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <io.h>
|
||||||
|
int _CRT_glob = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Define architecture */
|
/* Define architecture */
|
||||||
#if defined(__i386__) || defined _M_IX86
|
#if defined(__i386__) || defined _M_IX86
|
||||||
@ -9,6 +187,8 @@
|
|||||||
# define TRIPLET_ARCH "arm"
|
# define TRIPLET_ARCH "arm"
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
# define TRIPLET_ARCH "aarch64"
|
# define TRIPLET_ARCH "aarch64"
|
||||||
|
#elif defined(__riscv) && defined(__LP64__)
|
||||||
|
# define TRIPLET_ARCH "riscv64"
|
||||||
#else
|
#else
|
||||||
# define TRIPLET_ARCH "unknown"
|
# define TRIPLET_ARCH "unknown"
|
||||||
#endif
|
#endif
|
||||||
@ -18,21 +198,33 @@
|
|||||||
# define TRIPLET_OS "linux"
|
# define TRIPLET_OS "linux"
|
||||||
#elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
|
#elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
|
||||||
# define TRIPLET_OS "kfreebsd"
|
# define TRIPLET_OS "kfreebsd"
|
||||||
#elif defined _WIN32
|
#elif defined(__NetBSD__)
|
||||||
|
# define TRIPLET_OS "netbsd"
|
||||||
|
#elif defined(__OpenBSD__)
|
||||||
|
# define TRIPLET_OS "openbsd"
|
||||||
|
#elif defined(_WIN32)
|
||||||
# define TRIPLET_OS "win32"
|
# define TRIPLET_OS "win32"
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
# define TRIPLET_OS "darwin"
|
||||||
#elif !defined (__GNU__)
|
#elif !defined (__GNU__)
|
||||||
# define TRIPLET_OS "unknown"
|
# define TRIPLET_OS "unknown"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined __ANDROID__
|
||||||
|
# define ABI_PREFIX "android"
|
||||||
|
#else
|
||||||
|
# define ABI_PREFIX "gnu"
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Define calling convention and ABI */
|
/* Define calling convention and ABI */
|
||||||
#if defined (__ARM_EABI__)
|
#if defined (__ARM_EABI__)
|
||||||
# if defined (__ARM_PCS_VFP)
|
# if defined (__ARM_PCS_VFP)
|
||||||
# define TRIPLET_ABI "gnueabihf"
|
# define TRIPLET_ABI ABI_PREFIX"eabihf"
|
||||||
# else
|
# else
|
||||||
# define TRIPLET_ABI "gnueabi"
|
# define TRIPLET_ABI ABI_PREFIX"eabi"
|
||||||
# endif
|
# endif
|
||||||
#else
|
#else
|
||||||
# define TRIPLET_ABI "gnu"
|
# define TRIPLET_ABI ABI_PREFIX
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined _WIN32
|
#if defined _WIN32
|
||||||
@ -43,45 +235,74 @@
|
|||||||
# define TRIPLET TRIPLET_ARCH "-" TRIPLET_OS "-" TRIPLET_ABI
|
# define TRIPLET TRIPLET_ARCH "-" TRIPLET_OS "-" TRIPLET_ABI
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
int _CRT_glob = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
#if defined(_WIN32)
|
||||||
|
_setmode(_fileno(stdout), _O_BINARY); /* don't translate \n to \r\n */
|
||||||
|
#endif
|
||||||
switch(argc == 2 ? argv[1][0] : 0) {
|
switch(argc == 2 ? argv[1][0] : 0) {
|
||||||
case 'b':
|
case 'b'://igendian
|
||||||
{
|
{
|
||||||
volatile unsigned foo = 0x01234567;
|
volatile unsigned foo = 0x01234567;
|
||||||
puts(*(unsigned char*)&foo == 0x67 ? "no" : "yes");
|
puts(*(unsigned char*)&foo == 0x67 ? "no" : "yes");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifdef __GNUC__
|
#if defined(__clang__)
|
||||||
case 'm':
|
case 'm'://inor
|
||||||
printf("%d\n", __GNUC_MINOR__);
|
printf("%d\n", __clang_minor__);
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v'://ersion
|
||||||
printf("%d\n", __GNUC__);
|
printf("%d\n", __clang_major__);
|
||||||
break;
|
break;
|
||||||
#elif defined __TINYC__
|
#elif defined(__TINYC__)
|
||||||
case 'v':
|
case 'v'://ersion
|
||||||
puts("0");
|
puts("0");
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm'://inor
|
||||||
printf("%d\n", __TINYC__);
|
printf("%d\n", __TINYC__);
|
||||||
break;
|
break;
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
case 'v'://ersion
|
||||||
|
puts("0");
|
||||||
|
break;
|
||||||
|
case 'm'://inor
|
||||||
|
printf("%d\n", _MSC_VER);
|
||||||
|
break;
|
||||||
|
#elif defined(__GNUC__) && defined(__GNUC_MINOR__)
|
||||||
|
/* GNU comes last as other compilers may add 'GNU' compatibility */
|
||||||
|
case 'm'://inor
|
||||||
|
printf("%d\n", __GNUC_MINOR__);
|
||||||
|
break;
|
||||||
|
case 'v'://ersion
|
||||||
|
printf("%d\n", __GNUC__);
|
||||||
|
break;
|
||||||
#else
|
#else
|
||||||
case 'm':
|
case 'm'://inor
|
||||||
case 'v':
|
case 'v'://ersion
|
||||||
puts("0");
|
puts("0");
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case 't':
|
case 't'://riplet
|
||||||
puts(TRIPLET);
|
puts(TRIPLET);
|
||||||
break;
|
break;
|
||||||
|
case 'c'://ompiler
|
||||||
|
#if defined(__clang__)
|
||||||
|
puts("clang");
|
||||||
|
#elif defined(__TINYC__)
|
||||||
|
puts("tcc");
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
puts("msvc");
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
puts("gcc");
|
||||||
|
#else
|
||||||
|
puts("unknown");
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------- */
|
||||||
|
#endif
|
||||||
|
|||||||
96
elf.h
96
elf.h
@ -159,7 +159,12 @@ typedef struct
|
|||||||
#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */
|
#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */
|
||||||
#define ELFOSABI_MODESTO 11 /* Novell Modesto. */
|
#define ELFOSABI_MODESTO 11 /* Novell Modesto. */
|
||||||
#define ELFOSABI_OPENBSD 12 /* OpenBSD. */
|
#define ELFOSABI_OPENBSD 12 /* OpenBSD. */
|
||||||
#define ELFOSABI_ARM_AEABI 64 /* ARM EABI */
|
#define ELFOSABI_OPENVMS 13
|
||||||
|
#define ELFOSABI_NSK 14 /* Hewlett-Packard Non-Stop Kernel. */
|
||||||
|
#define ELFOSABI_AROS 15 /* Amiga Research OS. */
|
||||||
|
#define ELFOSABI_FENIXOS 16 /* FenixOS. */
|
||||||
|
#define ELFOSABI_ARM_AEABI 64 /* ARM EABI. */
|
||||||
|
#define ELFOSABI_C6000_LINUX 65 /* Linux TMS320C6000. */
|
||||||
#define ELFOSABI_ARM 97 /* ARM */
|
#define ELFOSABI_ARM 97 /* ARM */
|
||||||
#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
|
#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
|
||||||
|
|
||||||
@ -262,7 +267,8 @@ typedef struct
|
|||||||
#define EM_AARCH64 183 /* ARM AARCH64 */
|
#define EM_AARCH64 183 /* ARM AARCH64 */
|
||||||
#define EM_TILEPRO 188 /* Tilera TILEPro */
|
#define EM_TILEPRO 188 /* Tilera TILEPro */
|
||||||
#define EM_TILEGX 191 /* Tilera TILE-Gx */
|
#define EM_TILEGX 191 /* Tilera TILE-Gx */
|
||||||
#define EM_NUM 192
|
#define EM_RISCV 243 /* RISC-V */
|
||||||
|
#define EM_NUM 253
|
||||||
|
|
||||||
/* If it is necessary to assign new unofficial EM_* values, please
|
/* If it is necessary to assign new unofficial EM_* values, please
|
||||||
pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
|
pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
|
||||||
@ -381,7 +387,7 @@ typedef struct
|
|||||||
#define SHF_MASKPROC 0xf0000000 /* Processor-specific */
|
#define SHF_MASKPROC 0xf0000000 /* Processor-specific */
|
||||||
#define SHF_ORDERED (1 << 30) /* Special ordering requirement
|
#define SHF_ORDERED (1 << 30) /* Special ordering requirement
|
||||||
(Solaris). */
|
(Solaris). */
|
||||||
#define SHF_EXCLUDE (1 << 31) /* Section is excluded unless
|
#define SHF_EXCLUDE (1U << 31) /* Section is excluded unless
|
||||||
referenced or allocated (Solaris).*/
|
referenced or allocated (Solaris).*/
|
||||||
|
|
||||||
/* Section group handling. */
|
/* Section group handling. */
|
||||||
@ -819,6 +825,7 @@ typedef struct
|
|||||||
#define DF_1_SYMINTPOSE 0x00800000 /* Object has individual interposers. */
|
#define DF_1_SYMINTPOSE 0x00800000 /* Object has individual interposers. */
|
||||||
#define DF_1_GLOBAUDIT 0x01000000 /* Global auditing required. */
|
#define DF_1_GLOBAUDIT 0x01000000 /* Global auditing required. */
|
||||||
#define DF_1_SINGLETON 0x02000000 /* Singleton symbols are used. */
|
#define DF_1_SINGLETON 0x02000000 /* Singleton symbols are used. */
|
||||||
|
#define DF_1_PIE 0x08000000
|
||||||
|
|
||||||
/* Flags for the feature selection in DT_FEATURE_1. */
|
/* Flags for the feature selection in DT_FEATURE_1. */
|
||||||
#define DTF_1_PARINIT 0x00000001
|
#define DTF_1_PARINIT 0x00000001
|
||||||
@ -2329,7 +2336,8 @@ typedef Elf32_Addr Elf32_Conflict;
|
|||||||
/* Processor specific values for the Shdr sh_type field. */
|
/* Processor specific values for the Shdr sh_type field. */
|
||||||
#define SHT_ARM_EXIDX (SHT_LOPROC + 1) /* ARM unwind section. */
|
#define SHT_ARM_EXIDX (SHT_LOPROC + 1) /* ARM unwind section. */
|
||||||
#define SHT_ARM_PREEMPTMAP (SHT_LOPROC + 2) /* Preemption details. */
|
#define SHT_ARM_PREEMPTMAP (SHT_LOPROC + 2) /* Preemption details. */
|
||||||
#define SHT_ARM_ATTRIBUTES (SHT_LOPROC + 3) /* ARM attributes section. */
|
#define SHT_ARM_ATTRIBUTES (SHT_LOPROC + 3) /* ARM attributes section. */
|
||||||
|
#define SHT_RISCV_ATTRIBUTES 0x70000003
|
||||||
|
|
||||||
|
|
||||||
/* AArch64 relocs. */
|
/* AArch64 relocs. */
|
||||||
@ -2494,22 +2502,30 @@ typedef Elf32_Addr Elf32_Conflict;
|
|||||||
#define R_ARM_CALL 28
|
#define R_ARM_CALL 28
|
||||||
#define R_ARM_JUMP24 29
|
#define R_ARM_JUMP24 29
|
||||||
#define R_ARM_THM_JUMP24 30
|
#define R_ARM_THM_JUMP24 30
|
||||||
|
#define R_ARM_BASE_ABS 31 /* Adjust by program base. */
|
||||||
#define R_ARM_ALU_PCREL_7_0 32
|
#define R_ARM_ALU_PCREL_7_0 32
|
||||||
#define R_ARM_ALU_PCREL_15_8 33
|
#define R_ARM_ALU_PCREL_15_8 33
|
||||||
#define R_ARM_ALU_PCREL_23_15 34
|
#define R_ARM_ALU_PCREL_23_15 34
|
||||||
#define R_ARM_LDR_SBREL_11_0 35
|
#define R_ARM_LDR_SBREL_11_0 35
|
||||||
#define R_ARM_ALU_SBREL_19_12 36
|
#define R_ARM_ALU_SBREL_19_12 36
|
||||||
#define R_ARM_ALU_SBREL_27_20 37
|
#define R_ARM_ALU_SBREL_27_20 37
|
||||||
|
#define R_ARM_TARGET1 38
|
||||||
|
#define R_ARM_SBREL31 39 /* Program base relative. */
|
||||||
#define R_ARM_V4BX 40
|
#define R_ARM_V4BX 40
|
||||||
|
#define R_ARM_TARGET2 41
|
||||||
#define R_ARM_PREL31 42
|
#define R_ARM_PREL31 42
|
||||||
#define R_ARM_MOVW_ABS_NC 43
|
#define R_ARM_MOVW_ABS_NC 43
|
||||||
#define R_ARM_MOVT_ABS 44
|
#define R_ARM_MOVT_ABS 44
|
||||||
|
#define R_ARM_MOVW_PREL_NC 45 /* PC relative 16-bit (MOVW). */
|
||||||
|
#define R_ARM_MOVT_PREL 46 /* PC relative (MOVT). */
|
||||||
#define R_ARM_THM_MOVW_ABS_NC 47
|
#define R_ARM_THM_MOVW_ABS_NC 47
|
||||||
#define R_ARM_THM_MOVT_ABS 48
|
#define R_ARM_THM_MOVT_ABS 48
|
||||||
|
/* Values from 49 to 89 are not yet used/handled by tcc. */
|
||||||
#define R_ARM_TLS_GOTDESC 90
|
#define R_ARM_TLS_GOTDESC 90
|
||||||
#define R_ARM_TLS_CALL 91
|
#define R_ARM_TLS_CALL 91
|
||||||
#define R_ARM_TLS_DESCSEQ 92
|
#define R_ARM_TLS_DESCSEQ 92
|
||||||
#define R_ARM_THM_TLS_CALL 93
|
#define R_ARM_THM_TLS_CALL 93
|
||||||
|
#define R_ARM_GOT_PREL 96
|
||||||
#define R_ARM_GNU_VTENTRY 100
|
#define R_ARM_GNU_VTENTRY 100
|
||||||
#define R_ARM_GNU_VTINHERIT 101
|
#define R_ARM_GNU_VTINHERIT 101
|
||||||
#define R_ARM_THM_PC11 102 /* thumb unconditional branch */
|
#define R_ARM_THM_PC11 102 /* thumb unconditional branch */
|
||||||
@ -2907,6 +2923,8 @@ typedef Elf32_Addr Elf32_Conflict;
|
|||||||
|
|
||||||
#define R_X86_64_NUM 43
|
#define R_X86_64_NUM 43
|
||||||
|
|
||||||
|
/* x86-64 sh_type values. */
|
||||||
|
#define SHT_X86_64_UNWIND 0x70000001 /* Unwind information. */
|
||||||
|
|
||||||
/* AM33 relocations. */
|
/* AM33 relocations. */
|
||||||
#define R_MN10300_NONE 0 /* No reloc. */
|
#define R_MN10300_NONE 0 /* No reloc. */
|
||||||
@ -3233,5 +3251,75 @@ typedef Elf32_Addr Elf32_Conflict;
|
|||||||
|
|
||||||
#define R_TILEGX_NUM 130
|
#define R_TILEGX_NUM 130
|
||||||
|
|
||||||
|
/* RISC-V ELF Flags */
|
||||||
|
#define EF_RISCV_RVC 0x0001
|
||||||
|
#define EF_RISCV_FLOAT_ABI 0x0006
|
||||||
|
#define EF_RISCV_FLOAT_ABI_SOFT 0x0000
|
||||||
|
#define EF_RISCV_FLOAT_ABI_SINGLE 0x0002
|
||||||
|
#define EF_RISCV_FLOAT_ABI_DOUBLE 0x0004
|
||||||
|
#define EF_RISCV_FLOAT_ABI_QUAD 0x0006
|
||||||
|
|
||||||
|
/* RISC-V relocations. */
|
||||||
|
#define R_RISCV_NONE 0
|
||||||
|
#define R_RISCV_32 1
|
||||||
|
#define R_RISCV_64 2
|
||||||
|
#define R_RISCV_RELATIVE 3
|
||||||
|
#define R_RISCV_COPY 4
|
||||||
|
#define R_RISCV_JUMP_SLOT 5
|
||||||
|
#define R_RISCV_TLS_DTPMOD32 6
|
||||||
|
#define R_RISCV_TLS_DTPMOD64 7
|
||||||
|
#define R_RISCV_TLS_DTPREL32 8
|
||||||
|
#define R_RISCV_TLS_DTPREL64 9
|
||||||
|
#define R_RISCV_TLS_TPREL32 10
|
||||||
|
#define R_RISCV_TLS_TPREL64 11
|
||||||
|
#define R_RISCV_BRANCH 16
|
||||||
|
#define R_RISCV_JAL 17
|
||||||
|
#define R_RISCV_CALL 18
|
||||||
|
#define R_RISCV_CALL_PLT 19
|
||||||
|
#define R_RISCV_GOT_HI20 20
|
||||||
|
#define R_RISCV_TLS_GOT_HI20 21
|
||||||
|
#define R_RISCV_TLS_GD_HI20 22
|
||||||
|
#define R_RISCV_PCREL_HI20 23
|
||||||
|
#define R_RISCV_PCREL_LO12_I 24
|
||||||
|
#define R_RISCV_PCREL_LO12_S 25
|
||||||
|
#define R_RISCV_HI20 26
|
||||||
|
#define R_RISCV_LO12_I 27
|
||||||
|
#define R_RISCV_LO12_S 28
|
||||||
|
#define R_RISCV_TPREL_HI20 29
|
||||||
|
#define R_RISCV_TPREL_LO12_I 30
|
||||||
|
#define R_RISCV_TPREL_LO12_S 31
|
||||||
|
#define R_RISCV_TPREL_ADD 32
|
||||||
|
#define R_RISCV_ADD8 33
|
||||||
|
#define R_RISCV_ADD16 34
|
||||||
|
#define R_RISCV_ADD32 35
|
||||||
|
#define R_RISCV_ADD64 36
|
||||||
|
#define R_RISCV_SUB8 37
|
||||||
|
#define R_RISCV_SUB16 38
|
||||||
|
#define R_RISCV_SUB32 39
|
||||||
|
#define R_RISCV_SUB64 40
|
||||||
|
#define R_RISCV_GNU_VTINHERIT 41
|
||||||
|
#define R_RISCV_GNU_VTENTRY 42
|
||||||
|
#define R_RISCV_ALIGN 43
|
||||||
|
#define R_RISCV_RVC_BRANCH 44
|
||||||
|
#define R_RISCV_RVC_JUMP 45
|
||||||
|
#define R_RISCV_RVC_LUI 46
|
||||||
|
#define R_RISCV_GPREL_I 47
|
||||||
|
#define R_RISCV_GPREL_S 48
|
||||||
|
#define R_RISCV_TPREL_I 49
|
||||||
|
#define R_RISCV_TPREL_S 50
|
||||||
|
#define R_RISCV_RELAX 51
|
||||||
|
#define R_RISCV_SUB6 52
|
||||||
|
#define R_RISCV_SET6 53
|
||||||
|
#define R_RISCV_SET8 54
|
||||||
|
#define R_RISCV_SET16 55
|
||||||
|
#define R_RISCV_SET32 56
|
||||||
|
#define R_RISCV_32_PCREL 57
|
||||||
|
#define R_RISCV_IRELATIVE 58
|
||||||
|
#define R_RISCV_PLT32 59
|
||||||
|
#define R_RISCV_SET_ULEB128 60
|
||||||
|
#define R_RISCV_SUB_ULEB128 61
|
||||||
|
|
||||||
|
#define R_RISCV_NUM 62
|
||||||
|
|
||||||
|
|
||||||
#endif /* elf.h */
|
#endif /* elf.h */
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#include <tcclib.h>
|
#include <tcclib.h>
|
||||||
|
|
||||||
int fib(n)
|
int fib(int n)
|
||||||
{
|
{
|
||||||
if (n <= 2)
|
if (n <= 2)
|
||||||
return 1;
|
return 1;
|
||||||
@ -18,6 +18,6 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
n = atoi(argv[1]);
|
n = atoi(argv[1]);
|
||||||
printf("fib(%d) = %d\n", n, fib(n, 2));
|
printf("fib(%d) = %d\n", n, fib(n));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
189
i386-asm.c
189
i386-asm.c
@ -19,6 +19,7 @@
|
|||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define USING_GLOBALS
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
|
|
||||||
#define MAX_OPERANDS 3
|
#define MAX_OPERANDS 3
|
||||||
@ -39,6 +40,8 @@
|
|||||||
#define OPC_ARITH 0x30 /* arithmetic opcodes */
|
#define OPC_ARITH 0x30 /* arithmetic opcodes */
|
||||||
#define OPC_FARITH 0x40 /* FPU arithmetic opcodes */
|
#define OPC_FARITH 0x40 /* FPU arithmetic opcodes */
|
||||||
#define OPC_TEST 0x50 /* test opcodes */
|
#define OPC_TEST 0x50 /* test opcodes */
|
||||||
|
#define OPC_0F01 0x60 /* 0x0f01XX (group 7, XX is 2nd opcode,
|
||||||
|
no operands and unstructured mod/rm) */
|
||||||
#define OPCT_IS(v,i) (((v) & OPCT_MASK) == (i))
|
#define OPCT_IS(v,i) (((v) & OPCT_MASK) == (i))
|
||||||
|
|
||||||
#define OPC_0F 0x100 /* Is secondary map (0x0f prefix) */
|
#define OPC_0F 0x100 /* Is secondary map (0x0f prefix) */
|
||||||
@ -133,17 +136,19 @@ enum {
|
|||||||
# define OP_EA32 0
|
# define OP_EA32 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define OP_EA 0x40000000
|
#define OP_EA 0x40000000u
|
||||||
#define OP_REG (OP_REG8 | OP_REG16 | OP_REG32 | OP_REG64)
|
#define OP_REG (OP_REG8 | OP_REG16 | OP_REG32 | OP_REG64)
|
||||||
|
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
# define TREG_XAX TREG_RAX
|
# define TREG_XAX TREG_RAX
|
||||||
# define TREG_XCX TREG_RCX
|
# define TREG_XCX TREG_RCX
|
||||||
# define TREG_XDX TREG_RDX
|
# define TREG_XDX TREG_RDX
|
||||||
|
# define TOK_ASM_xax TOK_ASM_rax
|
||||||
#else
|
#else
|
||||||
# define TREG_XAX TREG_EAX
|
# define TREG_XAX TREG_EAX
|
||||||
# define TREG_XCX TREG_ECX
|
# define TREG_XCX TREG_ECX
|
||||||
# define TREG_XDX TREG_EDX
|
# define TREG_XDX TREG_EDX
|
||||||
|
# define TOK_ASM_xax TOK_ASM_eax
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct ASMInstr {
|
typedef struct ASMInstr {
|
||||||
@ -484,18 +489,11 @@ ST_FUNC void gen_expr32(ExprValue *pe)
|
|||||||
if (pe->pcrel)
|
if (pe->pcrel)
|
||||||
/* If PC-relative, always set VT_SYM, even without symbol,
|
/* If PC-relative, always set VT_SYM, even without symbol,
|
||||||
so as to force a relocation to be emitted. */
|
so as to force a relocation to be emitted. */
|
||||||
gen_addrpc32(VT_SYM, pe->sym, pe->v);
|
gen_addrpc32(VT_SYM, pe->sym, pe->v + (ind + 4));
|
||||||
else
|
else
|
||||||
gen_addr32(pe->sym ? VT_SYM : 0, pe->sym, pe->v);
|
gen_addr32(pe->sym ? VT_SYM : 0, pe->sym, pe->v);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TCC_TARGET_X86_64
|
|
||||||
ST_FUNC void gen_expr64(ExprValue *pe)
|
|
||||||
{
|
|
||||||
gen_addr64(pe->sym ? VT_SYM : 0, pe->sym, pe->v);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* XXX: unify with C code output ? */
|
/* XXX: unify with C code output ? */
|
||||||
static void gen_disp32(ExprValue *pe)
|
static void gen_disp32(ExprValue *pe)
|
||||||
{
|
{
|
||||||
@ -512,7 +510,13 @@ static void gen_disp32(ExprValue *pe)
|
|||||||
sym->type.t = VT_FUNC;
|
sym->type.t = VT_FUNC;
|
||||||
sym->type.ref = NULL;
|
sym->type.ref = NULL;
|
||||||
}
|
}
|
||||||
|
#ifdef TCC_TARGET_X86_64
|
||||||
|
greloca(cur_text_section, sym, ind, R_X86_64_PLT32, pe->v - 4);
|
||||||
|
gen_le32(0);
|
||||||
|
#else
|
||||||
gen_addrpc32(VT_SYM, sym, pe->v);
|
gen_addrpc32(VT_SYM, sym, pe->v);
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -637,10 +641,12 @@ static void asm_rex(int width64, Operand *ops, int nb_ops, int *op_type,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static void maybe_print_stats (void)
|
static void maybe_print_stats (void)
|
||||||
{
|
{
|
||||||
static int already = 1;
|
static int already;
|
||||||
if (!already)
|
|
||||||
|
if (0 && !already)
|
||||||
/* print stats about opcodes */
|
/* print stats about opcodes */
|
||||||
{
|
{
|
||||||
const struct ASMInstr *pa;
|
const struct ASMInstr *pa;
|
||||||
@ -679,7 +685,7 @@ static void maybe_print_stats (void)
|
|||||||
ST_FUNC void asm_opcode(TCCState *s1, int opcode)
|
ST_FUNC void asm_opcode(TCCState *s1, int opcode)
|
||||||
{
|
{
|
||||||
const ASMInstr *pa;
|
const ASMInstr *pa;
|
||||||
int i, modrm_index, modreg_index, reg, v, op1, seg_prefix, pc;
|
int i, modrm_index, modreg_index, reg, v, op1, seg_prefix, pc, p;
|
||||||
int nb_ops, s;
|
int nb_ops, s;
|
||||||
Operand ops[MAX_OPERANDS], *pop;
|
Operand ops[MAX_OPERANDS], *pop;
|
||||||
int op_type[3]; /* decoded op type */
|
int op_type[3]; /* decoded op type */
|
||||||
@ -709,7 +715,7 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode)
|
|||||||
}
|
}
|
||||||
parse_operand(s1, pop);
|
parse_operand(s1, pop);
|
||||||
if (tok == ':') {
|
if (tok == ':') {
|
||||||
if (pop->type != OP_SEG || seg_prefix)
|
if (!(pop->type & OP_SEG) || seg_prefix)
|
||||||
tcc_error("incorrect prefix");
|
tcc_error("incorrect prefix");
|
||||||
seg_prefix = segment_prefixes[pop->reg];
|
seg_prefix = segment_prefixes[pop->reg];
|
||||||
next();
|
next();
|
||||||
@ -830,6 +836,7 @@ again:
|
|||||||
goto next;
|
goto next;
|
||||||
alltypes |= ops[i].type;
|
alltypes |= ops[i].type;
|
||||||
}
|
}
|
||||||
|
(void)alltypes; /* maybe unused */
|
||||||
/* all is matching ! */
|
/* all is matching ! */
|
||||||
break;
|
break;
|
||||||
next: ;
|
next: ;
|
||||||
@ -838,7 +845,7 @@ again:
|
|||||||
if (opcode >= TOK_ASM_first && opcode <= TOK_ASM_last) {
|
if (opcode >= TOK_ASM_first && opcode <= TOK_ASM_last) {
|
||||||
int b;
|
int b;
|
||||||
b = op0_codes[opcode - TOK_ASM_first];
|
b = op0_codes[opcode - TOK_ASM_first];
|
||||||
if (b & 0xff00)
|
if (b & 0xff00)
|
||||||
g(b >> 8);
|
g(b >> 8);
|
||||||
g(b);
|
g(b);
|
||||||
return;
|
return;
|
||||||
@ -887,30 +894,6 @@ again:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TCC_TARGET_X86_64
|
|
||||||
/* Generate addr32 prefix if needed */
|
|
||||||
for(i = 0; i < nb_ops; i++) {
|
|
||||||
if (ops[i].type & OP_EA32) {
|
|
||||||
g(0x67);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* generate data16 prefix if needed */
|
|
||||||
p66 = 0;
|
|
||||||
if (s == 1)
|
|
||||||
p66 = 1;
|
|
||||||
else {
|
|
||||||
/* accepting mmx+sse in all operands --> needs 0x66 to
|
|
||||||
switch to sse mode. Accepting only sse in an operand --> is
|
|
||||||
already SSE insn and needs 0x66/f2/f3 handling. */
|
|
||||||
for (i = 0; i < nb_ops; i++)
|
|
||||||
if ((op_type[i] & (OP_MMX | OP_SSE)) == (OP_MMX | OP_SSE)
|
|
||||||
&& ops[i].type & OP_SSE)
|
|
||||||
p66 = 1;
|
|
||||||
}
|
|
||||||
if (p66)
|
|
||||||
g(0x66);
|
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
rex64 = 0;
|
rex64 = 0;
|
||||||
if (pa->instr_type & OPC_48)
|
if (pa->instr_type & OPC_48)
|
||||||
@ -943,8 +926,45 @@ again:
|
|||||||
g(0x9b);
|
g(0x9b);
|
||||||
if (seg_prefix)
|
if (seg_prefix)
|
||||||
g(seg_prefix);
|
g(seg_prefix);
|
||||||
|
#ifdef TCC_TARGET_X86_64
|
||||||
|
/* Generate addr32 prefix if needed */
|
||||||
|
for(i = 0; i < nb_ops; i++) {
|
||||||
|
if (ops[i].type & OP_EA32) {
|
||||||
|
g(0x67);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* generate data16 prefix if needed */
|
||||||
|
p66 = 0;
|
||||||
|
if (s == 1)
|
||||||
|
p66 = 1;
|
||||||
|
else {
|
||||||
|
/* accepting mmx+sse in all operands --> needs 0x66 to
|
||||||
|
switch to sse mode. Accepting only sse in an operand --> is
|
||||||
|
already SSE insn and needs 0x66/f2/f3 handling. */
|
||||||
|
for (i = 0; i < nb_ops; i++)
|
||||||
|
if ((op_type[i] & (OP_MMX | OP_SSE)) == (OP_MMX | OP_SSE)
|
||||||
|
&& ops[i].type & OP_SSE)
|
||||||
|
p66 = 1;
|
||||||
|
}
|
||||||
|
if (p66)
|
||||||
|
g(0x66);
|
||||||
|
|
||||||
v = pa->opcode;
|
v = pa->opcode;
|
||||||
|
p = v >> 8; /* possibly prefix byte(s) */
|
||||||
|
switch (p) {
|
||||||
|
case 0: break; /* no prefix */
|
||||||
|
case 0x48: break; /* REX, handled elsewhere */
|
||||||
|
case 0x66:
|
||||||
|
case 0x67:
|
||||||
|
case 0xf2:
|
||||||
|
case 0xf3: v = v & 0xff; g(p); break;
|
||||||
|
case 0xd4: case 0xd5: break; /* aam and aad, not prefix, but hardcoded immediate argument "10" */
|
||||||
|
case 0xd8: case 0xd9: case 0xda: case 0xdb: /* x87, no normal prefix */
|
||||||
|
case 0xdc: case 0xdd: case 0xde: case 0xdf: break;
|
||||||
|
default: tcc_error("bad prefix 0x%2x in opcode table", p); break;
|
||||||
|
}
|
||||||
if (pa->instr_type & OPC_0F)
|
if (pa->instr_type & OPC_0F)
|
||||||
v = ((v & ~0xff) << 8) | 0x0f00 | (v & 0xff);
|
v = ((v & ~0xff) << 8) | 0x0f00 | (v & 0xff);
|
||||||
if ((v == 0x69 || v == 0x6b) && nb_ops == 2) {
|
if ((v == 0x69 || v == 0x6b) && nb_ops == 2) {
|
||||||
@ -977,11 +997,20 @@ again:
|
|||||||
if (pa->instr_type & OPC_MODRM) {
|
if (pa->instr_type & OPC_MODRM) {
|
||||||
if (!nb_ops) {
|
if (!nb_ops) {
|
||||||
/* A modrm opcode without operands is a special case (e.g. mfence).
|
/* A modrm opcode without operands is a special case (e.g. mfence).
|
||||||
It has a group and acts as if there's an register operand 0
|
It has a group and acts as if there's an register operand 0 */
|
||||||
(ax). */
|
|
||||||
i = 0;
|
i = 0;
|
||||||
ops[i].type = OP_REG;
|
ops[i].type = OP_REG;
|
||||||
ops[i].reg = 0;
|
#ifdef TCC_TARGET_X86_64
|
||||||
|
if (pa->sym == TOK_ASM_endbr64)
|
||||||
|
ops[i].reg = 2; // dx
|
||||||
|
else if (pa->sym >= TOK_ASM_lfence && pa->sym <= TOK_ASM_sfence)
|
||||||
|
ops[i].reg = 0; // ax
|
||||||
|
#else
|
||||||
|
if (pa->sym == TOK_ASM_endbr32)
|
||||||
|
ops[i].reg = 3; // bx
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
tcc_error("bad MODR/M opcode without operands");
|
||||||
goto modrm_found;
|
goto modrm_found;
|
||||||
}
|
}
|
||||||
/* first look for an ea operand */
|
/* first look for an ea operand */
|
||||||
@ -1055,6 +1084,8 @@ again:
|
|||||||
}
|
}
|
||||||
if (OPCT_IS(pa->instr_type, OPC_TEST))
|
if (OPCT_IS(pa->instr_type, OPC_TEST))
|
||||||
v += test_bits[opcode - pa->sym];
|
v += test_bits[opcode - pa->sym];
|
||||||
|
else if (OPCT_IS(pa->instr_type, OPC_0F01))
|
||||||
|
v |= 0x0f0100;
|
||||||
op1 = v >> 16;
|
op1 = v >> 16;
|
||||||
if (op1)
|
if (op1)
|
||||||
g(op1);
|
g(op1);
|
||||||
@ -1195,22 +1226,23 @@ static const char *skip_constraint_modifiers(const char *p)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If T (a token) is of the form "%reg" returns the register
|
/* If t (a token) is of the form "%reg" or "reg" return the register number and
|
||||||
number and type, otherwise return -1. */
|
type, otherwise return -1. With GCC the % is optional, too. */
|
||||||
ST_FUNC int asm_parse_regvar (int t)
|
ST_FUNC int asm_parse_regvar (int t)
|
||||||
{
|
{
|
||||||
const char *s;
|
const char *s;
|
||||||
Operand op;
|
Operand op;
|
||||||
if (t < TOK_IDENT)
|
if (t < TOK_IDENT || (t & SYM_FIELD))
|
||||||
return -1;
|
return -1;
|
||||||
s = table_ident[t - TOK_IDENT]->str;
|
s = table_ident[t - TOK_IDENT]->str;
|
||||||
if (s[0] != '%')
|
if (s[0] == '%')
|
||||||
return -1;
|
++s;
|
||||||
t = tok_alloc(s+1, strlen(s)-1)->tok;
|
t = tok_alloc_const(s);
|
||||||
unget_tok(t);
|
unget_tok(t);
|
||||||
|
/* Internally the % prefix is required. */
|
||||||
unget_tok('%');
|
unget_tok('%');
|
||||||
parse_operand(tcc_state, &op);
|
parse_operand(tcc_state, &op);
|
||||||
/* Accept only integer regs for now. */
|
/* Accept only integer regs for now. */
|
||||||
if (op.type & OP_REG)
|
if (op.type & OP_REG)
|
||||||
return op.reg;
|
return op.reg;
|
||||||
else
|
else
|
||||||
@ -1315,7 +1347,6 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
|||||||
if (is_reg_allocated(op->reg))
|
if (is_reg_allocated(op->reg))
|
||||||
tcc_error("asm regvar requests register that's taken already");
|
tcc_error("asm regvar requests register that's taken already");
|
||||||
reg = op->reg;
|
reg = op->reg;
|
||||||
goto reg_found;
|
|
||||||
}
|
}
|
||||||
try_next:
|
try_next:
|
||||||
c = *str++;
|
c = *str++;
|
||||||
@ -1358,12 +1389,17 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
|||||||
case 'D':
|
case 'D':
|
||||||
reg = 7;
|
reg = 7;
|
||||||
alloc_reg:
|
alloc_reg:
|
||||||
|
if (op->reg >= 0 && reg != op->reg)
|
||||||
|
goto try_next;
|
||||||
if (is_reg_allocated(reg))
|
if (is_reg_allocated(reg))
|
||||||
goto try_next;
|
goto try_next;
|
||||||
goto reg_found;
|
goto reg_found;
|
||||||
case 'q':
|
case 'q':
|
||||||
/* eax, ebx, ecx or edx */
|
/* eax, ebx, ecx or edx */
|
||||||
for(reg = 0; reg < 4; reg++) {
|
if (op->reg >= 0) {
|
||||||
|
if ((reg = op->reg) < 4)
|
||||||
|
goto reg_found;
|
||||||
|
} else for(reg = 0; reg < 4; reg++) {
|
||||||
if (!is_reg_allocated(reg))
|
if (!is_reg_allocated(reg))
|
||||||
goto reg_found;
|
goto reg_found;
|
||||||
}
|
}
|
||||||
@ -1372,7 +1408,9 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
|||||||
case 'R':
|
case 'R':
|
||||||
case 'p': /* A general address, for x86(64) any register is acceptable*/
|
case 'p': /* A general address, for x86(64) any register is acceptable*/
|
||||||
/* any general register */
|
/* any general register */
|
||||||
for(reg = 0; reg < 8; reg++) {
|
if ((reg = op->reg) >= 0)
|
||||||
|
goto reg_found;
|
||||||
|
else for(reg = 0; reg < NB_ASM_REGS; reg++) {
|
||||||
if (!is_reg_allocated(reg))
|
if (!is_reg_allocated(reg))
|
||||||
goto reg_found;
|
goto reg_found;
|
||||||
}
|
}
|
||||||
@ -1407,7 +1445,7 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
|||||||
if (j < nb_outputs || c == 'm') {
|
if (j < nb_outputs || c == 'm') {
|
||||||
if ((op->vt->r & VT_VALMASK) == VT_LLOCAL) {
|
if ((op->vt->r & VT_VALMASK) == VT_LLOCAL) {
|
||||||
/* any general register */
|
/* any general register */
|
||||||
for(reg = 0; reg < 8; reg++) {
|
for(reg = 0; reg < NB_ASM_REGS; reg++) {
|
||||||
if (!(regs_allocated[reg] & REG_IN_MASK))
|
if (!(regs_allocated[reg] & REG_IN_MASK))
|
||||||
goto reg_found1;
|
goto reg_found1;
|
||||||
}
|
}
|
||||||
@ -1440,7 +1478,7 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
|||||||
if (op->reg >= 0 &&
|
if (op->reg >= 0 &&
|
||||||
(op->vt->r & VT_VALMASK) == VT_LLOCAL &&
|
(op->vt->r & VT_VALMASK) == VT_LLOCAL &&
|
||||||
!op->is_memory) {
|
!op->is_memory) {
|
||||||
for(reg = 0; reg < 8; reg++) {
|
for(reg = 0; reg < NB_ASM_REGS; reg++) {
|
||||||
if (!(regs_allocated[reg] & REG_OUT_MASK))
|
if (!(regs_allocated[reg] & REG_OUT_MASK))
|
||||||
goto reg_found2;
|
goto reg_found2;
|
||||||
}
|
}
|
||||||
@ -1472,7 +1510,6 @@ ST_FUNC void subst_asm_operand(CString *add_str,
|
|||||||
SValue *sv, int modifier)
|
SValue *sv, int modifier)
|
||||||
{
|
{
|
||||||
int r, reg, size, val;
|
int r, reg, size, val;
|
||||||
char buf[64];
|
|
||||||
|
|
||||||
r = sv->r;
|
r = sv->r;
|
||||||
if ((r & VT_VALMASK) == VT_CONST) {
|
if ((r & VT_VALMASK) == VT_CONST) {
|
||||||
@ -1487,8 +1524,10 @@ ST_FUNC void subst_asm_operand(CString *add_str,
|
|||||||
in the C symbol table when later looking up
|
in the C symbol table when later looking up
|
||||||
this name. So enter them now into the asm label
|
this name. So enter them now into the asm label
|
||||||
list when we still know the symbol. */
|
list when we still know the symbol. */
|
||||||
get_asm_sym(tok_alloc(name, strlen(name))->tok, sv->sym);
|
get_asm_sym(tok_alloc_const(name), sv->sym);
|
||||||
}
|
}
|
||||||
|
if (tcc_state->leading_underscore)
|
||||||
|
cstr_ccat(add_str, '_');
|
||||||
cstr_cat(add_str, name, -1);
|
cstr_cat(add_str, name, -1);
|
||||||
if ((uint32_t)sv->c.i == 0)
|
if ((uint32_t)sv->c.i == 0)
|
||||||
goto no_offset;
|
goto no_offset;
|
||||||
@ -1497,37 +1536,24 @@ ST_FUNC void subst_asm_operand(CString *add_str,
|
|||||||
val = sv->c.i;
|
val = sv->c.i;
|
||||||
if (modifier == 'n')
|
if (modifier == 'n')
|
||||||
val = -val;
|
val = -val;
|
||||||
snprintf(buf, sizeof(buf), "%d", (int)sv->c.i);
|
cstr_printf(add_str, "%d", (int)sv->c.i);
|
||||||
cstr_cat(add_str, buf, -1);
|
|
||||||
no_offset:;
|
no_offset:;
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
if (r & VT_LVAL)
|
if (r & VT_LVAL)
|
||||||
cstr_cat(add_str, "(%rip)", -1);
|
cstr_cat(add_str, "(%rip)", -1);
|
||||||
#endif
|
#endif
|
||||||
} else if ((r & VT_VALMASK) == VT_LOCAL) {
|
} else if ((r & VT_VALMASK) == VT_LOCAL) {
|
||||||
#ifdef TCC_TARGET_X86_64
|
cstr_printf(add_str, "%d(%%%s)", (int)sv->c.i, get_tok_str(TOK_ASM_xax + 5, NULL));
|
||||||
snprintf(buf, sizeof(buf), "%d(%%rbp)", (int)sv->c.i);
|
|
||||||
#else
|
|
||||||
snprintf(buf, sizeof(buf), "%d(%%ebp)", (int)sv->c.i);
|
|
||||||
#endif
|
|
||||||
cstr_cat(add_str, buf, -1);
|
|
||||||
} else if (r & VT_LVAL) {
|
} else if (r & VT_LVAL) {
|
||||||
reg = r & VT_VALMASK;
|
reg = r & VT_VALMASK;
|
||||||
if (reg >= VT_CONST)
|
if (reg >= VT_CONST)
|
||||||
tcc_error("internal compiler error");
|
tcc_internal_error("");
|
||||||
snprintf(buf, sizeof(buf), "(%%%s)",
|
cstr_printf(add_str, "(%%%s)", get_tok_str(TOK_ASM_xax + reg, NULL));
|
||||||
#ifdef TCC_TARGET_X86_64
|
|
||||||
get_tok_str(TOK_ASM_rax + reg, NULL)
|
|
||||||
#else
|
|
||||||
get_tok_str(TOK_ASM_eax + reg, NULL)
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
cstr_cat(add_str, buf, -1);
|
|
||||||
} else {
|
} else {
|
||||||
/* register case */
|
/* register case */
|
||||||
reg = r & VT_VALMASK;
|
reg = r & VT_VALMASK;
|
||||||
if (reg >= VT_CONST)
|
if (reg >= VT_CONST)
|
||||||
tcc_error("internal compiler error");
|
tcc_internal_error("");
|
||||||
|
|
||||||
/* choose register operand size */
|
/* choose register operand size */
|
||||||
if ((sv->type.t & VT_BTYPE) == VT_BYTE ||
|
if ((sv->type.t & VT_BTYPE) == VT_BYTE ||
|
||||||
@ -1563,6 +1589,10 @@ ST_FUNC void subst_asm_operand(CString *add_str,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (reg >= 8) {
|
||||||
|
cstr_printf(add_str, "%%r%d%c", reg, (size == 1) ? 'b' : ((size == 2) ? 'w' : ((size == 4) ? 'd' : ' ')));
|
||||||
|
return;
|
||||||
|
}
|
||||||
switch(size) {
|
switch(size) {
|
||||||
case -1:
|
case -1:
|
||||||
reg = TOK_ASM_ah + reg;
|
reg = TOK_ASM_ah + reg;
|
||||||
@ -1582,8 +1612,7 @@ ST_FUNC void subst_asm_operand(CString *add_str,
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
snprintf(buf, sizeof(buf), "%%%s", get_tok_str(reg, NULL));
|
cstr_printf(add_str, "%%%s", get_tok_str(reg, NULL));
|
||||||
cstr_cat(add_str, buf, -1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1601,12 +1630,12 @@ ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
|
|||||||
call-preserved registers, but currently it doesn't matter. */
|
call-preserved registers, but currently it doesn't matter. */
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
static uint8_t reg_saved[] = { 3, 6, 7, 12, 13, 14, 15 };
|
static const uint8_t reg_saved[] = { 3, 6, 7, 12, 13, 14, 15 };
|
||||||
#else
|
#else
|
||||||
static uint8_t reg_saved[] = { 3, 12, 13, 14, 15 };
|
static const uint8_t reg_saved[] = { 3, 12, 13, 14, 15 };
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
static uint8_t reg_saved[] = { 3, 6, 7 };
|
static const uint8_t reg_saved[] = { 3, 6, 7 };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* mark all used registers */
|
/* mark all used registers */
|
||||||
@ -1695,7 +1724,6 @@ ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
|
|||||||
ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str)
|
ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str)
|
||||||
{
|
{
|
||||||
int reg;
|
int reg;
|
||||||
TokenSym *ts;
|
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
unsigned int type;
|
unsigned int type;
|
||||||
#endif
|
#endif
|
||||||
@ -1704,8 +1732,7 @@ ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str)
|
|||||||
!strcmp(str, "cc") ||
|
!strcmp(str, "cc") ||
|
||||||
!strcmp(str, "flags"))
|
!strcmp(str, "flags"))
|
||||||
return;
|
return;
|
||||||
ts = tok_alloc(str, strlen(str));
|
reg = tok_alloc_const(str);
|
||||||
reg = ts->tok;
|
|
||||||
if (reg >= TOK_ASM_eax && reg <= TOK_ASM_edi) {
|
if (reg >= TOK_ASM_eax && reg <= TOK_ASM_edi) {
|
||||||
reg -= TOK_ASM_eax;
|
reg -= TOK_ASM_eax;
|
||||||
} else if (reg >= TOK_ASM_ax && reg <= TOK_ASM_di) {
|
} else if (reg >= TOK_ASM_ax && reg <= TOK_ASM_di) {
|
||||||
|
|||||||
12
i386-asm.h
12
i386-asm.h
@ -37,7 +37,10 @@
|
|||||||
DEF_ASM_OP0(pause, 0xf390)
|
DEF_ASM_OP0(pause, 0xf390)
|
||||||
DEF_ASM_OP0(xlat, 0xd7)
|
DEF_ASM_OP0(xlat, 0xd7)
|
||||||
|
|
||||||
/* strings */
|
/* Control-Flow Enforcement */
|
||||||
|
DEF_ASM_OP0L(endbr32, 0xf30f1e, 7, OPC_MODRM)
|
||||||
|
|
||||||
|
/* strings */
|
||||||
ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWLX))
|
ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWLX))
|
||||||
ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWLX))
|
ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWLX))
|
||||||
|
|
||||||
@ -73,6 +76,11 @@ ALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW | OPT_EA
|
|||||||
ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_REGW | OPT_EA))
|
ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_REGW | OPT_EA))
|
||||||
ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW | OPT_EA))
|
ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW | OPT_EA))
|
||||||
|
|
||||||
|
ALT(DEF_ASM_OP2(popcntw, 0xf30fb8, 0, OPC_MODRM | OPC_WLX, OPT_REGW | OPT_EA, OPT_REGW))
|
||||||
|
|
||||||
|
ALT(DEF_ASM_OP2(tzcntw, 0xf30fbc, 0, OPC_MODRM | OPC_WLX, OPT_REGW | OPT_EA, OPT_REGW))
|
||||||
|
ALT(DEF_ASM_OP2(lzcntw, 0xf30fbd, 0, OPC_MODRM | OPC_WLX, OPT_REGW | OPT_EA, OPT_REGW))
|
||||||
|
|
||||||
/* prefixes */
|
/* prefixes */
|
||||||
DEF_ASM_OP0(wait, 0x9b)
|
DEF_ASM_OP0(wait, 0x9b)
|
||||||
DEF_ASM_OP0(fwait, 0x9b)
|
DEF_ASM_OP0(fwait, 0x9b)
|
||||||
@ -447,6 +455,8 @@ ALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMXSSE ))
|
|||||||
DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
|
||||||
|
|
||||||
/* sse */
|
/* sse */
|
||||||
|
DEF_ASM_OP1(ldmxcsr, 0x0fae, 2, OPC_MODRM, OPT_EA)
|
||||||
|
DEF_ASM_OP1(stmxcsr, 0x0fae, 3, OPC_MODRM, OPT_EA)
|
||||||
DEF_ASM_OP2(movups, 0x0f10, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_SSE )
|
DEF_ASM_OP2(movups, 0x0f10, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_SSE )
|
||||||
ALT(DEF_ASM_OP2(movups, 0x0f11, 0, OPC_MODRM, OPT_SSE, OPT_EA | OPT_REG32 ))
|
ALT(DEF_ASM_OP2(movups, 0x0f11, 0, OPC_MODRM, OPT_SSE, OPT_EA | OPT_REG32 ))
|
||||||
DEF_ASM_OP2(movaps, 0x0f28, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_SSE )
|
DEF_ASM_OP2(movaps, 0x0f28, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_SSE )
|
||||||
|
|||||||
768
i386-gen.c
768
i386-gen.c
File diff suppressed because it is too large
Load Diff
161
i386-link.c
161
i386-link.c
@ -15,16 +15,21 @@
|
|||||||
#define ELF_START_ADDR 0x08048000
|
#define ELF_START_ADDR 0x08048000
|
||||||
#define ELF_PAGE_SIZE 0x1000
|
#define ELF_PAGE_SIZE 0x1000
|
||||||
|
|
||||||
|
#if defined CONFIG_TCC_PIC
|
||||||
|
#define PCRELATIVE_DLLPLT 1
|
||||||
|
#else
|
||||||
#define PCRELATIVE_DLLPLT 0
|
#define PCRELATIVE_DLLPLT 0
|
||||||
#define RELOCATE_DLLPLT 0
|
#endif
|
||||||
|
#define RELOCATE_DLLPLT 1
|
||||||
|
|
||||||
#else /* !TARGET_DEFS_ONLY */
|
#else /* !TARGET_DEFS_ONLY */
|
||||||
|
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
|
|
||||||
|
#ifdef NEED_RELOC_TYPE
|
||||||
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
|
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
|
||||||
relocations, returns -1. */
|
relocations, returns -1. */
|
||||||
int code_reloc (int reloc_type)
|
ST_FUNC int code_reloc (int reloc_type)
|
||||||
{
|
{
|
||||||
switch (reloc_type) {
|
switch (reloc_type) {
|
||||||
case R_386_RELATIVE:
|
case R_386_RELATIVE:
|
||||||
@ -36,6 +41,10 @@ int code_reloc (int reloc_type)
|
|||||||
case R_386_GOT32X:
|
case R_386_GOT32X:
|
||||||
case R_386_GLOB_DAT:
|
case R_386_GLOB_DAT:
|
||||||
case R_386_COPY:
|
case R_386_COPY:
|
||||||
|
case R_386_TLS_GD:
|
||||||
|
case R_386_TLS_LDM:
|
||||||
|
case R_386_TLS_LDO_32:
|
||||||
|
case R_386_TLS_LE:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case R_386_PC16:
|
case R_386_PC16:
|
||||||
@ -44,15 +53,13 @@ int code_reloc (int reloc_type)
|
|||||||
case R_386_JMP_SLOT:
|
case R_386_JMP_SLOT:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
tcc_error ("Unknown relocation type: %d", reloc_type);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns an enumerator to describe whether and when the relocation needs a
|
/* Returns an enumerator to describe whether and when the relocation needs a
|
||||||
GOT and/or PLT entry to be created. See tcc.h for a description of the
|
GOT and/or PLT entry to be created. See tcc.h for a description of the
|
||||||
different values. */
|
different values. */
|
||||||
int gotplt_entry_type (int reloc_type)
|
ST_FUNC int gotplt_entry_type (int reloc_type)
|
||||||
{
|
{
|
||||||
switch (reloc_type) {
|
switch (reloc_type) {
|
||||||
case R_386_RELATIVE:
|
case R_386_RELATIVE:
|
||||||
@ -79,13 +86,16 @@ int gotplt_entry_type (int reloc_type)
|
|||||||
case R_386_GOT32:
|
case R_386_GOT32:
|
||||||
case R_386_GOT32X:
|
case R_386_GOT32X:
|
||||||
case R_386_PLT32:
|
case R_386_PLT32:
|
||||||
|
case R_386_TLS_GD:
|
||||||
|
case R_386_TLS_LDM:
|
||||||
|
case R_386_TLS_LDO_32:
|
||||||
|
case R_386_TLS_LE:
|
||||||
return ALWAYS_GOTPLT_ENTRY;
|
return ALWAYS_GOTPLT_ENTRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
tcc_error ("Unknown relocation type: %d", reloc_type);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef NEED_BUILD_GOT
|
||||||
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
|
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
|
||||||
{
|
{
|
||||||
Section *plt = s1->plt;
|
Section *plt = s1->plt;
|
||||||
@ -94,7 +104,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
|
|||||||
unsigned plt_offset, relofs;
|
unsigned plt_offset, relofs;
|
||||||
|
|
||||||
/* on i386 if we build a DLL, we add a %ebx offset */
|
/* on i386 if we build a DLL, we add a %ebx offset */
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL)
|
if (s1->output_type & TCC_OUTPUT_DYN)
|
||||||
modrm = 0xa3;
|
modrm = 0xa3;
|
||||||
else
|
else
|
||||||
modrm = 0x25;
|
modrm = 0x25;
|
||||||
@ -116,7 +126,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
|
|||||||
/* The PLT slot refers to the relocation entry it needs via offset.
|
/* The PLT slot refers to the relocation entry it needs via offset.
|
||||||
The reloc entry is created below, so its offset is the current
|
The reloc entry is created below, so its offset is the current
|
||||||
data_offset */
|
data_offset */
|
||||||
relofs = s1->got->reloc ? s1->got->reloc->data_offset : 0;
|
relofs = s1->plt->reloc ? s1->plt->reloc->data_offset : 0;
|
||||||
|
|
||||||
/* Jump to GOT entry where ld.so initially put the address of ip + 4 */
|
/* Jump to GOT entry where ld.so initially put the address of ip + 4 */
|
||||||
p = section_ptr_add(plt, 16);
|
p = section_ptr_add(plt, 16);
|
||||||
@ -124,7 +134,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
|
|||||||
p[1] = modrm;
|
p[1] = modrm;
|
||||||
write32le(p + 2, got_offset);
|
write32le(p + 2, got_offset);
|
||||||
p[6] = 0x68; /* push $xxx */
|
p[6] = 0x68; /* push $xxx */
|
||||||
write32le(p + 7, relofs);
|
write32le(p + 7, relofs - sizeof (ElfW_Rel));
|
||||||
p[11] = 0xe9; /* jmp plt_start */
|
p[11] = 0xe9; /* jmp plt_start */
|
||||||
write32le(p + 12, -(plt->data_offset));
|
write32le(p + 12, -(plt->data_offset));
|
||||||
return plt_offset;
|
return plt_offset;
|
||||||
@ -142,7 +152,7 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
|||||||
p = s1->plt->data;
|
p = s1->plt->data;
|
||||||
p_end = p + s1->plt->data_offset;
|
p_end = p + s1->plt->data_offset;
|
||||||
|
|
||||||
if (p < p_end) {
|
if (!(s1->output_type & TCC_OUTPUT_DYN) && p < p_end) {
|
||||||
add32le(p + 2, s1->got->sh_addr);
|
add32le(p + 2, s1->got->sh_addr);
|
||||||
add32le(p + 8, s1->got->sh_addr);
|
add32le(p + 8, s1->got->sh_addr);
|
||||||
p += 16;
|
p += 16;
|
||||||
@ -151,16 +161,21 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
|||||||
p += 16;
|
p += 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s1->plt->reloc) {
|
||||||
|
ElfW_Rel *rel;
|
||||||
|
int x = s1->plt->sh_addr + 16 + 6;
|
||||||
|
p = s1->got->data;
|
||||||
|
for_each_elem(s1->plt->reloc, 0, rel, ElfW_Rel) {
|
||||||
|
write32le(p + rel->r_offset, x);
|
||||||
|
x += 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
static ElfW_Rel *qrel; /* ptr to next reloc entry reused */
|
ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
||||||
|
|
||||||
void relocate_init(Section *sr)
|
|
||||||
{
|
|
||||||
qrel = (ElfW_Rel *) sr->data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
|
||||||
{
|
{
|
||||||
int sym_index, esym_index;
|
int sym_index, esym_index;
|
||||||
|
|
||||||
@ -168,8 +183,8 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case R_386_32:
|
case R_386_32:
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL) {
|
if (s1->output_type & TCC_OUTPUT_DYN) {
|
||||||
esym_index = s1->sym_attrs[sym_index].dyn_index;
|
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
|
||||||
qrel->r_offset = rel->r_offset;
|
qrel->r_offset = rel->r_offset;
|
||||||
if (esym_index) {
|
if (esym_index) {
|
||||||
qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
|
qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
|
||||||
@ -185,7 +200,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
case R_386_PC32:
|
case R_386_PC32:
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL) {
|
if (s1->output_type == TCC_OUTPUT_DLL) {
|
||||||
/* DLL relocation */
|
/* DLL relocation */
|
||||||
esym_index = s1->sym_attrs[sym_index].dyn_index;
|
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
|
||||||
if (esym_index) {
|
if (esym_index) {
|
||||||
qrel->r_offset = rel->r_offset;
|
qrel->r_offset = rel->r_offset;
|
||||||
qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
|
qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
|
||||||
@ -211,12 +226,12 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
case R_386_GOT32:
|
case R_386_GOT32:
|
||||||
case R_386_GOT32X:
|
case R_386_GOT32X:
|
||||||
/* we load the got offset */
|
/* we load the got offset */
|
||||||
add32le(ptr, s1->sym_attrs[sym_index].got_offset);
|
add32le(ptr, get_sym_attr(s1, sym_index, 0)->got_offset);
|
||||||
return;
|
return;
|
||||||
case R_386_16:
|
case R_386_16:
|
||||||
if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
|
if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
|
||||||
output_file:
|
output_file:
|
||||||
tcc_error("can only produce 16-bit binary files");
|
tcc_error_noabort("can only produce 16-bit binary files");
|
||||||
}
|
}
|
||||||
write16le(ptr, read16le(ptr) + val);
|
write16le(ptr, read16le(ptr) + val);
|
||||||
return;
|
return;
|
||||||
@ -237,6 +252,104 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
(to remove noise of default case). Is this true?
|
(to remove noise of default case). Is this true?
|
||||||
*/
|
*/
|
||||||
return;
|
return;
|
||||||
|
case R_386_TLS_GD:
|
||||||
|
{
|
||||||
|
static const unsigned char expect[] = {
|
||||||
|
/* lea 0(,%ebx,1),%eax */
|
||||||
|
0x8d, 0x04, 0x1d, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
/* call __tls_get_addr@PLT */
|
||||||
|
0xe8, 0xfc, 0xff, 0xff, 0xff };
|
||||||
|
static const unsigned char replace[] = {
|
||||||
|
/* mov %gs:0,%eax */
|
||||||
|
0x65, 0xa1, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
/* sub 0,%eax */
|
||||||
|
0x81, 0xe8, 0x00, 0x00, 0x00, 0x00 };
|
||||||
|
|
||||||
|
if (memcmp (ptr-3, expect, sizeof(expect)) == 0) {
|
||||||
|
ElfW(Sym) *sym;
|
||||||
|
Section *sec;
|
||||||
|
int32_t x;
|
||||||
|
|
||||||
|
memcpy(ptr-3, replace, sizeof(replace));
|
||||||
|
rel[1].r_info = ELFW(R_INFO)(0, R_386_NONE);
|
||||||
|
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||||
|
sec = s1->sections[sym->st_shndx];
|
||||||
|
x = sym->st_value - sec->sh_addr - sec->data_offset;
|
||||||
|
add32le(ptr + 5, -x);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tcc_error_noabort("unexpected R_386_TLS_GD pattern");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case R_386_TLS_LDM:
|
||||||
|
{
|
||||||
|
static const unsigned char expect[] = {
|
||||||
|
/* lea 0(%ebx),%eax */
|
||||||
|
0x8d, 0x83, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
/* call __tls_get_addr@PLT */
|
||||||
|
0xe8, 0xfc, 0xff, 0xff, 0xff };
|
||||||
|
static const unsigned char replace[] = {
|
||||||
|
/* mov %gs:0,%eax */
|
||||||
|
0x65, 0xa1, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
/* nop */
|
||||||
|
0x90,
|
||||||
|
/* lea 0(%esi,%eiz,1),%esi */
|
||||||
|
0x8d, 0x74, 0x26, 0x00 };
|
||||||
|
|
||||||
|
if (memcmp (ptr-2, expect, sizeof(expect)) == 0) {
|
||||||
|
memcpy(ptr-2, replace, sizeof(replace));
|
||||||
|
rel[1].r_info = ELFW(R_INFO)(0, R_386_NONE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tcc_error_noabort("unexpected R_386_TLS_LDM pattern");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case R_386_TLS_LDO_32:
|
||||||
|
{
|
||||||
|
ElfW(Sym) *sym;
|
||||||
|
Section *sec;
|
||||||
|
int32_t x;
|
||||||
|
|
||||||
|
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||||
|
sec = s1->sections[sym->st_shndx];
|
||||||
|
x = val - sec->sh_addr - sec->data_offset;
|
||||||
|
add32le(ptr, x);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case R_386_TLS_LE:
|
||||||
|
{
|
||||||
|
ElfW(Sym) *sym;
|
||||||
|
Section *sec;
|
||||||
|
int32_t x;
|
||||||
|
addr_t tls_start = 0, tls_end = 0, tls_align = 1;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||||
|
sec = s1->sections[sym->st_shndx];
|
||||||
|
|
||||||
|
for (i = 1; i < s1->nb_sections; i++) {
|
||||||
|
Section *s = s1->sections[i];
|
||||||
|
if (s->sh_flags & SHF_TLS && s->sh_size) {
|
||||||
|
if (!tls_start || s->sh_addr < tls_start)
|
||||||
|
tls_start = s->sh_addr;
|
||||||
|
if (s->sh_addr + s->sh_size > tls_end)
|
||||||
|
tls_end = s->sh_addr + s->sh_size;
|
||||||
|
if (s->sh_addralign > tls_align)
|
||||||
|
tls_align = s->sh_addralign;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tls_end > tls_start) {
|
||||||
|
addr_t tls_size = tls_end - tls_start;
|
||||||
|
addr_t aligned_size = (tls_size + tls_align - 1) & ~(tls_align - 1);
|
||||||
|
x = val - (tls_start + aligned_size);
|
||||||
|
} else {
|
||||||
|
x = val - sec->sh_addr - sec->data_offset;
|
||||||
|
}
|
||||||
|
add32le(ptr, x);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case R_386_NONE:
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr,"FIXME: handle reloc type %d at %x [%p] to %x\n",
|
fprintf(stderr,"FIXME: handle reloc type %d at %x [%p] to %x\n",
|
||||||
type, (unsigned)addr, ptr, (unsigned)val);
|
type, (unsigned)addr, ptr, (unsigned)val);
|
||||||
|
|||||||
79
i386-tok.h
79
i386-tok.h
@ -1,6 +1,82 @@
|
|||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
/* WARNING: relative order of tokens is important. */
|
/* WARNING: relative order of tokens is important. */
|
||||||
|
|
||||||
|
#define DEF_BWL(x) \
|
||||||
|
DEF(TOK_ASM_ ## x ## b, #x "b") \
|
||||||
|
DEF(TOK_ASM_ ## x ## w, #x "w") \
|
||||||
|
DEF(TOK_ASM_ ## x ## l, #x "l") \
|
||||||
|
DEF(TOK_ASM_ ## x, #x)
|
||||||
|
#define DEF_WL(x) \
|
||||||
|
DEF(TOK_ASM_ ## x ## w, #x "w") \
|
||||||
|
DEF(TOK_ASM_ ## x ## l, #x "l") \
|
||||||
|
DEF(TOK_ASM_ ## x, #x)
|
||||||
|
#ifdef TCC_TARGET_X86_64
|
||||||
|
# define DEF_BWLQ(x) \
|
||||||
|
DEF(TOK_ASM_ ## x ## b, #x "b") \
|
||||||
|
DEF(TOK_ASM_ ## x ## w, #x "w") \
|
||||||
|
DEF(TOK_ASM_ ## x ## l, #x "l") \
|
||||||
|
DEF(TOK_ASM_ ## x ## q, #x "q") \
|
||||||
|
DEF(TOK_ASM_ ## x, #x)
|
||||||
|
# define DEF_WLQ(x) \
|
||||||
|
DEF(TOK_ASM_ ## x ## w, #x "w") \
|
||||||
|
DEF(TOK_ASM_ ## x ## l, #x "l") \
|
||||||
|
DEF(TOK_ASM_ ## x ## q, #x "q") \
|
||||||
|
DEF(TOK_ASM_ ## x, #x)
|
||||||
|
# define DEF_BWLX DEF_BWLQ
|
||||||
|
# define DEF_WLX DEF_WLQ
|
||||||
|
/* number of sizes + 1 */
|
||||||
|
# define NBWLX 5
|
||||||
|
#else
|
||||||
|
# define DEF_BWLX DEF_BWL
|
||||||
|
# define DEF_WLX DEF_WL
|
||||||
|
/* number of sizes + 1 */
|
||||||
|
# define NBWLX 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DEF_FP1(x) \
|
||||||
|
DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
|
||||||
|
DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
|
||||||
|
DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
|
||||||
|
DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
|
||||||
|
|
||||||
|
#define DEF_FP(x) \
|
||||||
|
DEF(TOK_ASM_ ## f ## x, "f" #x ) \
|
||||||
|
DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
|
||||||
|
DEF_FP1(x)
|
||||||
|
|
||||||
|
#define DEF_ASMTEST(x,suffix) \
|
||||||
|
DEF_ASM(x ## o ## suffix) \
|
||||||
|
DEF_ASM(x ## no ## suffix) \
|
||||||
|
DEF_ASM(x ## b ## suffix) \
|
||||||
|
DEF_ASM(x ## c ## suffix) \
|
||||||
|
DEF_ASM(x ## nae ## suffix) \
|
||||||
|
DEF_ASM(x ## nb ## suffix) \
|
||||||
|
DEF_ASM(x ## nc ## suffix) \
|
||||||
|
DEF_ASM(x ## ae ## suffix) \
|
||||||
|
DEF_ASM(x ## e ## suffix) \
|
||||||
|
DEF_ASM(x ## z ## suffix) \
|
||||||
|
DEF_ASM(x ## ne ## suffix) \
|
||||||
|
DEF_ASM(x ## nz ## suffix) \
|
||||||
|
DEF_ASM(x ## be ## suffix) \
|
||||||
|
DEF_ASM(x ## na ## suffix) \
|
||||||
|
DEF_ASM(x ## nbe ## suffix) \
|
||||||
|
DEF_ASM(x ## a ## suffix) \
|
||||||
|
DEF_ASM(x ## s ## suffix) \
|
||||||
|
DEF_ASM(x ## ns ## suffix) \
|
||||||
|
DEF_ASM(x ## p ## suffix) \
|
||||||
|
DEF_ASM(x ## pe ## suffix) \
|
||||||
|
DEF_ASM(x ## np ## suffix) \
|
||||||
|
DEF_ASM(x ## po ## suffix) \
|
||||||
|
DEF_ASM(x ## l ## suffix) \
|
||||||
|
DEF_ASM(x ## nge ## suffix) \
|
||||||
|
DEF_ASM(x ## nl ## suffix) \
|
||||||
|
DEF_ASM(x ## ge ## suffix) \
|
||||||
|
DEF_ASM(x ## le ## suffix) \
|
||||||
|
DEF_ASM(x ## ng ## suffix) \
|
||||||
|
DEF_ASM(x ## nle ## suffix) \
|
||||||
|
DEF_ASM(x ## g ## suffix)
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
/* register */
|
/* register */
|
||||||
DEF_ASM(al)
|
DEF_ASM(al)
|
||||||
DEF_ASM(cl)
|
DEF_ASM(cl)
|
||||||
@ -192,6 +268,9 @@
|
|||||||
DEF_WLX(bts)
|
DEF_WLX(bts)
|
||||||
DEF_WLX(btr)
|
DEF_WLX(btr)
|
||||||
DEF_WLX(btc)
|
DEF_WLX(btc)
|
||||||
|
DEF_WLX(popcnt)
|
||||||
|
DEF_WLX(tzcnt)
|
||||||
|
DEF_WLX(lzcnt)
|
||||||
|
|
||||||
DEF_WLX(lar)
|
DEF_WLX(lar)
|
||||||
DEF_WLX(lsl)
|
DEF_WLX(lsl)
|
||||||
|
|||||||
@ -38,19 +38,37 @@
|
|||||||
#define LDBL_MAX_EXP 16384
|
#define LDBL_MAX_EXP 16384
|
||||||
#define LDBL_MAX 1.18973149535723176502e+4932L
|
#define LDBL_MAX 1.18973149535723176502e+4932L
|
||||||
#define LDBL_MAX_10_EXP 4932
|
#define LDBL_MAX_10_EXP 4932
|
||||||
|
#define DECIMAL_DIG 21
|
||||||
|
|
||||||
|
#elif defined __aarch64__ || defined __riscv
|
||||||
|
/*
|
||||||
|
* Use values from:
|
||||||
|
* gcc -dM -E -xc /dev/null | grep LDBL | sed -e "s/__//g"
|
||||||
|
*/
|
||||||
|
#define LDBL_MANT_DIG 113
|
||||||
|
#define LDBL_DIG 33
|
||||||
|
#define LDBL_EPSILON 1.92592994438723585305597794258492732e-34L
|
||||||
|
#define LDBL_MIN_EXP (-16381)
|
||||||
|
#define LDBL_MIN 3.36210314311209350626267781732175260e-4932L
|
||||||
|
#define LDBL_MIN_10_EXP (-4931)
|
||||||
|
#define LDBL_MAX_EXP 16384
|
||||||
|
#define LDBL_MAX 1.18973149535723176508575932662800702e+4932L
|
||||||
|
#define LDBL_MAX_10_EXP 4932
|
||||||
|
#define DECIMAL_DIG 36
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
/* same as IEEE double */
|
/* same as IEEE double */
|
||||||
#define LDBL_MANT_DIG 53
|
#define LDBL_MANT_DIG 53
|
||||||
#define LDBL_DIG 15
|
#define LDBL_DIG 15
|
||||||
#define LDBL_EPSILON 2.2204460492503131e-16
|
#define LDBL_EPSILON 2.2204460492503131e-16L
|
||||||
#define LDBL_MIN_EXP (-1021)
|
#define LDBL_MIN_EXP (-1021)
|
||||||
#define LDBL_MIN 2.2250738585072014e-308
|
#define LDBL_MIN 2.2250738585072014e-308L
|
||||||
#define LDBL_MIN_10_EXP (-307)
|
#define LDBL_MIN_10_EXP (-307)
|
||||||
#define LDBL_MAX_EXP 1024
|
#define LDBL_MAX_EXP 1024
|
||||||
#define LDBL_MAX 1.7976931348623157e+308
|
#define LDBL_MAX 1.7976931348623157e+308L
|
||||||
#define LDBL_MAX_10_EXP 308
|
#define LDBL_MAX_10_EXP 308
|
||||||
|
#define DECIMAL_DIG 17
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
16
include/stdalign.h
Normal file
16
include/stdalign.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef _STDALIGN_H
|
||||||
|
#define _STDALIGN_H
|
||||||
|
|
||||||
|
#if __STDC_VERSION__ < 201112L && (defined(__GNUC__) || defined(__TINYC__))
|
||||||
|
# define _Alignas(t) __attribute__((__aligned__(t)))
|
||||||
|
# define _Alignof(t) __alignof__(t)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define alignas _Alignas
|
||||||
|
#define alignof _Alignof
|
||||||
|
|
||||||
|
#define __alignas_is_defined 1
|
||||||
|
#define __alignof_is_defined 1
|
||||||
|
|
||||||
|
#endif /* _STDALIGN_H */
|
||||||
|
|
||||||
@ -1,76 +1,11 @@
|
|||||||
#ifndef _STDARG_H
|
#ifndef _STDARG_H
|
||||||
#define _STDARG_H
|
#define _STDARG_H
|
||||||
|
|
||||||
#ifdef __x86_64__
|
typedef __builtin_va_list va_list;
|
||||||
#ifndef _WIN64
|
#define va_start __builtin_va_start
|
||||||
|
#define va_arg __builtin_va_arg
|
||||||
//This should be in sync with the declaration on our lib/libtcc1.c
|
#define va_copy __builtin_va_copy
|
||||||
/* GCC compatible definition of va_list. */
|
#define va_end __builtin_va_end
|
||||||
typedef struct {
|
|
||||||
unsigned int gp_offset;
|
|
||||||
unsigned int fp_offset;
|
|
||||||
union {
|
|
||||||
unsigned int overflow_offset;
|
|
||||||
char *overflow_arg_area;
|
|
||||||
};
|
|
||||||
char *reg_save_area;
|
|
||||||
} __va_list_struct;
|
|
||||||
|
|
||||||
typedef __va_list_struct va_list[1];
|
|
||||||
|
|
||||||
void __va_start(__va_list_struct *ap, void *fp);
|
|
||||||
void *__va_arg(__va_list_struct *ap, int arg_type, int size, int align);
|
|
||||||
|
|
||||||
#define va_start(ap, last) __va_start(ap, __builtin_frame_address(0))
|
|
||||||
#define va_arg(ap, type) \
|
|
||||||
(*(type *)(__va_arg(ap, __builtin_va_arg_types(type), sizeof(type), __alignof__(type))))
|
|
||||||
#define va_copy(dest, src) (*(dest) = *(src))
|
|
||||||
#define va_end(ap)
|
|
||||||
|
|
||||||
/* avoid conflicting definition for va_list on Macs. */
|
|
||||||
#define _VA_LIST_T
|
|
||||||
|
|
||||||
#else /* _WIN64 */
|
|
||||||
typedef char *va_list;
|
|
||||||
#define va_start(ap,last) __builtin_va_start(ap,last)
|
|
||||||
#define va_arg(ap, t) ((sizeof(t) > 8 || (sizeof(t) & (sizeof(t) - 1))) \
|
|
||||||
? **(t **)((ap += 8) - 8) : *(t *)((ap += 8) - 8))
|
|
||||||
#define va_copy(dest, src) ((dest) = (src))
|
|
||||||
#define va_end(ap)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#elif __arm__
|
|
||||||
typedef char *va_list;
|
|
||||||
#define _tcc_alignof(type) ((int)&((struct {char c;type x;} *)0)->x)
|
|
||||||
#define _tcc_align(addr,type) (((unsigned)addr + _tcc_alignof(type) - 1) \
|
|
||||||
& ~(_tcc_alignof(type) - 1))
|
|
||||||
#define va_start(ap,last) ap = ((char *)&(last)) + ((sizeof(last)+3)&~3)
|
|
||||||
#define va_arg(ap,type) (ap = (void *) ((_tcc_align(ap,type)+sizeof(type)+3) \
|
|
||||||
&~3), *(type *)(ap - ((sizeof(type)+3)&~3)))
|
|
||||||
#define va_copy(dest, src) (dest) = (src)
|
|
||||||
#define va_end(ap)
|
|
||||||
|
|
||||||
#elif defined(__aarch64__)
|
|
||||||
typedef struct {
|
|
||||||
void *__stack;
|
|
||||||
void *__gr_top;
|
|
||||||
void *__vr_top;
|
|
||||||
int __gr_offs;
|
|
||||||
int __vr_offs;
|
|
||||||
} va_list;
|
|
||||||
#define va_start(ap, last) __va_start(ap, last)
|
|
||||||
#define va_arg(ap, type) __va_arg(ap, type)
|
|
||||||
#define va_end(ap)
|
|
||||||
#define va_copy(dest, src) ((dest) = (src))
|
|
||||||
|
|
||||||
#else /* __i386__ */
|
|
||||||
typedef char *va_list;
|
|
||||||
/* only correct for i386 */
|
|
||||||
#define va_start(ap,last) ap = ((char *)&(last)) + ((sizeof(last)+3)&~3)
|
|
||||||
#define va_arg(ap,type) (ap += (sizeof(type)+3)&~3, *(type *)(ap - ((sizeof(type)+3)&~3)))
|
|
||||||
#define va_copy(dest, src) (dest) = (src)
|
|
||||||
#define va_end(ap)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* fix a buggy dependency on GCC in libio.h */
|
/* fix a buggy dependency on GCC in libio.h */
|
||||||
typedef va_list __gnuc_va_list;
|
typedef va_list __gnuc_va_list;
|
||||||
|
|||||||
171
include/stdatomic.h
Normal file
171
include/stdatomic.h
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
/* This file is derived from clang's stdatomic.h */
|
||||||
|
|
||||||
|
/*===---- stdatomic.h - Standard header for atomic types and operations -----===
|
||||||
|
*
|
||||||
|
* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
* See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*
|
||||||
|
*===-----------------------------------------------------------------------===
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _STDATOMIC_H
|
||||||
|
#define _STDATOMIC_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define __ATOMIC_RELAXED 0
|
||||||
|
#define __ATOMIC_CONSUME 1
|
||||||
|
#define __ATOMIC_ACQUIRE 2
|
||||||
|
#define __ATOMIC_RELEASE 3
|
||||||
|
#define __ATOMIC_ACQ_REL 4
|
||||||
|
#define __ATOMIC_SEQ_CST 5
|
||||||
|
|
||||||
|
/* Memory ordering */
|
||||||
|
typedef enum {
|
||||||
|
memory_order_relaxed = __ATOMIC_RELAXED,
|
||||||
|
memory_order_consume = __ATOMIC_CONSUME,
|
||||||
|
memory_order_acquire = __ATOMIC_ACQUIRE,
|
||||||
|
memory_order_release = __ATOMIC_RELEASE,
|
||||||
|
memory_order_acq_rel = __ATOMIC_ACQ_REL,
|
||||||
|
memory_order_seq_cst = __ATOMIC_SEQ_CST,
|
||||||
|
} memory_order;
|
||||||
|
|
||||||
|
/* Atomic typedefs */
|
||||||
|
typedef _Atomic(_Bool) atomic_bool;
|
||||||
|
typedef _Atomic(char) atomic_char;
|
||||||
|
typedef _Atomic(signed char) atomic_schar;
|
||||||
|
typedef _Atomic(unsigned char) atomic_uchar;
|
||||||
|
typedef _Atomic(short) atomic_short;
|
||||||
|
typedef _Atomic(unsigned short) atomic_ushort;
|
||||||
|
typedef _Atomic(int) atomic_int;
|
||||||
|
typedef _Atomic(unsigned int) atomic_uint;
|
||||||
|
typedef _Atomic(long) atomic_long;
|
||||||
|
typedef _Atomic(unsigned long) atomic_ulong;
|
||||||
|
typedef _Atomic(long long) atomic_llong;
|
||||||
|
typedef _Atomic(unsigned long long) atomic_ullong;
|
||||||
|
typedef _Atomic(uint_least16_t) atomic_char16_t;
|
||||||
|
typedef _Atomic(uint_least32_t) atomic_char32_t;
|
||||||
|
typedef _Atomic(wchar_t) atomic_wchar_t;
|
||||||
|
typedef _Atomic(int_least8_t) atomic_int_least8_t;
|
||||||
|
typedef _Atomic(uint_least8_t) atomic_uint_least8_t;
|
||||||
|
typedef _Atomic(int_least16_t) atomic_int_least16_t;
|
||||||
|
typedef _Atomic(uint_least16_t) atomic_uint_least16_t;
|
||||||
|
typedef _Atomic(int_least32_t) atomic_int_least32_t;
|
||||||
|
typedef _Atomic(uint_least32_t) atomic_uint_least32_t;
|
||||||
|
typedef _Atomic(int_least64_t) atomic_int_least64_t;
|
||||||
|
typedef _Atomic(uint_least64_t) atomic_uint_least64_t;
|
||||||
|
typedef _Atomic(int_fast8_t) atomic_int_fast8_t;
|
||||||
|
typedef _Atomic(uint_fast8_t) atomic_uint_fast8_t;
|
||||||
|
typedef _Atomic(int_fast16_t) atomic_int_fast16_t;
|
||||||
|
typedef _Atomic(uint_fast16_t) atomic_uint_fast16_t;
|
||||||
|
typedef _Atomic(int_fast32_t) atomic_int_fast32_t;
|
||||||
|
typedef _Atomic(uint_fast32_t) atomic_uint_fast32_t;
|
||||||
|
typedef _Atomic(int_fast64_t) atomic_int_fast64_t;
|
||||||
|
typedef _Atomic(uint_fast64_t) atomic_uint_fast64_t;
|
||||||
|
typedef _Atomic(intptr_t) atomic_intptr_t;
|
||||||
|
typedef _Atomic(uintptr_t) atomic_uintptr_t;
|
||||||
|
typedef _Atomic(size_t) atomic_size_t;
|
||||||
|
typedef _Atomic(ptrdiff_t) atomic_ptrdiff_t;
|
||||||
|
typedef _Atomic(intmax_t) atomic_intmax_t;
|
||||||
|
typedef _Atomic(uintmax_t) atomic_uintmax_t;
|
||||||
|
|
||||||
|
/* Atomic flag */
|
||||||
|
typedef struct {
|
||||||
|
atomic_bool value;
|
||||||
|
} atomic_flag;
|
||||||
|
|
||||||
|
#define ATOMIC_FLAG_INIT {0}
|
||||||
|
#define ATOMIC_VAR_INIT(value) (value)
|
||||||
|
|
||||||
|
/* Generic routines */
|
||||||
|
#define atomic_init(object, desired) \
|
||||||
|
atomic_store_explicit(object, desired, __ATOMIC_RELAXED)
|
||||||
|
|
||||||
|
#define __atomic_store_n(ptr, val, order) \
|
||||||
|
(*(ptr) = (val), __atomic_store((ptr), &(typeof(*(ptr))){val}, (order)))
|
||||||
|
#define atomic_store_explicit(object, desired, order) \
|
||||||
|
({ __typeof__ (object) ptr = (object); \
|
||||||
|
__typeof__ (*ptr) tmp = (desired); \
|
||||||
|
__atomic_store (ptr, &tmp, (order)); \
|
||||||
|
})
|
||||||
|
#define atomic_store(object, desired) \
|
||||||
|
atomic_store_explicit (object, desired, __ATOMIC_SEQ_CST)
|
||||||
|
|
||||||
|
#define __atomic_load_n(ptr, order) \
|
||||||
|
({ typeof(*(ptr)) __val; \
|
||||||
|
__atomic_load((ptr), &__val, (order)); \
|
||||||
|
__val; })
|
||||||
|
#define atomic_load_explicit(object, order) \
|
||||||
|
({ __typeof__ (object) ptr = (object); \
|
||||||
|
__typeof__ ((void)0,*ptr) tmp; \
|
||||||
|
__atomic_load (ptr, &tmp, (order)); \
|
||||||
|
tmp; \
|
||||||
|
})
|
||||||
|
#define atomic_load(object) atomic_load_explicit (object, __ATOMIC_SEQ_CST)
|
||||||
|
|
||||||
|
#define atomic_exchange_explicit(object, desired, order) \
|
||||||
|
({ __typeof__ (object) ptr = (object); \
|
||||||
|
__typeof__ (*ptr) val = (desired); \
|
||||||
|
__typeof__ (*ptr) tmp; \
|
||||||
|
__atomic_exchange (ptr, &val, &tmp, (order)); \
|
||||||
|
tmp; \
|
||||||
|
})
|
||||||
|
#define atomic_exchange(object, desired) \
|
||||||
|
atomic_exchange_explicit (object, desired, __ATOMIC_SEQ_CST)
|
||||||
|
#define __atomic_compare_exchange_n(ptr, expected, desired, weak, success, failure) \
|
||||||
|
({ typeof(*(ptr)) __desired = (desired); \
|
||||||
|
__atomic_compare_exchange((ptr), (expected), &__desired, \
|
||||||
|
(weak), (success), (failure)); })
|
||||||
|
#define atomic_compare_exchange_strong_explicit(object, expected, desired, success, failure) \
|
||||||
|
({ __typeof__ (object) ptr = (object); \
|
||||||
|
__typeof__ (*ptr) tmp = desired; \
|
||||||
|
__atomic_compare_exchange(ptr, expected, &tmp, 0, success, failure); \
|
||||||
|
})
|
||||||
|
#define atomic_compare_exchange_strong(object, expected, desired) \
|
||||||
|
atomic_compare_exchange_strong_explicit (object, expected, desired, \
|
||||||
|
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
|
||||||
|
#define atomic_compare_exchange_weak_explicit(object, expected, desired, success, failure) \
|
||||||
|
({ __typeof__ (object) ptr = (object); \
|
||||||
|
__typeof__ (*ptr) tmp = desired; \
|
||||||
|
__atomic_compare_exchange(ptr, expected, &tmp, 1, success, failure); \
|
||||||
|
})
|
||||||
|
#define atomic_compare_exchange_weak(object, expected, desired) \
|
||||||
|
atomic_compare_exchange_weak_explicit (object, expected, desired, \
|
||||||
|
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
|
||||||
|
|
||||||
|
#define atomic_fetch_add(object, operand) \
|
||||||
|
__atomic_fetch_add(object, operand, __ATOMIC_SEQ_CST)
|
||||||
|
#define atomic_fetch_add_explicit __atomic_fetch_add
|
||||||
|
|
||||||
|
#define atomic_fetch_sub(object, operand) \
|
||||||
|
__atomic_fetch_sub(object, operand, __ATOMIC_SEQ_CST)
|
||||||
|
#define atomic_fetch_sub_explicit __atomic_fetch_sub
|
||||||
|
|
||||||
|
#define atomic_fetch_or(object, operand) \
|
||||||
|
__atomic_fetch_or(object, operand, __ATOMIC_SEQ_CST)
|
||||||
|
#define atomic_fetch_or_explicit __atomic_fetch_or
|
||||||
|
|
||||||
|
#define atomic_fetch_xor(object, operand) \
|
||||||
|
__atomic_fetch_xor(object, operand, __ATOMIC_SEQ_CST)
|
||||||
|
#define atomic_fetch_xor_explicit __atomic_fetch_xor
|
||||||
|
|
||||||
|
#define atomic_fetch_and(object, operand) \
|
||||||
|
__atomic_fetch_and(object, operand, __ATOMIC_SEQ_CST)
|
||||||
|
#define atomic_fetch_and_explicit __atomic_fetch_and
|
||||||
|
|
||||||
|
extern void atomic_thread_fence (memory_order);
|
||||||
|
#define __atomic_thread_fence(order) atomic_thread_fence (order)
|
||||||
|
extern void atomic_signal_fence (memory_order);
|
||||||
|
#define __atomic_signal_fence(order) atomic_signal_fence(order)
|
||||||
|
#define atomic_signal_fence(order) __atomic_signal_fence (order)
|
||||||
|
extern bool __atomic_is_lock_free(size_t size, void *ptr);
|
||||||
|
#define atomic_is_lock_free(OBJ) __atomic_is_lock_free (sizeof (*(OBJ)), (OBJ))
|
||||||
|
|
||||||
|
extern bool atomic_flag_test_and_set(void *object);
|
||||||
|
extern bool atomic_flag_test_and_set_explicit(void *object, memory_order order);
|
||||||
|
extern void atomic_flag_clear(void *object);
|
||||||
|
extern void atomic_flag_clear_explicit(void *object, memory_order order);
|
||||||
|
#endif /* _STDATOMIC_H */
|
||||||
@ -8,31 +8,16 @@ typedef __PTRDIFF_TYPE__ ptrdiff_t;
|
|||||||
typedef __PTRDIFF_TYPE__ intptr_t;
|
typedef __PTRDIFF_TYPE__ intptr_t;
|
||||||
typedef __SIZE_TYPE__ uintptr_t;
|
typedef __SIZE_TYPE__ uintptr_t;
|
||||||
|
|
||||||
#ifndef __int8_t_defined
|
#if __STDC_VERSION__ >= 201112L
|
||||||
#define __int8_t_defined
|
typedef union { long long __ll; long double __ld; } max_align_t;
|
||||||
typedef signed char int8_t;
|
|
||||||
typedef signed short int int16_t;
|
|
||||||
typedef signed int int32_t;
|
|
||||||
#ifdef __LP64__
|
|
||||||
typedef signed long int int64_t;
|
|
||||||
#else
|
|
||||||
typedef signed long long int int64_t;
|
|
||||||
#endif
|
|
||||||
typedef unsigned char uint8_t;
|
|
||||||
typedef unsigned short int uint16_t;
|
|
||||||
typedef unsigned int uint32_t;
|
|
||||||
#ifdef __LP64__
|
|
||||||
typedef unsigned long int uint64_t;
|
|
||||||
#else
|
|
||||||
typedef unsigned long long int uint64_t;
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NULL
|
#ifndef NULL
|
||||||
#define NULL ((void*)0)
|
#define NULL ((void*)0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define offsetof(type, field) ((size_t)&((type *)0)->field)
|
#undef offsetof
|
||||||
|
#define offsetof(type, field) __builtin_offsetof(type, field)
|
||||||
|
|
||||||
void *alloca(size_t size);
|
void *alloca(size_t size);
|
||||||
|
|
||||||
|
|||||||
7
include/stdnoreturn.h
Normal file
7
include/stdnoreturn.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#ifndef _STDNORETURN_H
|
||||||
|
#define _STDNORETURN_H
|
||||||
|
|
||||||
|
/* ISOC11 noreturn */
|
||||||
|
#define noreturn _Noreturn
|
||||||
|
|
||||||
|
#endif /* _STDNORETURN_H */
|
||||||
338
include/tccdefs.h
Normal file
338
include/tccdefs.h
Normal file
@ -0,0 +1,338 @@
|
|||||||
|
/* tccdefs.h
|
||||||
|
|
||||||
|
Nothing is defined before this file except target machine, target os
|
||||||
|
and the few things related to option settings in tccpp.c:tcc_predefs().
|
||||||
|
|
||||||
|
This file is either included at runtime as is, or converted and
|
||||||
|
included as C-strings at compile-time (depending on CONFIG_TCC_PREDEFS).
|
||||||
|
|
||||||
|
Note that line indent matters:
|
||||||
|
|
||||||
|
- in lines starting at column 1, platform macros are replaced by
|
||||||
|
corresponding TCC target compile-time macros. See conftest.c for
|
||||||
|
the list of platform macros supported in lines starting at column 1.
|
||||||
|
|
||||||
|
- only lines indented >= 4 are actually included into the executable,
|
||||||
|
check tccdefs_.h.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if __SIZEOF_POINTER__ == 4
|
||||||
|
/* 32bit systems. */
|
||||||
|
#if defined __OpenBSD__
|
||||||
|
#define __SIZE_TYPE__ unsigned long
|
||||||
|
#define __PTRDIFF_TYPE__ long
|
||||||
|
#else
|
||||||
|
#define __SIZE_TYPE__ unsigned int
|
||||||
|
#define __PTRDIFF_TYPE__ int
|
||||||
|
#endif
|
||||||
|
#define __ILP32__ 1
|
||||||
|
#define __INT64_TYPE__ long long
|
||||||
|
#elif __SIZEOF_LONG__ == 4
|
||||||
|
/* 64bit Windows. */
|
||||||
|
#define __SIZE_TYPE__ unsigned long long
|
||||||
|
#define __PTRDIFF_TYPE__ long long
|
||||||
|
#define __LLP64__ 1
|
||||||
|
#define __INT64_TYPE__ long long
|
||||||
|
#else
|
||||||
|
/* Other 64bit systems. */
|
||||||
|
#define __SIZE_TYPE__ unsigned long
|
||||||
|
#define __PTRDIFF_TYPE__ long
|
||||||
|
#define __LP64__ 1
|
||||||
|
# if defined __linux__
|
||||||
|
#define __INT64_TYPE__ long
|
||||||
|
# else /* APPLE, BSD */
|
||||||
|
#define __INT64_TYPE__ long long
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#define __SIZEOF_INT__ 4
|
||||||
|
#define __INT_MAX__ 0x7fffffff
|
||||||
|
#if __SIZEOF_LONG__ == 4
|
||||||
|
#define __LONG_MAX__ 0x7fffffffL
|
||||||
|
#else
|
||||||
|
#define __LONG_MAX__ 0x7fffffffffffffffL
|
||||||
|
#endif
|
||||||
|
#define __SIZEOF_LONG_LONG__ 8
|
||||||
|
#define __LONG_LONG_MAX__ 0x7fffffffffffffffLL
|
||||||
|
#define __CHAR_BIT__ 8
|
||||||
|
#define __ORDER_LITTLE_ENDIAN__ 1234
|
||||||
|
#define __ORDER_BIG_ENDIAN__ 4321
|
||||||
|
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
|
||||||
|
#if defined _WIN32
|
||||||
|
#define __WCHAR_TYPE__ unsigned short
|
||||||
|
#define __WINT_TYPE__ unsigned short
|
||||||
|
#elif defined __linux__
|
||||||
|
#define __WCHAR_TYPE__ int
|
||||||
|
#define __WINT_TYPE__ unsigned int
|
||||||
|
#else
|
||||||
|
#define __WCHAR_TYPE__ int
|
||||||
|
#define __WINT_TYPE__ int
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __STDC_VERSION__ >= 201112L
|
||||||
|
# define __STDC_NO_ATOMICS__ 1
|
||||||
|
# define __STDC_NO_COMPLEX__ 1
|
||||||
|
# define __STDC_NO_THREADS__ 1
|
||||||
|
#if !defined _WIN32
|
||||||
|
# define __STDC_UTF_16__ 1
|
||||||
|
# define __STDC_UTF_32__ 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined _WIN32
|
||||||
|
#define __declspec(x) __attribute__((x))
|
||||||
|
#define __cdecl
|
||||||
|
|
||||||
|
#elif defined __FreeBSD__
|
||||||
|
#define __GNUC__ 9
|
||||||
|
#define __GNUC_MINOR__ 3
|
||||||
|
#define __GNUC_PATCHLEVEL__ 0
|
||||||
|
#define __GNUC_STDC_INLINE__ 1
|
||||||
|
#define __NO_TLS 1
|
||||||
|
#define __RUNETYPE_INTERNAL 1
|
||||||
|
# if __SIZEOF_POINTER__ == 8
|
||||||
|
#define __SIZEOF_SIZE_T__ 8
|
||||||
|
#define __SIZEOF_PTRDIFF_T__ 8
|
||||||
|
#else
|
||||||
|
#define __SIZEOF_SIZE_T__ 4
|
||||||
|
#define __SIZEOF_PTRDIFF_T__ 4
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined __FreeBSD_kernel__
|
||||||
|
|
||||||
|
#elif defined __NetBSD__
|
||||||
|
#define __GNUC__ 4
|
||||||
|
#define __GNUC_MINOR__ 1
|
||||||
|
#define __GNUC_PATCHLEVEL__ 0
|
||||||
|
#define _Pragma(x)
|
||||||
|
#define __ELF__ 1
|
||||||
|
#if defined __aarch64__
|
||||||
|
#define _LOCORE /* avoids usage of __asm */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif defined __OpenBSD__
|
||||||
|
#define __GNUC__ 4
|
||||||
|
#define _ANSI_LIBRARY 1
|
||||||
|
|
||||||
|
#elif defined __APPLE__
|
||||||
|
/* emulate APPLE-GCC to make libc's headerfiles compile: */
|
||||||
|
#define __GNUC__ 4 /* darwin emits warning on GCC<4 */
|
||||||
|
#define __APPLE_CC__ 1 /* for <TargetConditionals.h> */
|
||||||
|
#define __LITTLE_ENDIAN__ 1
|
||||||
|
#define _DONT_USE_CTYPE_INLINE_ 1
|
||||||
|
/* avoids usage of GCC/clang specific builtins in libc-headerfiles: */
|
||||||
|
#define __FINITE_MATH_ONLY__ 1
|
||||||
|
#define _FORTIFY_SOURCE 0
|
||||||
|
//#define __has_builtin(x) 0
|
||||||
|
#define _Float16 short unsigned int /* fake type just for size & alignment (macOS Sequoia) */
|
||||||
|
|
||||||
|
#elif defined __ANDROID__
|
||||||
|
#define BIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD
|
||||||
|
|
||||||
|
#else
|
||||||
|
/* Linux */
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Some derived integer types needed to get stdint.h to compile correctly on some platforms */
|
||||||
|
#ifndef __NetBSD__
|
||||||
|
#define __UINTPTR_TYPE__ unsigned __PTRDIFF_TYPE__
|
||||||
|
#define __INTPTR_TYPE__ __PTRDIFF_TYPE__
|
||||||
|
#endif
|
||||||
|
#define __INT32_TYPE__ int
|
||||||
|
|
||||||
|
#if !defined _WIN32
|
||||||
|
/* glibc defines. We do not support __USER_NAME_PREFIX__ */
|
||||||
|
#define __REDIRECT(name, proto, alias) name proto __asm__ (#alias)
|
||||||
|
#define __REDIRECT_NTH(name, proto, alias) name proto __asm__ (#alias) __THROW
|
||||||
|
#define __REDIRECT_NTHNL(name, proto, alias) name proto __asm__ (#alias) __THROWNL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* not implemented */
|
||||||
|
#define __PRETTY_FUNCTION__ __FUNCTION__
|
||||||
|
#define __has_builtin(x) 0
|
||||||
|
#define __has_feature(x) 0
|
||||||
|
#define __has_attribute(x) 0
|
||||||
|
/* C23 Keywords */
|
||||||
|
#define _Nonnull
|
||||||
|
#define _Nullable
|
||||||
|
#define _Nullable_result
|
||||||
|
#define _Null_unspecified
|
||||||
|
|
||||||
|
/* skip __builtin... with -E */
|
||||||
|
#ifndef __TCC_PP__
|
||||||
|
|
||||||
|
#define __builtin_offsetof(type, field) ((__SIZE_TYPE__)&((type*)0)->field)
|
||||||
|
#define __builtin_extract_return_addr(x) x
|
||||||
|
#if !defined __linux__ && !defined _WIN32
|
||||||
|
/* used by math.h */
|
||||||
|
#define __builtin_huge_val() 1e500
|
||||||
|
#define __builtin_huge_valf() 1e50f
|
||||||
|
#define __builtin_huge_vall() 1e5000L
|
||||||
|
# if defined __APPLE__
|
||||||
|
#define __builtin_nanf(ignored_string) (0.0F/0.0F)
|
||||||
|
/* used by floats.h to implement FLT_ROUNDS C99 macro. 1 == to nearest */
|
||||||
|
#define __builtin_flt_rounds() 1
|
||||||
|
/* used by _fd_def.h */
|
||||||
|
#define __builtin_bzero(p, ignored_size) bzero(p, sizeof(*(p)))
|
||||||
|
# else
|
||||||
|
#define __builtin_nanf(ignored_string) (0.0F/0.0F)
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* GCC's __uint128_t appears in some Linux/OSX header files.
|
||||||
|
Just make it some type with same size and alignment. */
|
||||||
|
struct __uint128__ { char x[16]; } __attribute((__aligned__(16)));
|
||||||
|
#define __int128_t struct __uint128__
|
||||||
|
#define __uint128_t struct __uint128__
|
||||||
|
|
||||||
|
/* __builtin_va_list */
|
||||||
|
#if defined __x86_64__
|
||||||
|
#if !defined _WIN32
|
||||||
|
/* GCC compatible definition of va_list. */
|
||||||
|
/* This should be in sync with the declaration in our lib/va_list.c */
|
||||||
|
typedef struct {
|
||||||
|
unsigned gp_offset, fp_offset;
|
||||||
|
union {
|
||||||
|
unsigned overflow_offset;
|
||||||
|
char *overflow_arg_area;
|
||||||
|
};
|
||||||
|
char *reg_save_area;
|
||||||
|
} __builtin_va_list[1];
|
||||||
|
|
||||||
|
void *__va_arg(__builtin_va_list ap, int arg_type, int size, int align);
|
||||||
|
#define __builtin_va_start(ap, last) \
|
||||||
|
(*(ap) = *(__builtin_va_list)((char*)__builtin_frame_address(0) - 24))
|
||||||
|
#define __builtin_va_arg(ap, t) \
|
||||||
|
(*(t *)(__va_arg(ap, __builtin_va_arg_types(t), sizeof(t), __alignof__(t))))
|
||||||
|
#define __builtin_va_copy(dest, src) (*(dest) = *(src))
|
||||||
|
|
||||||
|
#else /* _WIN64 */
|
||||||
|
typedef char *__builtin_va_list;
|
||||||
|
#define __builtin_va_arg(ap, t) ((sizeof(t) > 8 || (sizeof(t) & (sizeof(t) - 1))) \
|
||||||
|
? **(t **)((ap += 8) - 8) : *(t *)((ap += 8) - 8))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif defined __arm__
|
||||||
|
typedef char *__builtin_va_list;
|
||||||
|
#define _tcc_alignof(type) ((int)&((struct {char c;type x;} *)0)->x)
|
||||||
|
#define _tcc_align(addr,type) (((unsigned)addr + _tcc_alignof(type) - 1) \
|
||||||
|
& ~(_tcc_alignof(type) - 1))
|
||||||
|
#define __builtin_va_start(ap,last) (ap = ((char *)&(last)) + ((sizeof(last)+3)&~3))
|
||||||
|
#define __builtin_va_arg(ap,type) (ap = (void *) ((_tcc_align(ap,type)+sizeof(type)+3) \
|
||||||
|
&~3), *(type *)(ap - ((sizeof(type)+3)&~3)))
|
||||||
|
|
||||||
|
#elif defined __aarch64__
|
||||||
|
#if defined _WIN32
|
||||||
|
typedef char *__builtin_va_list;
|
||||||
|
#elif defined __APPLE__
|
||||||
|
typedef struct {
|
||||||
|
void *__stack;
|
||||||
|
} __builtin_va_list;
|
||||||
|
|
||||||
|
#else
|
||||||
|
typedef struct {
|
||||||
|
void *__stack, *__gr_top, *__vr_top;
|
||||||
|
int __gr_offs, __vr_offs;
|
||||||
|
} __builtin_va_list;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#elif defined __riscv
|
||||||
|
typedef char *__builtin_va_list;
|
||||||
|
#define __va_reg_size (__riscv_xlen >> 3)
|
||||||
|
#define _tcc_align(addr,type) (((unsigned long)addr + __alignof__(type) - 1) \
|
||||||
|
& -(__alignof__(type)))
|
||||||
|
#define __builtin_va_arg(ap,type) (*(sizeof(type) > (2*__va_reg_size) ? *(type **)((ap += __va_reg_size) - __va_reg_size) : (ap = (va_list)(_tcc_align(ap,type) + (sizeof(type)+__va_reg_size - 1)& -__va_reg_size), (type *)(ap - ((sizeof(type)+ __va_reg_size - 1)& -__va_reg_size)))))
|
||||||
|
|
||||||
|
#else /* __i386__ */
|
||||||
|
typedef char *__builtin_va_list;
|
||||||
|
#define __builtin_va_start(ap,last) (ap = ((char *)&(last)) + ((sizeof(last)+3)&~3))
|
||||||
|
#define __builtin_va_arg(ap,t) (*(t*)((ap+=(sizeof(t)+3)&~3)-((sizeof(t)+3)&~3)))
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#define __builtin_va_end(ap) (void)(ap)
|
||||||
|
#ifndef __builtin_va_copy
|
||||||
|
# define __builtin_va_copy(dest, src) (dest) = (src)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* TCC BBUILTIN AND BOUNDS ALIASES */
|
||||||
|
#ifdef __leading_underscore
|
||||||
|
# define __RENAME(X) __asm__("_"X)
|
||||||
|
#else
|
||||||
|
# define __RENAME(X) __asm__(X)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __TCC_BCHECK__
|
||||||
|
# define __BUILTINBC(ret,name,params) ret __builtin_##name params __RENAME("__bound_"#name);
|
||||||
|
# define __BOUND(ret,name,params) ret name params __RENAME("__bound_"#name);
|
||||||
|
#else
|
||||||
|
# define __BUILTINBC(ret,name,params) ret __builtin_##name params __RENAME(#name);
|
||||||
|
# define __BOUND(ret,name,params)
|
||||||
|
#endif
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define __BOTH __BOUND
|
||||||
|
#define __BUILTIN(ret,name,params)
|
||||||
|
#else
|
||||||
|
#define __BOTH(ret,name,params) __BUILTINBC(ret,name,params)__BOUND(ret,name,params)
|
||||||
|
#define __BUILTIN(ret,name,params) ret __builtin_##name params __RENAME(#name);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
__BOTH(void*, memcpy, (void *, const void*, __SIZE_TYPE__))
|
||||||
|
__BOTH(void*, memmove, (void *, const void*, __SIZE_TYPE__))
|
||||||
|
__BOTH(void*, memset, (void *, int, __SIZE_TYPE__))
|
||||||
|
__BOTH(int, memcmp, (const void *, const void*, __SIZE_TYPE__))
|
||||||
|
__BOTH(__SIZE_TYPE__, strlen, (const char *))
|
||||||
|
__BOTH(char*, strcpy, (char *, const char *))
|
||||||
|
__BOTH(char*, strncpy, (char *, const char*, __SIZE_TYPE__))
|
||||||
|
__BOTH(int, strcmp, (const char*, const char*))
|
||||||
|
__BOTH(int, strncmp, (const char*, const char*, __SIZE_TYPE__))
|
||||||
|
__BOTH(char*, strcat, (char*, const char*))
|
||||||
|
__BOTH(char*, strncat, (char*, const char*, __SIZE_TYPE__))
|
||||||
|
__BOTH(char*, strchr, (const char*, int))
|
||||||
|
__BOTH(char*, strrchr, (const char*, int))
|
||||||
|
__BOTH(char*, strdup, (const char*))
|
||||||
|
#if defined __ARM_EABI__
|
||||||
|
__BOUND(void*,__aeabi_memcpy,(void*,const void*,__SIZE_TYPE__))
|
||||||
|
__BOUND(void*,__aeabi_memmove,(void*,const void*,__SIZE_TYPE__))
|
||||||
|
__BOUND(void*,__aeabi_memmove4,(void*,const void*,__SIZE_TYPE__))
|
||||||
|
__BOUND(void*,__aeabi_memmove8,(void*,const void*,__SIZE_TYPE__))
|
||||||
|
__BOUND(void*,__aeabi_memset,(void*,int,__SIZE_TYPE__))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined __linux__ || defined __APPLE__ // HAVE MALLOC_REDIR
|
||||||
|
#define __MAYBE_REDIR __BUILTIN
|
||||||
|
#else
|
||||||
|
#define __MAYBE_REDIR __BOTH
|
||||||
|
#endif
|
||||||
|
__MAYBE_REDIR(void*, malloc, (__SIZE_TYPE__))
|
||||||
|
__MAYBE_REDIR(void*, realloc, (void *, __SIZE_TYPE__))
|
||||||
|
__MAYBE_REDIR(void*, calloc, (__SIZE_TYPE__, __SIZE_TYPE__))
|
||||||
|
__MAYBE_REDIR(void*, memalign, (__SIZE_TYPE__, __SIZE_TYPE__))
|
||||||
|
__MAYBE_REDIR(void, free, (void*))
|
||||||
|
__BOTH(void*, alloca, (__SIZE_TYPE__))
|
||||||
|
void *alloca(__SIZE_TYPE__);
|
||||||
|
__BUILTIN(void, abort, (void))
|
||||||
|
__BOUND(void, longjmp, ())
|
||||||
|
#if !defined _WIN32
|
||||||
|
__BOUND(void*, mmap, ())
|
||||||
|
__BOUND(int, munmap, ())
|
||||||
|
#endif
|
||||||
|
#undef __BUILTINBC
|
||||||
|
#undef __BUILTIN
|
||||||
|
#undef __BOUND
|
||||||
|
#undef __BOTH
|
||||||
|
#undef __MAYBE_REDIR
|
||||||
|
#undef __RENAME
|
||||||
|
|
||||||
|
#define __BUILTIN_EXTERN(name,u) \
|
||||||
|
int __builtin_##name(u int); \
|
||||||
|
int __builtin_##name##l(u long); \
|
||||||
|
int __builtin_##name##ll(u long long);
|
||||||
|
__BUILTIN_EXTERN(ffs,)
|
||||||
|
__BUILTIN_EXTERN(clz, unsigned)
|
||||||
|
__BUILTIN_EXTERN(ctz, unsigned)
|
||||||
|
__BUILTIN_EXTERN(clrsb,)
|
||||||
|
__BUILTIN_EXTERN(popcount, unsigned)
|
||||||
|
__BUILTIN_EXTERN(parity, unsigned)
|
||||||
|
#undef __BUILTIN_EXTERN
|
||||||
|
|
||||||
|
#endif /* ndef __TCC_PP__ */
|
||||||
89
include/tgmath.h
Normal file
89
include/tgmath.h
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* ISO C Standard: 7.22 Type-generic math <tgmath.h>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TGMATH_H
|
||||||
|
#define _TGMATH_H
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#define __tgmath_real(x, F) \
|
||||||
|
_Generic ((x), float: F##f, long double: F##l, default: F)(x)
|
||||||
|
#define __tgmath_real_2_1(x, y, F) \
|
||||||
|
_Generic ((x), float: F##f, long double: F##l, default: F)(x, y)
|
||||||
|
#define __tgmath_real_2(x, y, F) \
|
||||||
|
_Generic ((x)+(y), float: F##f, long double: F##l, default: F)(x, y)
|
||||||
|
#define __tgmath_real_3_2(x, y, z, F) \
|
||||||
|
_Generic ((x)+(y), float: F##f, long double: F##l, default: F)(x, y, z)
|
||||||
|
#define __tgmath_real_3(x, y, z, F) \
|
||||||
|
_Generic ((x)+(y)+(z), float: F##f, long double: F##l, default: F)(x, y, z)
|
||||||
|
|
||||||
|
/* Functions defined in both <math.h> and <complex.h> (7.22p4) */
|
||||||
|
#define acos(z) __tgmath_real(z, acos)
|
||||||
|
#define asin(z) __tgmath_real(z, asin)
|
||||||
|
#define atan(z) __tgmath_real(z, atan)
|
||||||
|
#define acosh(z) __tgmath_real(z, acosh)
|
||||||
|
#define asinh(z) __tgmath_real(z, asinh)
|
||||||
|
#define atanh(z) __tgmath_real(z, atanh)
|
||||||
|
#define cos(z) __tgmath_real(z, cos)
|
||||||
|
#define sin(z) __tgmath_real(z, sin)
|
||||||
|
#define tan(z) __tgmath_real(z, tan)
|
||||||
|
#define cosh(z) __tgmath_real(z, cosh)
|
||||||
|
#define sinh(z) __tgmath_real(z, sinh)
|
||||||
|
#define tanh(z) __tgmath_real(z, tanh)
|
||||||
|
#define exp(z) __tgmath_real(z, exp)
|
||||||
|
#define log(z) __tgmath_real(z, log)
|
||||||
|
#define pow(z1,z2) __tgmath_real_2(z1, z2, pow)
|
||||||
|
#define sqrt(z) __tgmath_real(z, sqrt)
|
||||||
|
#define fabs(z) __tgmath_real(z, fabs)
|
||||||
|
|
||||||
|
/* Functions defined in <math.h> only (7.22p5) */
|
||||||
|
#define atan2(x,y) __tgmath_real_2(x, y, atan2)
|
||||||
|
#define cbrt(x) __tgmath_real(x, cbrt)
|
||||||
|
#define ceil(x) __tgmath_real(x, ceil)
|
||||||
|
#define copysign(x,y) __tgmath_real_2(x, y, copysign)
|
||||||
|
#define erf(x) __tgmath_real(x, erf)
|
||||||
|
#define erfc(x) __tgmath_real(x, erfc)
|
||||||
|
#define exp2(x) __tgmath_real(x, exp2)
|
||||||
|
#define expm1(x) __tgmath_real(x, expm1)
|
||||||
|
#define fdim(x,y) __tgmath_real_2(x, y, fdim)
|
||||||
|
#define floor(x) __tgmath_real(x, floor)
|
||||||
|
#define fma(x,y,z) __tgmath_real_3(x, y, z, fma)
|
||||||
|
#define fmax(x,y) __tgmath_real_2(x, y, fmax)
|
||||||
|
#define fmin(x,y) __tgmath_real_2(x, y, fmin)
|
||||||
|
#define fmod(x,y) __tgmath_real_2(x, y, fmod)
|
||||||
|
#define frexp(x,y) __tgmath_real_2_1(x, y, frexp)
|
||||||
|
#define hypot(x,y) __tgmath_real_2(x, y, hypot)
|
||||||
|
#define ilogb(x) __tgmath_real(x, ilogb)
|
||||||
|
#define ldexp(x,y) __tgmath_real_2_1(x, y, ldexp)
|
||||||
|
#define lgamma(x) __tgmath_real(x, lgamma)
|
||||||
|
#define llrint(x) __tgmath_real(x, llrint)
|
||||||
|
#define llround(x) __tgmath_real(x, llround)
|
||||||
|
#define log10(x) __tgmath_real(x, log10)
|
||||||
|
#define log1p(x) __tgmath_real(x, log1p)
|
||||||
|
#define log2(x) __tgmath_real(x, log2)
|
||||||
|
#define logb(x) __tgmath_real(x, logb)
|
||||||
|
#define lrint(x) __tgmath_real(x, lrint)
|
||||||
|
#define lround(x) __tgmath_real(x, lround)
|
||||||
|
#define nearbyint(x) __tgmath_real(x, nearbyint)
|
||||||
|
#define nextafter(x,y) __tgmath_real_2(x, y, nextafter)
|
||||||
|
#define nexttoward(x,y) __tgmath_real_2(x, y, nexttoward)
|
||||||
|
#define remainder(x,y) __tgmath_real_2(x, y, remainder)
|
||||||
|
#define remquo(x,y,z) __tgmath_real_3_2(x, y, z, remquo)
|
||||||
|
#define rint(x) __tgmath_real(x, rint)
|
||||||
|
#define round(x) __tgmath_real(x, round)
|
||||||
|
#define scalbln(x,y) __tgmath_real_2_1(x, y, scalbln)
|
||||||
|
#define scalbn(x,y) __tgmath_real_2_1(x, y, scalbn)
|
||||||
|
#define tgamma(x) __tgmath_real(x, tgamma)
|
||||||
|
#define trunc(x) __tgmath_real(x, trunc)
|
||||||
|
|
||||||
|
/* Functions defined in <complex.h> only (7.22p6)
|
||||||
|
#define carg(z) __tgmath_cplx_only(z, carg)
|
||||||
|
#define cimag(z) __tgmath_cplx_only(z, cimag)
|
||||||
|
#define conj(z) __tgmath_cplx_only(z, conj)
|
||||||
|
#define cproj(z) __tgmath_cplx_only(z, cproj)
|
||||||
|
#define creal(z) __tgmath_cplx_only(z, creal)
|
||||||
|
*/
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
#endif /* _TGMATH_H */
|
||||||
105
lib/Makefile
105
lib/Makefile
@ -7,67 +7,100 @@ include $(TOP)/Makefile
|
|||||||
VPATH = $(TOPSRC)/lib $(TOPSRC)/win32/lib
|
VPATH = $(TOPSRC)/lib $(TOPSRC)/win32/lib
|
||||||
T = $(or $(CROSS_TARGET),$(NATIVE_TARGET),unknown)
|
T = $(or $(CROSS_TARGET),$(NATIVE_TARGET),unknown)
|
||||||
X = $(if $(CROSS_TARGET),$(CROSS_TARGET)-)
|
X = $(if $(CROSS_TARGET),$(CROSS_TARGET)-)
|
||||||
BIN = $(TOP)/$(X)libtcc1.a
|
XCFG = $(or $(findstring -win,$T),-unx)
|
||||||
|
S = $(if $(findstring yes,$(SILENT)),@$(info * $@))
|
||||||
|
|
||||||
|
TCC = $(TOP)/$(X)tcc$(EXESUF)
|
||||||
XTCC ?= $(TOP)/$(X)tcc$(EXESUF)
|
XTCC ?= $(TOP)/$(X)tcc$(EXESUF)
|
||||||
XCC = $(XTCC)
|
XCC = $(XTCC)
|
||||||
XAR = $(XTCC) -ar
|
XAR = $(XTCC) -ar
|
||||||
XFLAGS-unx = -B$(TOPSRC)
|
XFLAGS-unx = -B$(TOPSRC)
|
||||||
XFLAGS-win = -B$(TOPSRC)/win32 -I$(TOPSRC)/include
|
XFLAGS-win = -B$(TOPSRC)/win32 -I$(TOPSRC)/include
|
||||||
XFLAGS = $(XFLAGS$(XCFG))
|
XFLAGS = $(XFLAGS$(XCFG))
|
||||||
XCFG = $(or $(findstring -win,$T),-unx)
|
BFLAGS = -bt
|
||||||
|
|
||||||
# in order to use gcc, tyoe: make <target>-libtcc1-usegcc=yes
|
# in order to use gcc, type: make <target>-libtcc1-usegcc=yes
|
||||||
arm-libtcc1-usegcc ?= no
|
arm-libtcc1-usegcc ?= no
|
||||||
|
|
||||||
|
# This makes bounds checking 40%..60% faster.
|
||||||
|
#x86_64-libtcc1-usegcc=yes
|
||||||
|
#i386-libtcc1-usegcc=yes
|
||||||
|
|
||||||
ifeq "$($(T)-libtcc1-usegcc)" "yes"
|
ifeq "$($(T)-libtcc1-usegcc)" "yes"
|
||||||
XCC = $(CC)
|
XCC = $(CC)
|
||||||
XAR = $(AR)
|
XAR = $(AR)
|
||||||
XFLAGS = $(CFLAGS) -fPIC
|
XFLAGS = $(CFLAGS) -fPIC -fno-omit-frame-pointer -Wno-unused-function -Wno-unused-variable
|
||||||
|
BFLAGS = $(if $(CONFIG_dwarf),-gdwarf,-gstabs)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# only for native compiler
|
XFLAGS += -I$(TOP)
|
||||||
$(X)BCHECK_O = bcheck.o
|
|
||||||
|
|
||||||
ifeq ($(CONFIG_musl)$(CONFIG_uClibc),yes)
|
I386_O = libtcc1.o $(COMMON_O)
|
||||||
BCHECK_O =
|
X86_64_O = libtcc1.o $(COMMON_O)
|
||||||
endif
|
ARM_O = libtcc1.o armeabi.o armflush.o $(COMMON_O)
|
||||||
|
ARM64_O = lib-arm64.o $(COMMON_O)
|
||||||
|
RISCV64_O = lib-arm64.o $(COMMON_O)
|
||||||
|
COMMON_O = stdatomic.o atomic.o builtin.o alloca.o alloca-bt.o
|
||||||
|
WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o winex.o
|
||||||
|
LIN_O = dsohandle.o
|
||||||
|
OSX_O =
|
||||||
|
|
||||||
ifdef CONFIG_OSX
|
# backtrace/bcheck/run only for native compiler
|
||||||
XFLAGS += -D_ANSI_SOURCE
|
Nat = $(if $X,no,)
|
||||||
endif
|
Cbt = $(Nat)$(subst yes,,$(CONFIG_backtrace))
|
||||||
|
Cbc = $(Cbt)$(subst yes,,$(CONFIG_bcheck))
|
||||||
|
|
||||||
I386_O = libtcc1.o alloca86.o alloca86-bt.o
|
$(Nat)COMMON_O += runmain.o tcov.o
|
||||||
X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o
|
$(Cbt)COMMON_O += bt-exe.o bt-log.o
|
||||||
ARM_O = libtcc1.o armeabi.o alloca-arm.o armflush.o
|
$(Cbt)WIN_O += bt-dll.o
|
||||||
ARM64_O = lib-arm64.o
|
$(Cbc)COMMON_O += bcheck.o
|
||||||
WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o
|
|
||||||
|
|
||||||
OBJ-i386 = $(I386_O) $(BCHECK_O)
|
# not in libtcc1.a
|
||||||
OBJ-x86_64 = $(X86_64_O) va_list.o $(BCHECK_O)
|
EXTRA_O = runmain.o bt-exe.o bt-dll.o bt-log.o bcheck.o
|
||||||
OBJ-x86_64-osx = $(X86_64_O) va_list.o
|
|
||||||
OBJ-i386-win32 = $(I386_O) chkstk.o bcheck.o $(WIN_O)
|
OBJ-i386 = $(I386_O) pic86.o $(LIN_O)
|
||||||
OBJ-x86_64-win32 = $(X86_64_O) chkstk.o bcheck.o $(WIN_O)
|
OBJ-x86_64 = $(X86_64_O) va_list.o $(LIN_O)
|
||||||
OBJ-arm64 = $(ARM64_O)
|
OBJ-x86_64-osx = $(X86_64_O) va_list.o $(OSX_O)
|
||||||
OBJ-arm = $(ARM_O)
|
OBJ-i386-win32 = $(I386_O) chkstk.o $(WIN_O)
|
||||||
OBJ-arm-fpa = $(ARM_O)
|
OBJ-x86_64-win32 = $(X86_64_O) chkstk.o $(WIN_O)
|
||||||
OBJ-arm-fpa-ld = $(ARM_O)
|
OBJ-arm64 = $(ARM64_O) armflush.o $(LIN_O)
|
||||||
OBJ-arm-vfp = $(ARM_O)
|
OBJ-arm64-osx = $(ARM64_O) $(OSX_O)
|
||||||
OBJ-arm-eabi = $(ARM_O)
|
OBJ-arm64-win32 = $(ARM64_O) chkstk.o $(WIN_O)
|
||||||
OBJ-arm-eabihf = $(ARM_O)
|
OBJ-arm = $(ARM_O) $(LIN_O)
|
||||||
|
OBJ-arm-fpa = $(OBJ-arm)
|
||||||
|
OBJ-arm-fpa-ld = $(OBJ-arm)
|
||||||
|
OBJ-arm-vfp = $(OBJ-arm)
|
||||||
|
OBJ-arm-eabi = $(OBJ-arm)
|
||||||
|
OBJ-arm-eabihf = $(OBJ-arm)
|
||||||
OBJ-arm-wince = $(ARM_O) $(WIN_O)
|
OBJ-arm-wince = $(ARM_O) $(WIN_O)
|
||||||
|
OBJ-riscv64 = $(RISCV64_O) lib-riscv.o $(LIN_O)
|
||||||
|
|
||||||
$(BIN) : $(patsubst %.o,$(X)%.o,$(OBJ-$T))
|
OBJ-extra = $(filter $(EXTRA_O),$(OBJ-$T))
|
||||||
$(XAR) rcs $@ $^
|
OBJ-libtcc1 = $(addprefix $(X),$(filter-out $(OBJ-extra),$(OBJ-$T)))
|
||||||
|
|
||||||
$(X)%.o : %.c
|
ALL = $(addprefix $(TOP)/,$(X)libtcc1.a $(OBJ-extra))
|
||||||
$(XCC) -c $< -o $@ $(XFLAGS)
|
|
||||||
|
|
||||||
$(X)%.o : %.S
|
all: $(ALL)
|
||||||
$(XCC) -c $< -o $@ $(XFLAGS)
|
|
||||||
|
$(TOP)/$(X)libtcc1.a : $(OBJ-libtcc1) $(TCC)
|
||||||
|
$S$(XAR) rcs $@ $(OBJ-libtcc1)
|
||||||
|
|
||||||
|
$(X)%.o : %.c $(TCC)
|
||||||
|
$S$(XCC) -c $< -o $@ $(XFLAGS)
|
||||||
|
|
||||||
|
$(X)%.o : %.S $(TCC)
|
||||||
|
$S$(XCC) -c $< -o $@ $(XFLAGS)
|
||||||
|
|
||||||
|
$(TOP)/%.o : %.c $(TCC)
|
||||||
|
$S$(XCC) -c $< -o $@ $(XFLAGS)
|
||||||
|
|
||||||
|
$(TOP)/bcheck.o : XFLAGS += $(BFLAGS)
|
||||||
|
|
||||||
$(X)crt1w.o : crt1.c
|
$(X)crt1w.o : crt1.c
|
||||||
$(X)wincrt1w.o : wincrt1.c
|
$(X)wincrt1w.o : wincrt1.c
|
||||||
|
|
||||||
|
# don't try to make it
|
||||||
|
$(TCC) : ;
|
||||||
|
|
||||||
clean :
|
clean :
|
||||||
rm -f *.a *.o $(BIN)
|
rm -f *.o $(addprefix $(TOP)/,*libtcc1.a $(EXTRA_O))
|
||||||
|
|||||||
@ -1,17 +0,0 @@
|
|||||||
.text
|
|
||||||
.align 2
|
|
||||||
.global alloca
|
|
||||||
.type alloca, %function
|
|
||||||
alloca:
|
|
||||||
#ifdef __TINYC__
|
|
||||||
.int 0xe060d00d
|
|
||||||
.int 0xe3cdd007
|
|
||||||
.int 0xe1a0000d
|
|
||||||
.int 0xe1a0f00e
|
|
||||||
#else
|
|
||||||
rsb sp, r0, sp
|
|
||||||
bic sp, sp, #7
|
|
||||||
mov r0, sp
|
|
||||||
mov pc, lr
|
|
||||||
#endif
|
|
||||||
.size alloca, .-alloca
|
|
||||||
200
lib/alloca-bt.S
Normal file
200
lib/alloca-bt.S
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
/* ---------------------------------------------- */
|
||||||
|
/* alloca-bt.S */
|
||||||
|
|
||||||
|
#ifdef __leading_underscore
|
||||||
|
# define _(s) _##s
|
||||||
|
#else
|
||||||
|
# define _(s) s
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ---------------------------------------------- */
|
||||||
|
#if defined __i386__
|
||||||
|
|
||||||
|
.globl _(__bound_alloca)
|
||||||
|
_(__bound_alloca):
|
||||||
|
pop %edx
|
||||||
|
pop %eax
|
||||||
|
mov %eax, %ecx
|
||||||
|
test %eax,%eax
|
||||||
|
jz p6
|
||||||
|
add $3 + 1,%eax
|
||||||
|
and $-4,%eax
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
p4:
|
||||||
|
cmp $4096,%eax
|
||||||
|
jb p5
|
||||||
|
test %eax,-4096(%esp)
|
||||||
|
sub $4096,%esp
|
||||||
|
sub $4096,%eax
|
||||||
|
jmp p4
|
||||||
|
|
||||||
|
p5:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
sub %eax,%esp
|
||||||
|
mov %esp,%eax
|
||||||
|
|
||||||
|
push %edx
|
||||||
|
push %eax
|
||||||
|
push %ecx
|
||||||
|
push %eax
|
||||||
|
call _(__bound_new_region)
|
||||||
|
add $8, %esp
|
||||||
|
pop %eax
|
||||||
|
pop %edx
|
||||||
|
|
||||||
|
p6:
|
||||||
|
push %edx
|
||||||
|
push %edx
|
||||||
|
ret
|
||||||
|
|
||||||
|
/* ---------------------------------------------- */
|
||||||
|
#elif defined __x86_64__
|
||||||
|
|
||||||
|
.globl _(__bound_alloca)
|
||||||
|
_(__bound_alloca):
|
||||||
|
#ifdef _WIN32
|
||||||
|
inc %rcx # add one extra to separate regions
|
||||||
|
jmp _(alloca)
|
||||||
|
.globl _(__bound_alloca_nr)
|
||||||
|
_(__bound_alloca_nr):
|
||||||
|
dec %rcx
|
||||||
|
push %rax
|
||||||
|
mov %rcx,%rdx
|
||||||
|
mov %rax,%rcx
|
||||||
|
sub $32,%rsp
|
||||||
|
call _(__bound_new_region)
|
||||||
|
add $32,%rsp
|
||||||
|
pop %rax
|
||||||
|
ret
|
||||||
|
#else
|
||||||
|
pop %rdx
|
||||||
|
mov %rdi,%rax
|
||||||
|
and %eax,%eax
|
||||||
|
jz p3
|
||||||
|
mov %rax,%rsi # size, a second parm to the __bound_new_region
|
||||||
|
add $15 + 1,%rax # add one extra to separate regions
|
||||||
|
and $-16,%rax
|
||||||
|
|
||||||
|
sub %rax,%rsp
|
||||||
|
mov %rsp,%rdi # pointer, a first parm to the __bound_new_region
|
||||||
|
mov %rsp,%rax
|
||||||
|
|
||||||
|
push %rdx
|
||||||
|
push %rax
|
||||||
|
call _(__bound_new_region)
|
||||||
|
pop %rax
|
||||||
|
pop %rdx
|
||||||
|
|
||||||
|
p3:
|
||||||
|
push %rdx
|
||||||
|
ret
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ---------------------------------------------- */
|
||||||
|
#elif defined __arm__
|
||||||
|
|
||||||
|
.globl _(__bound_alloca)
|
||||||
|
_(__bound_alloca):
|
||||||
|
mov r1, r0
|
||||||
|
add r0, r0, #1
|
||||||
|
rsb sp, r0, sp
|
||||||
|
bic sp, sp, #7
|
||||||
|
mov r0, sp
|
||||||
|
push { lr }
|
||||||
|
bl _(__bound_new_region)
|
||||||
|
pop { lr }
|
||||||
|
mov r0, sp
|
||||||
|
mov pc, lr
|
||||||
|
|
||||||
|
/* ---------------------------------------------- */
|
||||||
|
#elif defined __aarch64__ || defined __arm64__
|
||||||
|
|
||||||
|
.globl _(__bound_alloca)
|
||||||
|
_(__bound_alloca):
|
||||||
|
#ifdef __TINYC__
|
||||||
|
.int 0xaa0003e1
|
||||||
|
.int 0x91004000
|
||||||
|
.int 0x927cec00
|
||||||
|
#ifdef _WIN32
|
||||||
|
.int 0xb4000160
|
||||||
|
.int 0xd2820002
|
||||||
|
.int 0xeb02001f
|
||||||
|
.int 0x540000c3
|
||||||
|
.int 0xcb2263e3
|
||||||
|
.int 0xf940007f
|
||||||
|
.int 0xcb2263ff
|
||||||
|
.int 0xcb020000
|
||||||
|
.int 0x17fffffa
|
||||||
|
.int 0xb4000040
|
||||||
|
#endif
|
||||||
|
.int 0xcb2063ff
|
||||||
|
.int 0x910003e0
|
||||||
|
.int 0xa9bf7bfd
|
||||||
|
.reloc ., R_AARCH64_CALL26, _(__bound_new_region)
|
||||||
|
.int 0x94000000
|
||||||
|
.int 0xa8c17bfd
|
||||||
|
.int 0x910003e0
|
||||||
|
.int 0xd65f03c0
|
||||||
|
#else
|
||||||
|
mov x1, x0
|
||||||
|
add x0, x0, #16 // Round up to 16-byte boundary
|
||||||
|
and x0, x0, #-16 // Ensure 16-byte alignment
|
||||||
|
#ifdef _WIN32
|
||||||
|
cbz x0, p100 // If size is 0, skip to return
|
||||||
|
// Windows requires page-wise allocation with stack probing
|
||||||
|
mov x2, #4096 // Page size = 4096 bytes
|
||||||
|
|
||||||
|
p101:
|
||||||
|
cmp x0, x2 // Compare remaining size with page size
|
||||||
|
b.lo p102 // If less than page, jump to remainder
|
||||||
|
|
||||||
|
// Probe first, then allocate
|
||||||
|
sub x3, sp, x2 // Calculate guard page address (sp - 4096)
|
||||||
|
ldr xzr, [x3] // Touch guard page FIRST
|
||||||
|
sub sp, sp, x2 // THEN allocate the page
|
||||||
|
|
||||||
|
sub x0, x0, x2 // Decrement remaining size
|
||||||
|
b p101 // Continue loop
|
||||||
|
|
||||||
|
p102:
|
||||||
|
// Allocate remaining bytes (less than one page)
|
||||||
|
cbz x0, p100 // If no remaining bytes, skip
|
||||||
|
sub sp, sp, x0 // Allocate remaining space
|
||||||
|
#else
|
||||||
|
// Non-Windows: simple one-time allocation
|
||||||
|
sub sp, sp, x0 // Allocate space on stack
|
||||||
|
#endif
|
||||||
|
|
||||||
|
p100:
|
||||||
|
mov x0, sp // Return allocated address
|
||||||
|
stp x29, x30, [sp, #-16]!
|
||||||
|
bl _(__bound_new_region)
|
||||||
|
ldp x29, x30, [sp], #16
|
||||||
|
mov x0, sp // Return allocated address
|
||||||
|
ret // Return to caller
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ---------------------------------------------- */
|
||||||
|
#elif defined __riscv
|
||||||
|
|
||||||
|
.globl _(__bound_alloca)
|
||||||
|
_(__bound_alloca):
|
||||||
|
mv a1, a0
|
||||||
|
sub sp, sp, a0
|
||||||
|
addi sp, sp, -16
|
||||||
|
andi sp, sp, -16
|
||||||
|
add a0, sp, zero
|
||||||
|
addi sp,sp,-16
|
||||||
|
sd s0,0(sp)
|
||||||
|
sd ra,8(sp)
|
||||||
|
jal _(__bound_new_region)
|
||||||
|
ld s0,0(sp)
|
||||||
|
ld ra,8(sp)
|
||||||
|
addi sp,sp,16
|
||||||
|
add a0, sp, zero
|
||||||
|
ret
|
||||||
|
|
||||||
|
/* ---------------------------------------------- */
|
||||||
|
#endif
|
||||||
148
lib/alloca.S
Normal file
148
lib/alloca.S
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
/* ---------------------------------------------- */
|
||||||
|
/* alloca.S */
|
||||||
|
|
||||||
|
#ifdef __leading_underscore
|
||||||
|
# define _(s) _##s
|
||||||
|
#else
|
||||||
|
# define _(s) s
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ---------------------------------------------- */
|
||||||
|
#if defined __i386__
|
||||||
|
|
||||||
|
.globl _(alloca), _(__alloca)
|
||||||
|
_(alloca):
|
||||||
|
_(__alloca):
|
||||||
|
pop %edx
|
||||||
|
pop %eax
|
||||||
|
add $3,%eax
|
||||||
|
and $-4,%eax
|
||||||
|
jz p3
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
p1:
|
||||||
|
cmp $4096,%eax
|
||||||
|
jb p2
|
||||||
|
test %eax,-4096(%esp)
|
||||||
|
sub $4096,%esp
|
||||||
|
sub $4096,%eax
|
||||||
|
jmp p1
|
||||||
|
p2:
|
||||||
|
#endif
|
||||||
|
sub %eax,%esp
|
||||||
|
mov %esp,%eax
|
||||||
|
p3:
|
||||||
|
push %edx
|
||||||
|
push %edx
|
||||||
|
ret
|
||||||
|
|
||||||
|
/* ---------------------------------------------- */
|
||||||
|
#elif defined __x86_64__
|
||||||
|
|
||||||
|
.globl _(alloca)
|
||||||
|
_(alloca):
|
||||||
|
pop %rdx
|
||||||
|
#ifdef _WIN32
|
||||||
|
mov %rcx,%rax
|
||||||
|
#else
|
||||||
|
mov %rdi,%rax
|
||||||
|
#endif
|
||||||
|
add $15,%rax
|
||||||
|
and $-16,%rax
|
||||||
|
jz p3
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
p1:
|
||||||
|
cmp $4096,%rax
|
||||||
|
jb p2
|
||||||
|
test %rax,-4096(%rsp)
|
||||||
|
sub $4096,%rsp
|
||||||
|
sub $4096,%rax
|
||||||
|
jmp p1
|
||||||
|
p2:
|
||||||
|
#endif
|
||||||
|
sub %rax,%rsp
|
||||||
|
mov %rsp,%rax
|
||||||
|
p3:
|
||||||
|
push %rdx
|
||||||
|
ret
|
||||||
|
|
||||||
|
/* ---------------------------------------------- */
|
||||||
|
#elif defined __arm__
|
||||||
|
|
||||||
|
.globl _(alloca)
|
||||||
|
_(alloca):
|
||||||
|
rsb sp, r0, sp
|
||||||
|
bic sp, sp, #7
|
||||||
|
mov r0, sp
|
||||||
|
mov pc, lr
|
||||||
|
|
||||||
|
/* ---------------------------------------------- */
|
||||||
|
#elif defined __aarch64__ || defined __arm64__
|
||||||
|
|
||||||
|
.globl _(alloca)
|
||||||
|
_(alloca):
|
||||||
|
#ifdef __TINYC__
|
||||||
|
.int 0x91003c00
|
||||||
|
.int 0x927cec00
|
||||||
|
#ifdef _WIN32
|
||||||
|
.int 0xb4000160
|
||||||
|
.int 0xd2820001
|
||||||
|
.int 0xeb01001f
|
||||||
|
.int 0x540000c3
|
||||||
|
.int 0xcb2163e2
|
||||||
|
.int 0xf940005f
|
||||||
|
.int 0xcb2163ff
|
||||||
|
.int 0xcb010000
|
||||||
|
.int 0x17fffffa
|
||||||
|
.int 0xb4000040
|
||||||
|
#endif
|
||||||
|
.int 0xcb2063ff
|
||||||
|
.int 0x910003e0
|
||||||
|
.int 0xd65f03c0
|
||||||
|
#else
|
||||||
|
add x0, x0, #15 // Round up to 16-byte boundary
|
||||||
|
and x0, x0, #-16 // Ensure 16-byte alignment
|
||||||
|
#ifdef _WIN32
|
||||||
|
cbz x0, p100 // If size is 0, skip to return
|
||||||
|
// Windows requires page-wise allocation with stack probing
|
||||||
|
mov x1, #4096 // Page size = 4096 bytes
|
||||||
|
|
||||||
|
p101:
|
||||||
|
cmp x0, x1 // Compare remaining size with page size
|
||||||
|
b.lo p102 // If less than page, jump to remainder
|
||||||
|
|
||||||
|
// Probe first, then allocate
|
||||||
|
sub x2, sp, x1 // Calculate guard page address (sp - 4096)
|
||||||
|
ldr xzr, [x2] // Touch guard page FIRST
|
||||||
|
sub sp, sp, x1 // THEN allocate the page
|
||||||
|
|
||||||
|
sub x0, x0, x1 // Decrement remaining size
|
||||||
|
b p101 // Continue loop
|
||||||
|
|
||||||
|
p102:
|
||||||
|
// Allocate remaining bytes (less than one page)
|
||||||
|
cbz x0, p100 // If no remaining bytes, skip
|
||||||
|
sub sp, sp, x0 // Allocate remaining space
|
||||||
|
#else
|
||||||
|
// Non-Windows: simple one-time allocation
|
||||||
|
sub sp, sp, x0 // Allocate space on stack
|
||||||
|
#endif
|
||||||
|
|
||||||
|
p100:
|
||||||
|
mov x0, sp // Return allocated address
|
||||||
|
ret // Return to caller
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ---------------------------------------------- */
|
||||||
|
#elif defined __riscv
|
||||||
|
|
||||||
|
.globl _(alloca)
|
||||||
|
_(alloca):
|
||||||
|
sub sp, sp, a0
|
||||||
|
addi sp, sp, -15
|
||||||
|
andi sp, sp, -16
|
||||||
|
add a0, sp, zero
|
||||||
|
ret
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -1,47 +0,0 @@
|
|||||||
/* ---------------------------------------------- */
|
|
||||||
/* alloca86-bt.S */
|
|
||||||
|
|
||||||
.globl __bound_alloca
|
|
||||||
|
|
||||||
__bound_alloca:
|
|
||||||
pop %edx
|
|
||||||
pop %eax
|
|
||||||
mov %eax, %ecx
|
|
||||||
add $3,%eax
|
|
||||||
and $-4,%eax
|
|
||||||
jz p6
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
p4:
|
|
||||||
cmp $4096,%eax
|
|
||||||
jbe p5
|
|
||||||
test %eax,-4096(%esp)
|
|
||||||
sub $4096,%esp
|
|
||||||
sub $4096,%eax
|
|
||||||
jmp p4
|
|
||||||
|
|
||||||
p5:
|
|
||||||
#endif
|
|
||||||
|
|
||||||
sub %eax,%esp
|
|
||||||
mov %esp,%eax
|
|
||||||
|
|
||||||
push %edx
|
|
||||||
push %eax
|
|
||||||
push %ecx
|
|
||||||
push %eax
|
|
||||||
call __bound_new_region
|
|
||||||
add $8, %esp
|
|
||||||
pop %eax
|
|
||||||
pop %edx
|
|
||||||
|
|
||||||
p6:
|
|
||||||
push %edx
|
|
||||||
push %edx
|
|
||||||
ret
|
|
||||||
|
|
||||||
/* mark stack as nonexecutable */
|
|
||||||
#if defined __ELF__ && defined __linux__
|
|
||||||
.section .note.GNU-stack,"",@progbits
|
|
||||||
#endif
|
|
||||||
/* ---------------------------------------------- */
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
/* ---------------------------------------------- */
|
|
||||||
/* alloca86.S */
|
|
||||||
|
|
||||||
.globl alloca
|
|
||||||
|
|
||||||
alloca:
|
|
||||||
pop %edx
|
|
||||||
pop %eax
|
|
||||||
add $3,%eax
|
|
||||||
and $-4,%eax
|
|
||||||
jz p3
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
p1:
|
|
||||||
cmp $4096,%eax
|
|
||||||
jbe p2
|
|
||||||
test %eax,-4096(%esp)
|
|
||||||
sub $4096,%esp
|
|
||||||
sub $4096,%eax
|
|
||||||
jmp p1
|
|
||||||
p2:
|
|
||||||
#endif
|
|
||||||
|
|
||||||
sub %eax,%esp
|
|
||||||
mov %esp,%eax
|
|
||||||
p3:
|
|
||||||
push %edx
|
|
||||||
push %edx
|
|
||||||
ret
|
|
||||||
|
|
||||||
/* ---------------------------------------------- */
|
|
||||||
@ -1,56 +0,0 @@
|
|||||||
/* ---------------------------------------------- */
|
|
||||||
/* alloca86_64.S */
|
|
||||||
|
|
||||||
.globl __bound_alloca
|
|
||||||
__bound_alloca:
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
# bound checking is not implemented
|
|
||||||
pop %rdx
|
|
||||||
mov %rcx,%rax
|
|
||||||
add $15,%rax
|
|
||||||
and $-16,%rax
|
|
||||||
jz p3
|
|
||||||
|
|
||||||
p1:
|
|
||||||
cmp $4096,%rax
|
|
||||||
jbe p2
|
|
||||||
test %rax,-4096(%rsp)
|
|
||||||
sub $4096,%rsp
|
|
||||||
sub $4096,%rax
|
|
||||||
jmp p1
|
|
||||||
p2:
|
|
||||||
|
|
||||||
sub %rax,%rsp
|
|
||||||
mov %rsp,%rax
|
|
||||||
add $32,%rax
|
|
||||||
|
|
||||||
p3:
|
|
||||||
push %rdx
|
|
||||||
ret
|
|
||||||
#else
|
|
||||||
pop %rdx
|
|
||||||
mov %rdi,%rax
|
|
||||||
mov %rax,%rsi # size, a second parm to the __bound_new_region
|
|
||||||
|
|
||||||
add $15,%rax
|
|
||||||
and $-16,%rax
|
|
||||||
jz p3
|
|
||||||
|
|
||||||
|
|
||||||
sub %rax,%rsp
|
|
||||||
mov %rsp,%rdi # pointer, a first parm to the __bound_new_region
|
|
||||||
mov %rsp,%rax
|
|
||||||
|
|
||||||
push %rdx
|
|
||||||
push %rax
|
|
||||||
call __bound_new_region
|
|
||||||
pop %rax
|
|
||||||
pop %rdx
|
|
||||||
|
|
||||||
p3:
|
|
||||||
push %rdx
|
|
||||||
ret
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ---------------------------------------------- */
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
/* ---------------------------------------------- */
|
|
||||||
/* alloca86_64.S */
|
|
||||||
|
|
||||||
.globl alloca
|
|
||||||
|
|
||||||
alloca:
|
|
||||||
pop %rdx
|
|
||||||
#ifdef _WIN32
|
|
||||||
mov %rcx,%rax
|
|
||||||
#else
|
|
||||||
mov %rdi,%rax
|
|
||||||
#endif
|
|
||||||
add $15,%rax
|
|
||||||
and $-16,%rax
|
|
||||||
jz p3
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
p1:
|
|
||||||
cmp $4096,%rax
|
|
||||||
jbe p2
|
|
||||||
test %rax,-4096(%rsp)
|
|
||||||
sub $4096,%rsp
|
|
||||||
sub $4096,%rax
|
|
||||||
jmp p1
|
|
||||||
p2:
|
|
||||||
#endif
|
|
||||||
|
|
||||||
sub %rax,%rsp
|
|
||||||
mov %rsp,%rax
|
|
||||||
p3:
|
|
||||||
push %rdx
|
|
||||||
ret
|
|
||||||
|
|
||||||
/* ---------------------------------------------- */
|
|
||||||
149
lib/armeabi.c
149
lib/armeabi.c
@ -47,7 +47,7 @@ typedef struct unsigned_int_struct {
|
|||||||
} unsigned_int_struct;
|
} unsigned_int_struct;
|
||||||
|
|
||||||
#define REGS_RETURN(name, type) \
|
#define REGS_RETURN(name, type) \
|
||||||
void name ## _return(type ret) {}
|
static void name ## _return(type ret) {}
|
||||||
|
|
||||||
|
|
||||||
/* Float helper functions */
|
/* Float helper functions */
|
||||||
@ -137,6 +137,11 @@ void __aeabi_ ## name(double_unsigned_struct val) \
|
|||||||
int exp, high_shift, sign; \
|
int exp, high_shift, sign; \
|
||||||
double_unsigned_struct ret; \
|
double_unsigned_struct ret; \
|
||||||
\
|
\
|
||||||
|
if ((val.high & ~0x80000000) == 0 && val.low == 0) { \
|
||||||
|
ret.low = ret.high = 0; \
|
||||||
|
goto _ret_; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
/* compute sign */ \
|
/* compute sign */ \
|
||||||
sign = val.high >> 31; \
|
sign = val.high >> 31; \
|
||||||
\
|
\
|
||||||
@ -172,7 +177,7 @@ void __aeabi_ ## name(double_unsigned_struct val) \
|
|||||||
ret.high = 0; \
|
ret.high = 0; \
|
||||||
ret.low = 1 << exp; \
|
ret.low = 1 << exp; \
|
||||||
if (exp > DOUBLE_FRAC_BITS - 32) { \
|
if (exp > DOUBLE_FRAC_BITS - 32) { \
|
||||||
high_shift = exp - DOUBLE_FRAC_BITS - 32; \
|
high_shift = exp - (DOUBLE_FRAC_BITS - 32); \
|
||||||
ret.low |= val.high << high_shift; \
|
ret.low |= val.high << high_shift; \
|
||||||
ret.low |= val.low >> (32 - high_shift); \
|
ret.low |= val.low >> (32 - high_shift); \
|
||||||
} else \
|
} else \
|
||||||
@ -190,6 +195,7 @@ void __aeabi_ ## name(double_unsigned_struct val) \
|
|||||||
ret.low++; \
|
ret.low++; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
|
_ret_: \
|
||||||
double_unsigned_struct_return(ret); \
|
double_unsigned_struct_return(ret); \
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,7 +319,7 @@ void __aeabi_ ## name(unsigned long long v) \
|
|||||||
} \
|
} \
|
||||||
} else { \
|
} else { \
|
||||||
ret.high = ret.low = 0; \
|
ret.high = ret.low = 0; \
|
||||||
double_unsigned_struct_return(ret); \
|
goto _ret_; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
@ -323,6 +329,7 @@ void __aeabi_ ## name(unsigned long long v) \
|
|||||||
/* fill sign bit */ \
|
/* fill sign bit */ \
|
||||||
ret.high |= sign << 31; \
|
ret.high |= sign << 31; \
|
||||||
\
|
\
|
||||||
|
_ret_: \
|
||||||
double_unsigned_struct_return(ret); \
|
double_unsigned_struct_return(ret); \
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,7 +339,7 @@ __AEABI_XL2D(ul2d, 0)
|
|||||||
/* long long to double conversion */
|
/* long long to double conversion */
|
||||||
__AEABI_XL2D(l2d, 1)
|
__AEABI_XL2D(l2d, 1)
|
||||||
|
|
||||||
|
#if 1
|
||||||
/* Long long helper functions */
|
/* Long long helper functions */
|
||||||
|
|
||||||
/* TODO: add error in case of den == 0 (see §4.3.1 and §4.3.2) */
|
/* TODO: add error in case of den == 0 (see §4.3.1 and §4.3.2) */
|
||||||
@ -467,6 +474,7 @@ void __aeabi_lasr(unsigned_int_struct val, int shift)
|
|||||||
|
|
||||||
/* Integer division functions */
|
/* Integer division functions */
|
||||||
|
|
||||||
|
#if 0 /* very slow */
|
||||||
AEABI_UXDIVMOD(uidivmod, unsigned, uidiv_t, UINT)
|
AEABI_UXDIVMOD(uidivmod, unsigned, uidiv_t, UINT)
|
||||||
|
|
||||||
int __aeabi_idiv(int numerator, int denominator)
|
int __aeabi_idiv(int numerator, int denominator)
|
||||||
@ -499,3 +507,136 @@ void __aeabi_uidivmod(unsigned num, unsigned den)
|
|||||||
{
|
{
|
||||||
uidiv_t_return(aeabi_uidivmod(num, den));
|
uidiv_t_return(aeabi_uidivmod(num, den));
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
# define UIDIVMOD_ASM 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Some targets do not have all eabi calls (OpenBSD) */
|
||||||
|
typedef __SIZE_TYPE__ size_t;
|
||||||
|
extern void *memcpy(void *dest, const void *src, size_t n);
|
||||||
|
extern void *memmove(void *dest, const void *src, size_t n);
|
||||||
|
extern void *memset(void *s, int c, size_t n);
|
||||||
|
|
||||||
|
void *
|
||||||
|
__aeabi_memcpy (void *dest, const void *src, size_t n)
|
||||||
|
{
|
||||||
|
return memcpy (dest, src, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
__aeabi_memmove (void *dest, const void *src, size_t n)
|
||||||
|
{
|
||||||
|
return memmove (dest, src, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
__aeabi_memmove4 (void *dest, const void *src, size_t n)
|
||||||
|
{
|
||||||
|
return memmove (dest, src, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
__aeabi_memmove8 (void *dest, const void *src, size_t n)
|
||||||
|
{
|
||||||
|
return memmove (dest, src, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
__aeabi_memset (void *s, size_t n, int c)
|
||||||
|
{
|
||||||
|
return memset (s, c, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ***************************************************************** */
|
||||||
|
#if UIDIVMOD_ASM
|
||||||
|
#include <config.h>
|
||||||
|
__asm__(
|
||||||
|
"\n .global __aeabi_idiv, __aeabi_idivmod"
|
||||||
|
"\n .global __aeabi_uidiv, __aeabi_uidivmod"
|
||||||
|
#if __ARM_FEATURE_IDIV
|
||||||
|
"\n__aeabi_idiv:"
|
||||||
|
"\n__aeabi_idivmod:"
|
||||||
|
"\n mov r2, r0"
|
||||||
|
"\n sdiv r0, r0, r1"
|
||||||
|
"\n mls r1, r1, r0, r2"
|
||||||
|
"\n bx lr"
|
||||||
|
|
||||||
|
"\n__aeabi_uidiv:"
|
||||||
|
"\n__aeabi_uidivmod:"
|
||||||
|
"\n mov r2, r0"
|
||||||
|
"\n udiv r0, r0, r1"
|
||||||
|
"\n mls r1, r1, r0, r2"
|
||||||
|
"\n bx lr"
|
||||||
|
#else
|
||||||
|
/* Runtime ABI for the ARM Cortex-M0
|
||||||
|
* idivmod.S: signed 32 bit division (quotient and remainder)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 Jörg Mische <bobbl@gmx.de>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*/
|
||||||
|
"\n__aeabi_idiv:"
|
||||||
|
"\n__aeabi_idivmod:"
|
||||||
|
"\n cmp r0, #0"
|
||||||
|
"\n bge .Lnumerator_pos"
|
||||||
|
"\n rsb r0, r0, #0" // num = -num
|
||||||
|
"\n cmp r1, #0"
|
||||||
|
"\n bge .Lboth_neg"
|
||||||
|
"\n rsb r1, r1, #0" // den = -den
|
||||||
|
"\n push {lr}"
|
||||||
|
"\n bl __aeabi_uidivmod"
|
||||||
|
"\n rsb r1, r1, #0" // rem = -rem
|
||||||
|
"\n pop {pc}"
|
||||||
|
"\n.Lboth_neg:"
|
||||||
|
"\n push {lr}"
|
||||||
|
"\n bl __aeabi_uidivmod"
|
||||||
|
"\n rsb r0, r0, #0" // quot = -quot
|
||||||
|
"\n rsb r1, r1, #0" // rem = -rem
|
||||||
|
"\n pop {pc}"
|
||||||
|
"\n.Ldenom_neg:"
|
||||||
|
"\n rsb r1, r1, #0" // den = -den
|
||||||
|
"\n push {lr}"
|
||||||
|
"\n bl __aeabi_uidivmod"
|
||||||
|
"\n rsb r0, r0, #0" // quot = -quot
|
||||||
|
"\n pop {pc}"
|
||||||
|
"\n.Lnumerator_pos:"
|
||||||
|
"\n cmp r1, #0"
|
||||||
|
"\n blt .Ldenom_neg"
|
||||||
|
|
||||||
|
// Divide r0 by r1 and return the quotient in r0 and the remainder in r1
|
||||||
|
"\n__aeabi_uidiv:"
|
||||||
|
"\n__aeabi_uidivmod:"
|
||||||
|
// Shift left the denominator until it is greater than the numerator
|
||||||
|
"\n mov r2, #1" // counter
|
||||||
|
"\n mov r3, #0" // result
|
||||||
|
"\n cmp r0, r1"
|
||||||
|
"\n bls .Lsub_loop"
|
||||||
|
"\n adds r1, #0" // dont shift if denominator would overflow
|
||||||
|
"\n bmi .Lsub_loop"
|
||||||
|
"\n beq .Luidiv0"
|
||||||
|
"\n.Ldenom_shift_loop:"
|
||||||
|
"\n lsl r2, #1"
|
||||||
|
"\n lsls r1, #1"
|
||||||
|
"\n bmi .Lsub_loop"
|
||||||
|
"\n cmp r0, r1"
|
||||||
|
"\n bhi .Ldenom_shift_loop"
|
||||||
|
"\n.Lsub_loop:"
|
||||||
|
"\n cmp r0, r1" // if (num >= den)...
|
||||||
|
"\n subcs r0, r1" // numerator -= denom
|
||||||
|
"\n orrcs r3, r2" // result(r3) |= bitmask(r2)
|
||||||
|
"\n lsr r1, #1" // denom(r1) >>= 1
|
||||||
|
"\n lsrs r2, #1" // bitmask(r2) >>= 1
|
||||||
|
"\n bne .Lsub_loop"
|
||||||
|
"\n mov r1, r0" // remainder(r1) = numerator(r0)
|
||||||
|
"\n mov r0, r3" // quotient(r0) = result(r3)
|
||||||
|
"\n bx lr"
|
||||||
|
"\n.Luidiv0:" // XXX: division by zero
|
||||||
|
"\n mov r0, #0"
|
||||||
|
"\n bx lr"
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
#endif /* UIDIVMOD_ASM */
|
||||||
|
/* ***************************************************************** */
|
||||||
|
#endif
|
||||||
|
|||||||
@ -4,22 +4,25 @@
|
|||||||
intrinsic with gcc. However tcc in order to compile
|
intrinsic with gcc. However tcc in order to compile
|
||||||
itself needs this function */
|
itself needs this function */
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------- */
|
||||||
|
#if defined __arm__
|
||||||
|
|
||||||
#ifdef __TINYC__
|
#ifdef __TINYC__
|
||||||
|
|
||||||
/* syscall wrapper */
|
/* syscall wrapper */
|
||||||
unsigned syscall(unsigned syscall_nr, ...);
|
unsigned _tccsyscall(unsigned syscall_nr, ...);
|
||||||
|
|
||||||
/* arm-tcc supports only fake asm currently */
|
/* arm-tcc supports only fake asm currently */
|
||||||
__asm__(
|
__asm__(
|
||||||
".global syscall\n"
|
".global _tccsyscall\n"
|
||||||
"syscall:\n"
|
"_tccsyscall:\n"
|
||||||
".int 0xe92d4080\n" // push {r7, lr}
|
"push {r7, lr}\n\t"
|
||||||
".int 0xe1a07000\n" // mov r7, r0
|
"mov r7, r0\n\t"
|
||||||
".int 0xe1a00001\n" // mov r0, r1
|
"mov r0, r1\n\t"
|
||||||
".int 0xe1a01002\n" // mov r1, r2
|
"mov r1, r2\n\t"
|
||||||
".int 0xe1a02003\n" // mov r2, r3
|
"mov r2, r3\n\t"
|
||||||
".int 0xef000000\n" // svc 0x00000000
|
"svc #0\n\t"
|
||||||
".int 0xe8bd8080\n" // pop {r7, pc}
|
"pop {r7, pc}"
|
||||||
);
|
);
|
||||||
|
|
||||||
/* from unistd.h: */
|
/* from unistd.h: */
|
||||||
@ -31,6 +34,8 @@ __asm__(
|
|||||||
#define __ARM_NR_BASE (__NR_SYSCALL_BASE+0x0f0000)
|
#define __ARM_NR_BASE (__NR_SYSCALL_BASE+0x0f0000)
|
||||||
#define __ARM_NR_cacheflush (__ARM_NR_BASE+2)
|
#define __ARM_NR_cacheflush (__ARM_NR_BASE+2)
|
||||||
|
|
||||||
|
#define syscall _tccsyscall
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
@ -45,14 +50,15 @@ void __clear_cache(void *beginning, void *end)
|
|||||||
{
|
{
|
||||||
/* __ARM_NR_cacheflush is kernel private and should not be used in user space.
|
/* __ARM_NR_cacheflush is kernel private and should not be used in user space.
|
||||||
* However, there is no ARM asm parser in tcc so we use it for now */
|
* However, there is no ARM asm parser in tcc so we use it for now */
|
||||||
#if 1
|
|
||||||
syscall(__ARM_NR_cacheflush, beginning, end, 0);
|
syscall(__ARM_NR_cacheflush, beginning, end, 0);
|
||||||
#else
|
|
||||||
__asm__ ("push {r7}\n\t"
|
|
||||||
"mov r7, #0xf0002\n\t"
|
|
||||||
"mov r2, #0\n\t"
|
|
||||||
"swi 0\n\t"
|
|
||||||
"pop {r7}\n\t"
|
|
||||||
"ret");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------- */
|
||||||
|
#elif defined __aarch64__
|
||||||
|
void __clear_cache(void *beg, void *end)
|
||||||
|
{
|
||||||
|
__arm64_clear_cache(beg, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------- */
|
||||||
|
#endif
|
||||||
|
|||||||
2669
lib/atomic.S
Normal file
2669
lib/atomic.S
Normal file
File diff suppressed because it is too large
Load Diff
2760
lib/bcheck.c
2760
lib/bcheck.c
File diff suppressed because it is too large
Load Diff
95
lib/bt-dll.c
Normal file
95
lib/bt-dll.c
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/* ------------------------------------------------------------- */
|
||||||
|
/* stubs for calling bcheck functions from a dll. */
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define REDIR_ALL \
|
||||||
|
REDIR(__bt_init) \
|
||||||
|
REDIR(__bt_exit) \
|
||||||
|
REDIR(tcc_backtrace) \
|
||||||
|
\
|
||||||
|
REDIR(__bound_ptr_add) \
|
||||||
|
REDIR(__bound_ptr_indir1) \
|
||||||
|
REDIR(__bound_ptr_indir2) \
|
||||||
|
REDIR(__bound_ptr_indir4) \
|
||||||
|
REDIR(__bound_ptr_indir8) \
|
||||||
|
REDIR(__bound_ptr_indir12) \
|
||||||
|
REDIR(__bound_ptr_indir16) \
|
||||||
|
REDIR(__bound_local_new) \
|
||||||
|
REDIR(__bound_local_delete) \
|
||||||
|
REDIR(__bound_new_region) \
|
||||||
|
\
|
||||||
|
REDIR(__bound_free) \
|
||||||
|
REDIR(__bound_malloc) \
|
||||||
|
REDIR(__bound_realloc) \
|
||||||
|
REDIR(__bound_memcpy) \
|
||||||
|
REDIR(__bound_memcmp) \
|
||||||
|
REDIR(__bound_memmove) \
|
||||||
|
REDIR(__bound_memset) \
|
||||||
|
REDIR(__bound_strlen) \
|
||||||
|
REDIR(__bound_strcpy) \
|
||||||
|
REDIR(__bound_strncpy) \
|
||||||
|
REDIR(__bound_strcmp) \
|
||||||
|
REDIR(__bound_strncmp) \
|
||||||
|
REDIR(__bound_strcat) \
|
||||||
|
REDIR(__bound_strchr) \
|
||||||
|
REDIR(__bound_strdup) \
|
||||||
|
REDIR(__bound_strncat) \
|
||||||
|
REDIR(__bound_strrchr) \
|
||||||
|
REDIR(__bound_setjmp) \
|
||||||
|
REDIR(__bound_longjmp)
|
||||||
|
|
||||||
|
#ifdef __leading_underscore
|
||||||
|
#define _(s) "_"#s
|
||||||
|
#else
|
||||||
|
#define _(s) #s
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define REDIR(s) void *s;
|
||||||
|
static struct { REDIR_ALL } all_ptrs;
|
||||||
|
#undef REDIR
|
||||||
|
|
||||||
|
#define REDIR(s) #s"\0"
|
||||||
|
static const char all_names[] = REDIR_ALL;
|
||||||
|
#undef REDIR
|
||||||
|
|
||||||
|
#if __aarch64__
|
||||||
|
# define REDIR(s) \
|
||||||
|
__asm__(".global "_(s)";"_(s)":"); \
|
||||||
|
__asm__(".int 0x58000090"); /* ldr x16, [pc, #16] */ \
|
||||||
|
__asm__(".int 0xf9400210"); /* ldr x16, [x16] */ \
|
||||||
|
__asm__(".int 0xd61f0200"); /* br x16 */ \
|
||||||
|
__asm__(".int 0xd503201f"); /* nop for alignment */ \
|
||||||
|
__asm__(".quad all_ptrs + (. - all_jmps - 16) / 24 * 8"); \
|
||||||
|
__asm__(".type "_(s)",function\n.size "_(s)",.-"_(s));
|
||||||
|
|
||||||
|
__asm__(".text\n.align 8\nall_jmps:");
|
||||||
|
REDIR_ALL
|
||||||
|
#else
|
||||||
|
# define REDIR(s) \
|
||||||
|
__asm__(".global "_(s)";"_(s)":"); goto *all_ptrs.s;
|
||||||
|
static void all_jmps() { REDIR_ALL }
|
||||||
|
#endif
|
||||||
|
#undef REDIR
|
||||||
|
|
||||||
|
void __bt_init_dll(int bcheck)
|
||||||
|
{
|
||||||
|
const char *s = all_names;
|
||||||
|
void **p = (void**)&all_ptrs;
|
||||||
|
do {
|
||||||
|
*p = (void*)GetProcAddress(GetModuleHandle(NULL), (char*)s);
|
||||||
|
if (NULL == *p) {
|
||||||
|
char buf[100];
|
||||||
|
sprintf(buf,
|
||||||
|
"Error: function '%s()' not found in executable. "
|
||||||
|
"(Need -bt or -b for linking the exe.)", s);
|
||||||
|
if (GetStdHandle(STD_ERROR_HANDLE))
|
||||||
|
fprintf(stderr, "TCC/BCHECK: %s\n", buf), fflush(stderr);
|
||||||
|
else
|
||||||
|
MessageBox(NULL, buf, "TCC/BCHECK", MB_ICONERROR);
|
||||||
|
ExitProcess(1);
|
||||||
|
}
|
||||||
|
s = strchr(s,'\0') + 1, ++p;
|
||||||
|
} while (*s && (bcheck || p < &all_ptrs.__bound_ptr_add));
|
||||||
|
}
|
||||||
87
lib/bt-exe.c
Normal file
87
lib/bt-exe.c
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/* ------------------------------------------------------------- */
|
||||||
|
/* for linking rt_printline and the signal/exception handler
|
||||||
|
from tccrun.c into executables. */
|
||||||
|
|
||||||
|
#define CONFIG_TCC_BACKTRACE_ONLY
|
||||||
|
#define ONE_SOURCE 1
|
||||||
|
#define pstrcpy tcc_pstrcpy
|
||||||
|
#include "../tccrun.c"
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
# define __declspec(n)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN64
|
||||||
|
static void bt_init_pe_prog_base(rt_context *p)
|
||||||
|
{
|
||||||
|
MEMORY_BASIC_INFORMATION mbi;
|
||||||
|
addr_t imagebase;
|
||||||
|
|
||||||
|
if (!p->prog_base)
|
||||||
|
return;
|
||||||
|
if (!VirtualQuery(p, &mbi, sizeof(mbi)) || !mbi.AllocationBase)
|
||||||
|
return;
|
||||||
|
imagebase = (addr_t)mbi.AllocationBase - p->prog_base;
|
||||||
|
p->prog_base = (addr_t)mbi.AllocationBase - (imagebase & 0xffffffffu);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
__declspec(dllexport)
|
||||||
|
void __bt_init(rt_context *p, int is_exe)
|
||||||
|
{
|
||||||
|
__attribute__((weak)) int main();
|
||||||
|
__attribute__((weak)) void __bound_init(void*, int);
|
||||||
|
|
||||||
|
//fprintf(stderr, "__bt_init %d %p %p %p\n", is_exe, p, p->stab_sym, p->bounds_start), fflush(stderr);
|
||||||
|
|
||||||
|
/* call __bound_init here due to redirection of sigaction */
|
||||||
|
/* needed to add global symbols */
|
||||||
|
if (p->bounds_start)
|
||||||
|
__bound_init(p->bounds_start, -1);
|
||||||
|
|
||||||
|
#ifdef _WIN64
|
||||||
|
bt_init_pe_prog_base(p);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* add to chain */
|
||||||
|
rt_wait_sem();
|
||||||
|
p->next = g_rc, g_rc = p;
|
||||||
|
rt_post_sem();
|
||||||
|
if (is_exe) {
|
||||||
|
/* we are the executable (not a dll) */
|
||||||
|
p->top_func = main;
|
||||||
|
set_exception_handler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__declspec(dllexport)
|
||||||
|
void __bt_exit(rt_context *p)
|
||||||
|
{
|
||||||
|
struct rt_context *rc, **pp;
|
||||||
|
__attribute__((weak)) void __bound_exit_dll(void*);
|
||||||
|
|
||||||
|
//fprintf(stderr, "__bt_exit %d %p\n", !!p->top_func, p);
|
||||||
|
|
||||||
|
if (p->bounds_start)
|
||||||
|
__bound_exit_dll(p->bounds_start);
|
||||||
|
|
||||||
|
/* remove from chain */
|
||||||
|
rt_wait_sem();
|
||||||
|
for (pp = &g_rc; rc = *pp, rc; pp = &rc->next)
|
||||||
|
if (rc == p) {
|
||||||
|
*pp = rc->next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rt_post_sem();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy a string and truncate it. */
|
||||||
|
ST_FUNC char *pstrcpy(char *buf, size_t buf_size, const char *s)
|
||||||
|
{
|
||||||
|
int l = strlen(s);
|
||||||
|
if (l >= buf_size)
|
||||||
|
l = buf_size - 1;
|
||||||
|
memcpy(buf, s, l);
|
||||||
|
buf[l] = 0;
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
56
lib/bt-log.c
Normal file
56
lib/bt-log.c
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/* ------------------------------------------------------------- */
|
||||||
|
/* function to get a stack backtrace on demand with a message */
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#undef __attribute__
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# define DLL_EXPORT __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
# define DLL_EXPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Needed when using ...libtcc1-usegcc=yes in lib/Makefile */
|
||||||
|
#if (defined(__GNUC__) && (__GNUC__ >= 6)) || defined(__clang__)
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wframe-address"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct rt_frame {
|
||||||
|
void *ip, *fp, *sp;
|
||||||
|
} rt_frame;
|
||||||
|
|
||||||
|
__attribute__((weak))
|
||||||
|
int _tcc_backtrace(rt_frame *f, const char *fmt, va_list ap);
|
||||||
|
|
||||||
|
DLL_EXPORT int tcc_backtrace(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (_tcc_backtrace) {
|
||||||
|
rt_frame f;
|
||||||
|
f.fp = __builtin_frame_address(1);
|
||||||
|
f.ip = __builtin_return_address(0);
|
||||||
|
va_start(ap, fmt);
|
||||||
|
ret = _tcc_backtrace(&f, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
} else {
|
||||||
|
const char *p, *nl = "\n";
|
||||||
|
if (fmt[0] == '^' && (p = strchr(fmt + 1, fmt[0])))
|
||||||
|
fmt = p + 1;
|
||||||
|
if (fmt[0] == '\001')
|
||||||
|
++fmt, nl = "";
|
||||||
|
va_start(ap, fmt);
|
||||||
|
ret = vfprintf(stderr, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
fprintf(stderr, "%s", nl), fflush(stderr);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (defined(__GNUC__) && (__GNUC__ >= 6)) || defined(__clang__)
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
164
lib/builtin.c
Normal file
164
lib/builtin.c
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
/* uses alias to allow building with gcc/clang */
|
||||||
|
#ifdef __TINYC__
|
||||||
|
#define BUILTIN(x) __builtin_##x
|
||||||
|
#define BUILTINN(x) "__builtin_" # x
|
||||||
|
#else
|
||||||
|
#define BUILTIN(x) __tcc_builtin_##x
|
||||||
|
#define BUILTINN(x) "__tcc_builtin_" # x
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ---------------------------------------------- */
|
||||||
|
/* This file implements:
|
||||||
|
* __builtin_ffs
|
||||||
|
* __builtin_clz
|
||||||
|
* __builtin_ctz
|
||||||
|
* __builtin_clrsb
|
||||||
|
* __builtin_popcount
|
||||||
|
* __builtin_parity
|
||||||
|
* for int, long and long long
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const unsigned char table_1_32[] = {
|
||||||
|
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
|
||||||
|
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
|
||||||
|
};
|
||||||
|
static const unsigned char table_2_32[32] = {
|
||||||
|
31, 22, 30, 21, 18, 10, 29, 2, 20, 17, 15, 13, 9, 6, 28, 1,
|
||||||
|
23, 19, 11, 3, 16, 14, 7, 24, 12, 4, 8, 25, 5, 26, 27, 0
|
||||||
|
};
|
||||||
|
static const unsigned char table_1_64[] = {
|
||||||
|
0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28,
|
||||||
|
62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11,
|
||||||
|
63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,
|
||||||
|
51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12
|
||||||
|
};
|
||||||
|
static const unsigned char table_2_64[] = {
|
||||||
|
63, 16, 62, 7, 15, 36, 61, 3, 6, 14, 22, 26, 35, 47, 60, 2,
|
||||||
|
9, 5, 28, 11, 13, 21, 42, 19, 25, 31, 34, 40, 46, 52, 59, 1,
|
||||||
|
17, 8, 37, 4, 23, 27, 48, 10, 29, 12, 43, 20, 32, 41, 53, 18,
|
||||||
|
38, 24, 49, 30, 44, 33, 54, 39, 50, 45, 55, 51, 56, 57, 58, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
#define FFSI(x) \
|
||||||
|
return table_1_32[((x & -x) * 0x077cb531u) >> 27] + (x != 0);
|
||||||
|
#define FFSL(x) \
|
||||||
|
return table_1_64[((x & -x) * 0x022fdd63cc95386dull) >> 58] + (x != 0);
|
||||||
|
#define CTZI(x) \
|
||||||
|
return table_1_32[((x & -x) * 0x077cb531u) >> 27];
|
||||||
|
#define CTZL(x) \
|
||||||
|
return table_1_64[((x & -x) * 0x022fdd63cc95386dull) >> 58];
|
||||||
|
#define CLZI(x) \
|
||||||
|
x |= x >> 1; \
|
||||||
|
x |= x >> 2; \
|
||||||
|
x |= x >> 4; \
|
||||||
|
x |= x >> 8; \
|
||||||
|
x |= x >> 16; \
|
||||||
|
return table_2_32[(x * 0x07c4acddu) >> 27];
|
||||||
|
#define CLZL(x) \
|
||||||
|
x |= x >> 1; \
|
||||||
|
x |= x >> 2; \
|
||||||
|
x |= x >> 4; \
|
||||||
|
x |= x >> 8; \
|
||||||
|
x |= x >> 16; \
|
||||||
|
x |= x >> 32; \
|
||||||
|
return table_2_64[x * 0x03f79d71b4cb0a89ull >> 58];
|
||||||
|
#define POPCOUNTI(x, m) \
|
||||||
|
x = x - ((x >> 1) & 0x55555555); \
|
||||||
|
x = (x & 0x33333333) + ((x >> 2) & 0x33333333); \
|
||||||
|
x = (x + (x >> 4)) & 0xf0f0f0f; \
|
||||||
|
return ((x * 0x01010101) >> 24) & m;
|
||||||
|
#define POPCOUNTL(x, m) \
|
||||||
|
x = x - ((x >> 1) & 0x5555555555555555ull); \
|
||||||
|
x = (x & 0x3333333333333333ull) + ((x >> 2) & 0x3333333333333333ull); \
|
||||||
|
x = (x + (x >> 4)) & 0xf0f0f0f0f0f0f0full; \
|
||||||
|
return ((x * 0x0101010101010101ull) >> 56) & m;
|
||||||
|
|
||||||
|
/* Returns one plus the index of the least significant 1-bit of x,
|
||||||
|
or if x is zero, returns zero. */
|
||||||
|
int BUILTIN(ffs) (int x) { FFSI(x) }
|
||||||
|
int BUILTIN(ffsll) (long long x) { FFSL(x) }
|
||||||
|
#if __SIZEOF_LONG__ == 4
|
||||||
|
int BUILTIN(ffsl) (long x) __attribute__((alias(BUILTINN(ffs))));
|
||||||
|
#else
|
||||||
|
int BUILTIN(ffsl) (long x) __attribute__((alias(BUILTINN(ffsll))));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Returns the number of leading 0-bits in x, starting at the most significant
|
||||||
|
bit position. If x is 0, the result is undefined. */
|
||||||
|
int BUILTIN(clz) (unsigned int x) { CLZI(x) }
|
||||||
|
int BUILTIN(clzll) (unsigned long long x) { CLZL(x) }
|
||||||
|
#if __SIZEOF_LONG__ == 4
|
||||||
|
int BUILTIN(clzl) (unsigned long x) __attribute__((alias(BUILTINN(clz))));
|
||||||
|
#else
|
||||||
|
int BUILTIN(clzl) (unsigned long x) __attribute__((alias(BUILTINN(clzll))));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Returns the number of trailing 0-bits in x, starting at the least
|
||||||
|
significant bit position. If x is 0, the result is undefined. */
|
||||||
|
int BUILTIN(ctz) (unsigned int x) { CTZI(x) }
|
||||||
|
int BUILTIN(ctzll) (unsigned long long x) { CTZL(x) }
|
||||||
|
#if __SIZEOF_LONG__ == 4
|
||||||
|
int BUILTIN(ctzl) (unsigned long x) __attribute__((alias(BUILTINN(ctz))));
|
||||||
|
#else
|
||||||
|
int BUILTIN(ctzl) (unsigned long x) __attribute__((alias(BUILTINN(ctzll))));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Returns the number of leading redundant sign bits in x, i.e. the number
|
||||||
|
of bits following the most significant bit that are identical to it.
|
||||||
|
There are no special cases for 0 or other values. */
|
||||||
|
int BUILTIN(clrsb) (int x) { if (x < 0) x = ~x; x <<= 1; CLZI(x) }
|
||||||
|
int BUILTIN(clrsbll) (long long x) { if (x < 0) x = ~x; x <<= 1; CLZL(x) }
|
||||||
|
#if __SIZEOF_LONG__ == 4
|
||||||
|
int BUILTIN(clrsbl) (long x) __attribute__((alias(BUILTINN(clrsb))));
|
||||||
|
#else
|
||||||
|
int BUILTIN(clrsbl) (long x) __attribute__((alias(BUILTINN(clrsbll))));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Returns the number of 1-bits in x.*/
|
||||||
|
int BUILTIN(popcount) (unsigned int x) { POPCOUNTI(x, 0x3f) }
|
||||||
|
int BUILTIN(popcountll) (unsigned long long x) { POPCOUNTL(x, 0x7f) }
|
||||||
|
#if __SIZEOF_LONG__ == 4
|
||||||
|
int BUILTIN(popcountl) (unsigned long x) __attribute__((alias(BUILTINN(popcount))));
|
||||||
|
#else
|
||||||
|
int BUILTIN(popcountl ) (unsigned long x) __attribute__((alias(BUILTINN(popcountll))));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Returns the parity of x, i.e. the number of 1-bits in x modulo 2. */
|
||||||
|
int BUILTIN(parity) (unsigned int x) { POPCOUNTI(x, 0x01) }
|
||||||
|
int BUILTIN(parityll) (unsigned long long x) { POPCOUNTL(x, 0x01) }
|
||||||
|
#if __SIZEOF_LONG__ == 4
|
||||||
|
int BUILTIN(parityl) (unsigned long x) __attribute__((alias(BUILTINN(parity))));
|
||||||
|
#else
|
||||||
|
int BUILTIN(parityl) (unsigned long x) __attribute__((alias(BUILTINN(parityll))));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __TINYC__
|
||||||
|
#if defined(__GNUC__) && (__GNUC__ >= 6)
|
||||||
|
/* gcc overrides alias from __builtin_ffs... to ffs.. so use assembly code */
|
||||||
|
__asm__(".globl __builtin_ffs");
|
||||||
|
__asm__(".set __builtin_ffs,__tcc_builtin_ffs");
|
||||||
|
__asm__(".globl __builtin_ffsl");
|
||||||
|
__asm__(".set __builtin_ffsl,__tcc_builtin_ffsl");
|
||||||
|
__asm__(".globl __builtin_ffsll");
|
||||||
|
__asm__(".set __builtin_ffsll,__tcc_builtin_ffsll");
|
||||||
|
#else
|
||||||
|
int __builtin_ffs(int x) __attribute__((alias("__tcc_builtin_ffs")));
|
||||||
|
int __builtin_ffsl(long x) __attribute__((alias("__tcc_builtin_ffsl")));
|
||||||
|
int __builtin_ffsll(long long x) __attribute__((alias("__tcc_builtin_ffsll")));
|
||||||
|
#endif
|
||||||
|
int __builtin_clz(unsigned int x) __attribute__((alias("__tcc_builtin_clz")));
|
||||||
|
int __builtin_clzl(unsigned long x) __attribute__((alias("__tcc_builtin_clzl")));
|
||||||
|
int __builtin_clzll(unsigned long long x) __attribute__((alias("__tcc_builtin_clzll")));
|
||||||
|
int __builtin_ctz(unsigned int x) __attribute__((alias("__tcc_builtin_ctz")));
|
||||||
|
int __builtin_ctzl(unsigned long x) __attribute__((alias("__tcc_builtin_ctzl")));
|
||||||
|
int __builtin_ctzll(unsigned long long x) __attribute__((alias("__tcc_builtin_ctzll")));
|
||||||
|
int __builtin_clrsb(int x) __attribute__((alias("__tcc_builtin_clrsb")));
|
||||||
|
int __builtin_clrsbl(long x) __attribute__((alias("__tcc_builtin_clrsbl")));
|
||||||
|
int __builtin_clrsbll(long long x) __attribute__((alias("__tcc_builtin_clrsbll")));
|
||||||
|
int __builtin_popcount(unsigned int x) __attribute__((alias("__tcc_builtin_popcount")));
|
||||||
|
int __builtin_popcountl(unsigned long x) __attribute__((alias("__tcc_builtin_popcountl")));
|
||||||
|
int __builtin_popcountll(unsigned long long x) __attribute__((alias("__tcc_builtin_popcountll")));
|
||||||
|
int __builtin_parity(unsigned int x) __attribute__((alias("__tcc_builtin_parity")));
|
||||||
|
int __builtin_parityl(unsigned long x) __attribute__((alias("__tcc_builtin_parityl")));
|
||||||
|
int __builtin_parityll(unsigned long long x) __attribute__((alias("__tcc_builtin_parityll")));
|
||||||
|
#endif
|
||||||
1
lib/dsohandle.c
Normal file
1
lib/dsohandle.c
Normal file
@ -0,0 +1 @@
|
|||||||
|
void * __dso_handle __attribute((visibility("hidden"))) = &__dso_handle;
|
||||||
224
lib/lib-arm64.c
224
lib/lib-arm64.c
@ -18,40 +18,40 @@ typedef int int32_t;
|
|||||||
typedef unsigned uint32_t;
|
typedef unsigned uint32_t;
|
||||||
typedef long long int64_t;
|
typedef long long int64_t;
|
||||||
typedef unsigned long long uint64_t;
|
typedef unsigned long long uint64_t;
|
||||||
void *memcpy(void*,void*,__SIZE_TYPE__);
|
|
||||||
#else
|
#else
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void __clear_cache(void *beg, void *end)
|
typedef union {
|
||||||
{
|
struct { uint64_t x0, x1; };
|
||||||
__arm64_clear_cache(beg, end);
|
long double f;
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint64_t x0, x1;
|
|
||||||
} u128_t;
|
} u128_t;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
uint64_t x;
|
||||||
|
double f;
|
||||||
|
} u64_t;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
uint32_t x;
|
||||||
|
float f;
|
||||||
|
} u32_t;
|
||||||
|
|
||||||
static long double f3_zero(int sgn)
|
static long double f3_zero(int sgn)
|
||||||
{
|
{
|
||||||
long double f;
|
|
||||||
u128_t x = { 0, (uint64_t)sgn << 63 };
|
u128_t x = { 0, (uint64_t)sgn << 63 };
|
||||||
memcpy(&f, &x, 16);
|
return x.f;
|
||||||
return f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static long double f3_infinity(int sgn)
|
static long double f3_infinity(int sgn)
|
||||||
{
|
{
|
||||||
long double f;
|
|
||||||
u128_t x = { 0, (uint64_t)sgn << 63 | 0x7fff000000000000 };
|
u128_t x = { 0, (uint64_t)sgn << 63 | 0x7fff000000000000 };
|
||||||
memcpy(&f, &x, 16);
|
return x.f;
|
||||||
return f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static long double f3_NaN(void)
|
static long double f3_NaN(void)
|
||||||
{
|
{
|
||||||
long double f;
|
|
||||||
#if 0
|
#if 0
|
||||||
// ARM's default NaN usually has just the top fraction bit set:
|
// ARM's default NaN usually has just the top fraction bit set:
|
||||||
u128_t x = { 0, 0x7fff800000000000 };
|
u128_t x = { 0, 0x7fff800000000000 };
|
||||||
@ -59,28 +59,31 @@ static long double f3_NaN(void)
|
|||||||
// GCC's library sets all fraction bits:
|
// GCC's library sets all fraction bits:
|
||||||
u128_t x = { -1, 0x7fffffffffffffff };
|
u128_t x = { -1, 0x7fffffffffffffff };
|
||||||
#endif
|
#endif
|
||||||
memcpy(&f, &x, 16);
|
return x.f;
|
||||||
return f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fp3_convert_NaN(long double *f, int sgn, u128_t mnt)
|
static int fp3_convert_NaN(long double *f, int sgn, u128_t *mnt)
|
||||||
{
|
{
|
||||||
u128_t x = { mnt.x0,
|
u128_t x = { mnt->x0,
|
||||||
mnt.x1 | 0x7fff800000000000 | (uint64_t)sgn << 63 };
|
mnt->x1 | 0x7fff800000000000 | (uint64_t)sgn << 63 };
|
||||||
memcpy(f, &x, 16);
|
*f = x.f;
|
||||||
return 1;
|
return 1;
|
||||||
|
#define fp3_convert_NaN(a,b,c) fp3_convert_NaN(a,b,&c)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fp3_detect_NaNs(long double *f,
|
static int fp3_detect_NaNs(long double *f,
|
||||||
int a_sgn, int a_exp, u128_t a,
|
int a_sgn, int a_exp, u128_t *a,
|
||||||
int b_sgn, int b_exp, u128_t b)
|
int b_sgn, int b_exp, u128_t *b)
|
||||||
|
#define a (*a)
|
||||||
|
#define b (*b)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
// Detect signalling NaNs:
|
// Detect signalling NaNs:
|
||||||
if (a_exp == 32767 && (a.x0 | a.x1 << 16) && !(a.x1 >> 47 & 1))
|
if (a_exp == 32767 && (a.x0 | a.x1 << 16) && !(a.x1 >> 47 & 1))
|
||||||
return fp3_convert_NaN(f, a_sgn, a);
|
return fp3_convert_NaN(f, a_sgn, a);
|
||||||
if (b_exp == 32767 && (b.x0 | b.x1 << 16) && !(b.x1 >> 47 & 1))
|
if (b_exp == 32767 && (b.x0 | b.x1 << 16) && !(b.x1 >> 47 & 1))
|
||||||
return fp3_convert_NaN(f, b_sgn, b);
|
return fp3_convert_NaN(f, b_sgn, b);
|
||||||
|
#endif
|
||||||
// Detect quiet NaNs:
|
// Detect quiet NaNs:
|
||||||
if (a_exp == 32767 && (a.x0 | a.x1 << 16))
|
if (a_exp == 32767 && (a.x0 | a.x1 << 16))
|
||||||
return fp3_convert_NaN(f, a_sgn, a);
|
return fp3_convert_NaN(f, a_sgn, a);
|
||||||
@ -88,12 +91,16 @@ static int fp3_detect_NaNs(long double *f,
|
|||||||
return fp3_convert_NaN(f, b_sgn, b);
|
return fp3_convert_NaN(f, b_sgn, b);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
#undef a
|
||||||
|
#undef b
|
||||||
|
#define fp3_detect_NaNs(a,b,c,d,e,f,g) fp3_detect_NaNs(a,b,c,&d,e,f,&g)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void f3_unpack(int *sgn, int32_t *exp, u128_t *mnt, long double f)
|
static void f3_unpack(int *sgn, int32_t *exp, u128_t *mnt, long double f)
|
||||||
{
|
{
|
||||||
u128_t x;
|
u128_t x;
|
||||||
memcpy(&x, &f, 16);
|
|
||||||
|
x.f = f;
|
||||||
*sgn = x.x1 >> 63;
|
*sgn = x.x1 >> 63;
|
||||||
*exp = x.x1 >> 48 & 32767;
|
*exp = x.x1 >> 48 & 32767;
|
||||||
x.x1 = x.x1 << 16 >> 16;
|
x.x1 = x.x1 << 16 >> 16;
|
||||||
@ -101,74 +108,72 @@ static void f3_unpack(int *sgn, int32_t *exp, u128_t *mnt, long double f)
|
|||||||
x.x1 |= (uint64_t)1 << 48;
|
x.x1 |= (uint64_t)1 << 48;
|
||||||
else
|
else
|
||||||
*exp = 1;
|
*exp = 1;
|
||||||
*mnt = x;
|
mnt->f = x.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u128_t f3_normalise(int32_t *exp, u128_t mnt)
|
static void f3_normalise(int32_t *exp, u128_t *mnt)
|
||||||
{
|
{
|
||||||
int sh;
|
int sh;
|
||||||
if (!(mnt.x0 | mnt.x1))
|
if (!(mnt->x0 | mnt->x1))
|
||||||
return mnt;
|
return;
|
||||||
if (!mnt.x1) {
|
if (!mnt->x1) {
|
||||||
mnt.x1 = mnt.x0;
|
mnt->x1 = mnt->x0;
|
||||||
mnt.x0 = 0;
|
mnt->x0 = 0;
|
||||||
*exp -= 64;
|
*exp -= 64;
|
||||||
}
|
}
|
||||||
for (sh = 32; sh; sh >>= 1) {
|
for (sh = 32; sh; sh >>= 1) {
|
||||||
if (!(mnt.x1 >> (64 - sh))) {
|
if (!(mnt->x1 >> (64 - sh))) {
|
||||||
mnt.x1 = mnt.x1 << sh | mnt.x0 >> (64 - sh);
|
mnt->x1 = mnt->x1 << sh | mnt->x0 >> (64 - sh);
|
||||||
mnt.x0 = mnt.x0 << sh;
|
mnt->x0 = mnt->x0 << sh;
|
||||||
*exp -= sh;
|
*exp -= sh;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return mnt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static u128_t f3_sticky_shift(int32_t sh, u128_t x)
|
static void f3_sticky_shift(int32_t sh, u128_t *x)
|
||||||
{
|
{
|
||||||
if (sh >= 128) {
|
if (sh >= 128) {
|
||||||
x.x0 = !!(x.x0 | x.x1);
|
x->x0 = !!(x->x0 | x->x1);
|
||||||
x.x1 = 0;
|
x->x1 = 0;
|
||||||
return x;
|
return;
|
||||||
}
|
}
|
||||||
if (sh >= 64) {
|
if (sh >= 64) {
|
||||||
x.x0 = x.x1 | !!x.x0;
|
x->x0 = x->x1 | !!x->x0;
|
||||||
x.x1 = 0;
|
x->x1 = 0;
|
||||||
sh -= 64;
|
sh -= 64;
|
||||||
}
|
}
|
||||||
if (sh > 0) {
|
if (sh > 0) {
|
||||||
x.x0 = x.x0 >> sh | x.x1 << (64 - sh) | !!(x.x0 << (64 - sh));
|
x->x0 = x->x0 >> sh | x->x1 << (64 - sh) | !!(x->x0 << (64 - sh));
|
||||||
x.x1 = x.x1 >> sh;
|
x->x1 = x->x1 >> sh;
|
||||||
}
|
}
|
||||||
return x;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static long double f3_round(int sgn, int32_t exp, u128_t x)
|
static long double f3_round(int sgn, int32_t exp, u128_t *x)
|
||||||
{
|
{
|
||||||
long double f;
|
long double f;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if (exp > 0) {
|
if (exp > 0) {
|
||||||
x = f3_sticky_shift(13, x);
|
f3_sticky_shift(13, x);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
x = f3_sticky_shift(14 - exp, x);
|
f3_sticky_shift(14 - exp, x);
|
||||||
exp = 0;
|
exp = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = x.x0 & 3;
|
error = x->x0 & 3;
|
||||||
x.x0 = x.x0 >> 2 | x.x1 << 62;
|
x->x0 = x->x0 >> 2 | x->x1 << 62;
|
||||||
x.x1 = x.x1 >> 2;
|
x->x1 = x->x1 >> 2;
|
||||||
|
|
||||||
if (error == 3 || ((error == 2) & (x.x0 & 1))) {
|
if (error == 3 || ((error == 2) & (x->x0 & 1))) {
|
||||||
if (!++x.x0) {
|
if (!++x->x0) {
|
||||||
++x.x1;
|
++x->x1;
|
||||||
if (x.x1 == (uint64_t)1 << 48)
|
if (x->x1 == (uint64_t)1 << 48)
|
||||||
exp = 1;
|
exp = 1;
|
||||||
else if (x.x1 == (uint64_t)1 << 49) {
|
else if (x->x1 == (uint64_t)1 << 49) {
|
||||||
++exp;
|
++exp;
|
||||||
x.x0 = x.x0 >> 1 | x.x1 << 63;
|
x->x0 = x->x0 >> 1 | x->x1 << 63;
|
||||||
x.x1 = x.x1 >> 1;
|
x->x1 = x->x1 >> 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -176,9 +181,8 @@ static long double f3_round(int sgn, int32_t exp, u128_t x)
|
|||||||
if (exp >= 32767)
|
if (exp >= 32767)
|
||||||
return f3_infinity(sgn);
|
return f3_infinity(sgn);
|
||||||
|
|
||||||
x.x1 = x.x1 << 16 >> 16 | (uint64_t)exp << 48 | (uint64_t)sgn << 63;
|
x->x1 = x->x1 << 16 >> 16 | (uint64_t)exp << 48 | (uint64_t)sgn << 63;
|
||||||
memcpy(&f, &x, 16);
|
return x->f;
|
||||||
return f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static long double f3_add(long double fa, long double fb, int neg)
|
static long double f3_add(long double fa, long double fb, int neg)
|
||||||
@ -212,11 +216,11 @@ static long double f3_add(long double fa, long double fb, int neg)
|
|||||||
b.x0 = b.x0 << 3;
|
b.x0 = b.x0 << 3;
|
||||||
|
|
||||||
if (a_exp <= b_exp) {
|
if (a_exp <= b_exp) {
|
||||||
a = f3_sticky_shift(b_exp - a_exp, a);
|
f3_sticky_shift(b_exp - a_exp, &a);
|
||||||
a_exp = b_exp;
|
a_exp = b_exp;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
b = f3_sticky_shift(a_exp - b_exp, b);
|
f3_sticky_shift(a_exp - b_exp, &b);
|
||||||
b_exp = a_exp;
|
b_exp = a_exp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,9 +243,9 @@ static long double f3_add(long double fa, long double fb, int neg)
|
|||||||
if (!(x.x0 | x.x1))
|
if (!(x.x0 | x.x1))
|
||||||
return f3_zero(0);
|
return f3_zero(0);
|
||||||
|
|
||||||
x = f3_normalise(&x_exp, x);
|
f3_normalise(&x_exp, &x);
|
||||||
|
|
||||||
return f3_round(x_sgn, x_exp + 12, x);
|
return f3_round(x_sgn, x_exp + 12, &x);
|
||||||
}
|
}
|
||||||
|
|
||||||
long double __addtf3(long double a, long double b)
|
long double __addtf3(long double a, long double b)
|
||||||
@ -276,8 +280,8 @@ long double __multf3(long double fa, long double fb)
|
|||||||
if (!(a.x0 | a.x1) || !(b.x0 | b.x1))
|
if (!(a.x0 | a.x1) || !(b.x0 | b.x1))
|
||||||
return f3_zero(a_sgn ^ b_sgn);
|
return f3_zero(a_sgn ^ b_sgn);
|
||||||
|
|
||||||
a = f3_normalise(&a_exp, a);
|
f3_normalise(&a_exp, &a);
|
||||||
b = f3_normalise(&b_exp, b);
|
f3_normalise(&b_exp, &b);
|
||||||
|
|
||||||
x_sgn = a_sgn ^ b_sgn;
|
x_sgn = a_sgn ^ b_sgn;
|
||||||
x_exp = a_exp + b_exp - 16352;
|
x_exp = a_exp + b_exp - 16352;
|
||||||
@ -316,7 +320,7 @@ long double __multf3(long double fa, long double fb)
|
|||||||
x.x1 = y1;
|
x.x1 = y1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return f3_round(x_sgn, x_exp, x);
|
return f3_round(x_sgn, x_exp, &x);
|
||||||
}
|
}
|
||||||
|
|
||||||
long double __divtf3(long double fa, long double fb)
|
long double __divtf3(long double fa, long double fb)
|
||||||
@ -341,8 +345,8 @@ long double __divtf3(long double fa, long double fb)
|
|||||||
if (!(a.x0 | a.x1) || b_exp == 32767)
|
if (!(a.x0 | a.x1) || b_exp == 32767)
|
||||||
return f3_zero(a_sgn ^ b_sgn);
|
return f3_zero(a_sgn ^ b_sgn);
|
||||||
|
|
||||||
a = f3_normalise(&a_exp, a);
|
f3_normalise(&a_exp, &a);
|
||||||
b = f3_normalise(&b_exp, b);
|
f3_normalise(&b_exp, &b);
|
||||||
|
|
||||||
x_sgn = a_sgn ^ b_sgn;
|
x_sgn = a_sgn ^ b_sgn;
|
||||||
x_exp = a_exp - b_exp + 16395;
|
x_exp = a_exp - b_exp + 16395;
|
||||||
@ -366,48 +370,67 @@ long double __divtf3(long double fa, long double fb)
|
|||||||
}
|
}
|
||||||
x.x0 |= !!(a.x0 | a.x1);
|
x.x0 |= !!(a.x0 | a.x1);
|
||||||
|
|
||||||
x = f3_normalise(&x_exp, x);
|
f3_normalise(&x_exp, &x);
|
||||||
|
|
||||||
return f3_round(x_sgn, x_exp, x);
|
return f3_round(x_sgn, x_exp, &x);
|
||||||
|
}
|
||||||
|
|
||||||
|
long double __negtf2(long double f)
|
||||||
|
{
|
||||||
|
((u128_t*)&f)->x1 ^= 1UL << 63;
|
||||||
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
long double __extendsftf2(float f)
|
long double __extendsftf2(float f)
|
||||||
{
|
{
|
||||||
long double fx;
|
|
||||||
u128_t x;
|
u128_t x;
|
||||||
|
u32_t u;
|
||||||
uint32_t a;
|
uint32_t a;
|
||||||
uint64_t aa;
|
uint64_t aa;
|
||||||
memcpy(&a, &f, 4);
|
|
||||||
|
u.f = f, a = u.x;
|
||||||
aa = a;
|
aa = a;
|
||||||
|
|
||||||
x.x0 = 0;
|
x.x0 = 0;
|
||||||
if (!(a << 1))
|
if (!(a << 1))
|
||||||
x.x1 = aa << 32;
|
x.x1 = aa << 32;
|
||||||
else if (a << 1 >> 24 == 255)
|
else if (a << 1 >> 24 == 255)
|
||||||
x.x1 = (0x7fff000000000000 | aa >> 31 << 63 | aa << 41 >> 16 |
|
x.x1 = (0x7fff000000000000 | aa >> 31 << 63 | aa << 41 >> 16 |
|
||||||
(uint64_t)!!(a << 9) << 47);
|
(uint64_t)!!(a << 9) << 47);
|
||||||
else
|
else if (a << 1 >> 24 == 0) {
|
||||||
|
uint64_t adj = 0;
|
||||||
|
while (!(a << 1 >> 1 >> (23 - adj)))
|
||||||
|
adj++;
|
||||||
|
x.x1 = aa >> 31 << 63 | (16256 - adj + 1) << 48 | aa << adj << 41 >> 16;
|
||||||
|
} else
|
||||||
x.x1 = (aa >> 31 << 63 | ((aa >> 23 & 255) + 16256) << 48 |
|
x.x1 = (aa >> 31 << 63 | ((aa >> 23 & 255) + 16256) << 48 |
|
||||||
aa << 41 >> 16);
|
aa << 41 >> 16);
|
||||||
memcpy(&fx, &x, 16);
|
return x.f;
|
||||||
return fx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long double __extenddftf2(double f)
|
long double __extenddftf2(double f)
|
||||||
{
|
{
|
||||||
long double fx;
|
|
||||||
u128_t x;
|
u128_t x;
|
||||||
|
u64_t u;
|
||||||
uint64_t a;
|
uint64_t a;
|
||||||
memcpy(&a, &f, 8);
|
|
||||||
|
u.f = f, a = u.x;
|
||||||
|
|
||||||
x.x0 = a << 60;
|
x.x0 = a << 60;
|
||||||
if (!(a << 1))
|
if (!(a << 1))
|
||||||
x.x1 = a;
|
x.x1 = a;
|
||||||
else if (a << 1 >> 53 == 2047)
|
else if (a << 1 >> 53 == 2047)
|
||||||
x.x1 = (0x7fff000000000000 | a >> 63 << 63 | a << 12 >> 16 |
|
x.x1 = (0x7fff000000000000 | a >> 63 << 63 | a << 12 >> 16 |
|
||||||
(uint64_t)!!(a << 12) << 47);
|
(uint64_t)!!(a << 12) << 47);
|
||||||
else
|
else if (a << 1 >> 53 == 0) {
|
||||||
|
uint64_t adj = 0;
|
||||||
|
while (!(a << 1 >> 1 >> (52 - adj)))
|
||||||
|
adj++;
|
||||||
|
x.x0 <<= adj;
|
||||||
|
x.x1 = a >> 63 << 63 | (15360 - adj + 1) << 48 | a << adj << 12 >> 16;
|
||||||
|
} else
|
||||||
x.x1 = a >> 63 << 63 | ((a >> 52 & 2047) + 15360) << 48 | a << 12 >> 16;
|
x.x1 = a >> 63 << 63 | ((a >> 52 & 2047) + 15360) << 48 | a << 12 >> 16;
|
||||||
memcpy(&fx, &x, 16);
|
return x.f;
|
||||||
return fx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float __trunctfsf2(long double f)
|
float __trunctfsf2(long double f)
|
||||||
@ -415,11 +438,10 @@ float __trunctfsf2(long double f)
|
|||||||
u128_t mnt;
|
u128_t mnt;
|
||||||
int32_t exp;
|
int32_t exp;
|
||||||
int sgn;
|
int sgn;
|
||||||
uint32_t x;
|
u32_t x;
|
||||||
float fx;
|
#define x x.x
|
||||||
|
|
||||||
f3_unpack(&sgn, &exp, &mnt, f);
|
f3_unpack(&sgn, &exp, &mnt, f);
|
||||||
|
|
||||||
if (exp == 32767 && (mnt.x0 | mnt.x1 << 16))
|
if (exp == 32767 && (mnt.x0 | mnt.x1 << 16))
|
||||||
x = 0x7fc00000 | (uint32_t)sgn << 31 | (mnt.x1 >> 25 & 0x007fffff);
|
x = 0x7fc00000 | (uint32_t)sgn << 31 | (mnt.x1 >> 25 & 0x007fffff);
|
||||||
else if (exp > 16510)
|
else if (exp > 16510)
|
||||||
@ -437,8 +459,8 @@ float __trunctfsf2(long double f)
|
|||||||
x += 4;
|
x += 4;
|
||||||
x = ((x >> 2) + (exp << 23)) | (uint32_t)sgn << 31;
|
x = ((x >> 2) + (exp << 23)) | (uint32_t)sgn << 31;
|
||||||
}
|
}
|
||||||
memcpy(&fx, &x, 4);
|
#undef x
|
||||||
return fx;
|
return x.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
double __trunctfdf2(long double f)
|
double __trunctfdf2(long double f)
|
||||||
@ -446,11 +468,10 @@ double __trunctfdf2(long double f)
|
|||||||
u128_t mnt;
|
u128_t mnt;
|
||||||
int32_t exp;
|
int32_t exp;
|
||||||
int sgn;
|
int sgn;
|
||||||
uint64_t x;
|
u64_t x;
|
||||||
double fx;
|
#define x x.x
|
||||||
|
|
||||||
f3_unpack(&sgn, &exp, &mnt, f);
|
f3_unpack(&sgn, &exp, &mnt, f);
|
||||||
|
|
||||||
if (exp == 32767 && (mnt.x0 | mnt.x1 << 16))
|
if (exp == 32767 && (mnt.x0 | mnt.x1 << 16))
|
||||||
x = (0x7ff8000000000000 | (uint64_t)sgn << 63 |
|
x = (0x7ff8000000000000 | (uint64_t)sgn << 63 |
|
||||||
mnt.x1 << 16 >> 12 | mnt.x0 >> 60);
|
mnt.x1 << 16 >> 12 | mnt.x0 >> 60);
|
||||||
@ -469,8 +490,8 @@ double __trunctfdf2(long double f)
|
|||||||
x += 4;
|
x += 4;
|
||||||
x = ((x >> 2) + ((uint64_t)exp << 52)) | (uint64_t)sgn << 63;
|
x = ((x >> 2) + ((uint64_t)exp << 52)) | (uint64_t)sgn << 63;
|
||||||
}
|
}
|
||||||
memcpy(&fx, &x, 8);
|
#undef x
|
||||||
return fx;
|
return x.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t __fixtfsi(long double fa)
|
int32_t __fixtfsi(long double fa)
|
||||||
@ -535,7 +556,6 @@ long double __floatsitf(int32_t a)
|
|||||||
int exp = 16414;
|
int exp = 16414;
|
||||||
uint32_t mnt = a;
|
uint32_t mnt = a;
|
||||||
u128_t x = { 0, 0 };
|
u128_t x = { 0, 0 };
|
||||||
long double f;
|
|
||||||
int i;
|
int i;
|
||||||
if (a) {
|
if (a) {
|
||||||
if (a < 0) {
|
if (a < 0) {
|
||||||
@ -550,8 +570,7 @@ long double __floatsitf(int32_t a)
|
|||||||
x.x1 = ((uint64_t)sgn << 63 | (uint64_t)exp << 48 |
|
x.x1 = ((uint64_t)sgn << 63 | (uint64_t)exp << 48 |
|
||||||
(uint64_t)(mnt << 1) << 16);
|
(uint64_t)(mnt << 1) << 16);
|
||||||
}
|
}
|
||||||
memcpy(&f, &x, 16);
|
return x.f;
|
||||||
return f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long double __floatditf(int64_t a)
|
long double __floatditf(int64_t a)
|
||||||
@ -560,7 +579,6 @@ long double __floatditf(int64_t a)
|
|||||||
int exp = 16446;
|
int exp = 16446;
|
||||||
uint64_t mnt = a;
|
uint64_t mnt = a;
|
||||||
u128_t x = { 0, 0 };
|
u128_t x = { 0, 0 };
|
||||||
long double f;
|
|
||||||
int i;
|
int i;
|
||||||
if (a) {
|
if (a) {
|
||||||
if (a < 0) {
|
if (a < 0) {
|
||||||
@ -575,8 +593,7 @@ long double __floatditf(int64_t a)
|
|||||||
x.x0 = mnt << 49;
|
x.x0 = mnt << 49;
|
||||||
x.x1 = (uint64_t)sgn << 63 | (uint64_t)exp << 48 | mnt << 1 >> 16;
|
x.x1 = (uint64_t)sgn << 63 | (uint64_t)exp << 48 | mnt << 1 >> 16;
|
||||||
}
|
}
|
||||||
memcpy(&f, &x, 16);
|
return x.f;
|
||||||
return f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long double __floatunsitf(uint32_t a)
|
long double __floatunsitf(uint32_t a)
|
||||||
@ -584,7 +601,6 @@ long double __floatunsitf(uint32_t a)
|
|||||||
int exp = 16414;
|
int exp = 16414;
|
||||||
uint32_t mnt = a;
|
uint32_t mnt = a;
|
||||||
u128_t x = { 0, 0 };
|
u128_t x = { 0, 0 };
|
||||||
long double f;
|
|
||||||
int i;
|
int i;
|
||||||
if (a) {
|
if (a) {
|
||||||
for (i = 16; i; i >>= 1)
|
for (i = 16; i; i >>= 1)
|
||||||
@ -594,8 +610,7 @@ long double __floatunsitf(uint32_t a)
|
|||||||
}
|
}
|
||||||
x.x1 = (uint64_t)exp << 48 | (uint64_t)(mnt << 1) << 16;
|
x.x1 = (uint64_t)exp << 48 | (uint64_t)(mnt << 1) << 16;
|
||||||
}
|
}
|
||||||
memcpy(&f, &x, 16);
|
return x.f;
|
||||||
return f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long double __floatunditf(uint64_t a)
|
long double __floatunditf(uint64_t a)
|
||||||
@ -614,15 +629,14 @@ long double __floatunditf(uint64_t a)
|
|||||||
x.x0 = mnt << 49;
|
x.x0 = mnt << 49;
|
||||||
x.x1 = (uint64_t)exp << 48 | mnt << 1 >> 16;
|
x.x1 = (uint64_t)exp << 48 | mnt << 1 >> 16;
|
||||||
}
|
}
|
||||||
memcpy(&f, &x, 16);
|
return x.f;
|
||||||
return f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int f3_cmp(long double fa, long double fb)
|
static int f3_cmp(long double fa, long double fb)
|
||||||
{
|
{
|
||||||
u128_t a, b;
|
u128_t a, b;
|
||||||
memcpy(&a, &fa, 16);
|
a.f = fa;
|
||||||
memcpy(&b, &fb, 16);
|
b.f = fb;
|
||||||
return (!(a.x0 | a.x1 << 1 | b.x0 | b.x1 << 1) ? 0 :
|
return (!(a.x0 | a.x1 << 1 | b.x0 | b.x1 << 1) ? 0 :
|
||||||
((a.x1 << 1 >> 49 == 0x7fff && (a.x0 | a.x1 << 16)) ||
|
((a.x1 << 1 >> 49 == 0x7fff && (a.x0 | a.x1 << 16)) ||
|
||||||
(b.x1 << 1 >> 49 == 0x7fff && (b.x0 | b.x1 << 16))) ? 2 :
|
(b.x1 << 1 >> 49 == 0x7fff && (b.x0 | b.x1 << 16))) ? 2 :
|
||||||
|
|||||||
20
lib/lib-riscv.c
Normal file
20
lib/lib-riscv.c
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* TCC runtime library for riscv64.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026
|
||||||
|
*
|
||||||
|
* Copying and distribution of this file, with or without modification,
|
||||||
|
* are permitted in any medium without royalty provided the copyright
|
||||||
|
* notice and this notice are preserved. This file is offered as-is,
|
||||||
|
* without any warranty.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------- */
|
||||||
|
/* __clear_cache is used in tccrun.c. It is a built-in
|
||||||
|
intrinsic with gcc. However tcc in order to compile
|
||||||
|
itself needs this function */
|
||||||
|
|
||||||
|
void __clear_cache(void *beg, void *end)
|
||||||
|
{
|
||||||
|
__riscv64_clear_cache(beg, end);
|
||||||
|
}
|
||||||
@ -107,10 +107,9 @@ union float_long {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* XXX: we don't support several builtin supports for now */
|
/* XXX: we don't support several builtin supports for now */
|
||||||
#if !defined __x86_64__ && !defined __arm__
|
#if defined __i386__
|
||||||
|
|
||||||
/* XXX: use gcc/tcc intrinsic ? */
|
/* XXX: use gcc/tcc intrinsic ? */
|
||||||
#if defined __i386__
|
|
||||||
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
|
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
|
||||||
__asm__ ("subl %5,%1\n\tsbbl %3,%0" \
|
__asm__ ("subl %5,%1\n\tsbbl %3,%0" \
|
||||||
: "=r" ((USItype) (sh)), \
|
: "=r" ((USItype) (sh)), \
|
||||||
@ -139,9 +138,6 @@ union float_long {
|
|||||||
: "=r" (__cbtmp) : "rm" ((USItype) (x))); \
|
: "=r" (__cbtmp) : "rm" ((USItype) (x))); \
|
||||||
(count) = __cbtmp ^ 31; \
|
(count) = __cbtmp ^ 31; \
|
||||||
} while (0)
|
} while (0)
|
||||||
#else
|
|
||||||
#error unsupported CPU type
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* most of this code is taken from libgcc2.c from gcc */
|
/* most of this code is taken from libgcc2.c from gcc */
|
||||||
|
|
||||||
@ -478,7 +474,7 @@ long long __ashldi3(long long a, int b)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !__x86_64__ */
|
#endif /* __i386__ */
|
||||||
|
|
||||||
/* XXX: fix tcc's code generator to do this instead */
|
/* XXX: fix tcc's code generator to do this instead */
|
||||||
float __floatundisf(unsigned long long a)
|
float __floatundisf(unsigned long long a)
|
||||||
@ -530,7 +526,7 @@ unsigned long long __fixunssfdi (float a1)
|
|||||||
{
|
{
|
||||||
register union float_long fl1;
|
register union float_long fl1;
|
||||||
register int exp;
|
register int exp;
|
||||||
register unsigned long l;
|
register unsigned long long l;
|
||||||
|
|
||||||
fl1.f = a1;
|
fl1.f = a1;
|
||||||
|
|
||||||
@ -538,16 +534,19 @@ unsigned long long __fixunssfdi (float a1)
|
|||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
exp = EXP (fl1.l) - EXCESS - 24;
|
exp = EXP (fl1.l) - EXCESS - 24;
|
||||||
|
|
||||||
l = MANT(fl1.l);
|
l = MANT(fl1.l);
|
||||||
|
|
||||||
if (exp >= 41)
|
if (exp >= 41)
|
||||||
return (unsigned long long)-1;
|
return 1ULL << 63;
|
||||||
else if (exp >= 0)
|
else if (exp >= 0)
|
||||||
return (unsigned long long)l << exp;
|
l <<= exp;
|
||||||
else if (exp >= -23)
|
else if (exp >= -23)
|
||||||
return l >> -exp;
|
l >>= -exp;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
|
if (SIGN(fl1.l))
|
||||||
|
l = (unsigned long long)-l;
|
||||||
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
long long __fixsfdi (float a1)
|
long long __fixsfdi (float a1)
|
||||||
@ -569,17 +568,19 @@ unsigned long long __fixunsdfdi (double a1)
|
|||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
exp = EXPD (dl1) - EXCESSD - 53;
|
exp = EXPD (dl1) - EXCESSD - 53;
|
||||||
|
|
||||||
l = MANTD_LL(dl1);
|
l = MANTD_LL(dl1);
|
||||||
|
|
||||||
if (exp >= 12)
|
if (exp >= 12)
|
||||||
return (unsigned long long)-1;
|
return 1ULL << 63; /* overflow result (like gcc, somewhat) */
|
||||||
else if (exp >= 0)
|
else if (exp >= 0)
|
||||||
return l << exp;
|
l <<= exp;
|
||||||
else if (exp >= -52)
|
else if (exp >= -52)
|
||||||
return l >> -exp;
|
l >>= -exp;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
|
if (SIGND(dl1))
|
||||||
|
l = (unsigned long long)-l;
|
||||||
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
long long __fixdfdi (double a1)
|
long long __fixdfdi (double a1)
|
||||||
@ -602,15 +603,15 @@ unsigned long long __fixunsxfdi (long double a1)
|
|||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
exp = EXPLD (dl1) - EXCESSLD - 64;
|
exp = EXPLD (dl1) - EXCESSLD - 64;
|
||||||
|
|
||||||
l = dl1.l.lower;
|
l = dl1.l.lower;
|
||||||
|
|
||||||
if (exp > 0)
|
if (exp > 0)
|
||||||
return (unsigned long long)-1;
|
return 1ULL << 63;
|
||||||
else if (exp >= -63)
|
if (exp < -63)
|
||||||
return l >> -exp;
|
|
||||||
else
|
|
||||||
return 0;
|
return 0;
|
||||||
|
l >>= -exp;
|
||||||
|
if (SIGNLD(dl1))
|
||||||
|
l = (unsigned long long)-l;
|
||||||
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
long long __fixxfdi (long double a1)
|
long long __fixxfdi (long double a1)
|
||||||
|
|||||||
39
lib/pic86.S
Normal file
39
lib/pic86.S
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/* ---------------------------------------------- */
|
||||||
|
/* get_pc_thunk.S */
|
||||||
|
|
||||||
|
#ifdef __leading_underscore
|
||||||
|
# define _(s) _##s
|
||||||
|
#else
|
||||||
|
# define _(s) s
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ---------------------------------------------- */
|
||||||
|
.text
|
||||||
|
|
||||||
|
.globl _(__x86.get_pc_thunk.ax)
|
||||||
|
.hidden _(__x86.get_pc_thunk.ax)
|
||||||
|
_(__x86.get_pc_thunk.ax):
|
||||||
|
mov (%esp),%eax
|
||||||
|
ret
|
||||||
|
.size _(__x86.get_pc_thunk.ax), .-_(__x86.get_pc_thunk.ax)
|
||||||
|
|
||||||
|
.globl _(__x86.get_pc_thunk.bx)
|
||||||
|
.hidden _(__x86.get_pc_thunk.bx)
|
||||||
|
_(__x86.get_pc_thunk.bx):
|
||||||
|
mov (%esp),%ebx
|
||||||
|
ret
|
||||||
|
.size _(__x86.get_pc_thunk.bx), .-_(__x86.get_pc_thunk.bx)
|
||||||
|
|
||||||
|
.globl _(__x86.get_pc_thunk.cx)
|
||||||
|
.hidden _(__x86.get_pc_thunk.cx)
|
||||||
|
_(__x86.get_pc_thunk.cx):
|
||||||
|
mov (%esp),%ecx
|
||||||
|
ret
|
||||||
|
.size _(__x86.get_pc_thunk.cx), .-_(__x86.get_pc_thunk.cx)
|
||||||
|
|
||||||
|
.globl _(__x86.get_pc_thunk.dx)
|
||||||
|
.hidden _(__x86.get_pc_thunk.dx)
|
||||||
|
_(__x86.get_pc_thunk.dx):
|
||||||
|
mov (%esp),%edx
|
||||||
|
ret
|
||||||
|
.size _(__x86.get_pc_thunk.dx), .-_(__x86.get_pc_thunk.dx)
|
||||||
86
lib/runmain.c
Normal file
86
lib/runmain.c
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/* ------------------------------------------------------------- */
|
||||||
|
/* support for tcc_run() */
|
||||||
|
|
||||||
|
#ifdef __leading_underscore
|
||||||
|
# define _(s) s
|
||||||
|
#else
|
||||||
|
# define _(s) _##s
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
extern void (*_(_init_array_start)[]) (int argc, char **argv, char **envp);
|
||||||
|
extern void (*_(_init_array_end)[]) (int argc, char **argv, char **envp);
|
||||||
|
static void run_ctors(int argc, char **argv, char **env)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while (&_(_init_array_start)[i] != _(_init_array_end))
|
||||||
|
(*_(_init_array_start)[i++])(argc, argv, env);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern void (*_(_fini_array_start)[]) (void);
|
||||||
|
extern void (*_(_fini_array_end)[]) (void);
|
||||||
|
static void run_dtors(void)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while (&_(_fini_array_end)[i] != _(_fini_array_start))
|
||||||
|
(*_(_fini_array_end)[--i])();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *rt_exitfunc[32];
|
||||||
|
static void *rt_exitarg[32];
|
||||||
|
static int __rt_nr_exit;
|
||||||
|
|
||||||
|
void __run_on_exit(int ret)
|
||||||
|
{
|
||||||
|
int n = __rt_nr_exit;
|
||||||
|
while (n)
|
||||||
|
--n, ((void(*)(int,void*))rt_exitfunc[n])(ret, rt_exitarg[n]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int on_exit(void *function, void *arg)
|
||||||
|
{
|
||||||
|
int n = __rt_nr_exit;
|
||||||
|
if (n < 32) {
|
||||||
|
rt_exitfunc[n] = function;
|
||||||
|
rt_exitarg[n] = arg;
|
||||||
|
__rt_nr_exit = n + 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int atexit(void (*function)(void))
|
||||||
|
{
|
||||||
|
return on_exit(function, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct rt_frame {
|
||||||
|
void *ip, *fp, *sp;
|
||||||
|
} rt_frame;
|
||||||
|
|
||||||
|
__attribute__((noreturn)) void __rt_exit(rt_frame *, int);
|
||||||
|
|
||||||
|
void exit(int code)
|
||||||
|
{
|
||||||
|
rt_frame f;
|
||||||
|
run_dtors();
|
||||||
|
__run_on_exit(code);
|
||||||
|
f.fp = 0;
|
||||||
|
f.ip = exit;
|
||||||
|
__rt_exit(&f, code);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
int main(int, char**, char**);
|
||||||
|
|
||||||
|
int _runmain(int argc, char **argv, char **envp)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
run_ctors(argc, argv, envp);
|
||||||
|
ret = main(argc, argv, envp);
|
||||||
|
run_dtors();
|
||||||
|
__run_on_exit(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
104
lib/stdatomic.c
Normal file
104
lib/stdatomic.c
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
// for libtcc1, avoid including files that are not part of tcc
|
||||||
|
// #include <stdint.h>
|
||||||
|
#define uint8_t unsigned char
|
||||||
|
#define uint16_t unsigned short
|
||||||
|
#define uint32_t unsigned int
|
||||||
|
#define uint64_t unsigned long long
|
||||||
|
#define bool _Bool
|
||||||
|
#define false 0
|
||||||
|
#define true 1
|
||||||
|
#define __ATOMIC_RELAXED 0
|
||||||
|
#define __ATOMIC_CONSUME 1
|
||||||
|
#define __ATOMIC_ACQUIRE 2
|
||||||
|
#define __ATOMIC_RELEASE 3
|
||||||
|
#define __ATOMIC_ACQ_REL 4
|
||||||
|
#define __ATOMIC_SEQ_CST 5
|
||||||
|
typedef __SIZE_TYPE__ size_t;
|
||||||
|
|
||||||
|
#define ATOMIC_GEN_OP(TYPE, MODE, NAME, OP, RET) \
|
||||||
|
TYPE __atomic_##NAME##_##MODE(volatile void *atom, TYPE value, int memorder) \
|
||||||
|
{ \
|
||||||
|
TYPE xchg, cmp; \
|
||||||
|
__atomic_load((TYPE *)atom, (TYPE *)&cmp, __ATOMIC_RELAXED); \
|
||||||
|
do { \
|
||||||
|
xchg = (OP); \
|
||||||
|
} while (!__atomic_compare_exchange((TYPE *)atom, &cmp, &xchg, true, \
|
||||||
|
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)); \
|
||||||
|
return RET; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ATOMIC_EXCHANGE(TYPE, MODE) \
|
||||||
|
ATOMIC_GEN_OP(TYPE, MODE, exchange, value, cmp)
|
||||||
|
#define ATOMIC_ADD_FETCH(TYPE, MODE) \
|
||||||
|
ATOMIC_GEN_OP(TYPE, MODE, add_fetch, (cmp + value), xchg)
|
||||||
|
#define ATOMIC_SUB_FETCH(TYPE, MODE) \
|
||||||
|
ATOMIC_GEN_OP(TYPE, MODE, sub_fetch, (cmp - value), xchg)
|
||||||
|
#define ATOMIC_AND_FETCH(TYPE, MODE) \
|
||||||
|
ATOMIC_GEN_OP(TYPE, MODE, and_fetch, (cmp & value), xchg)
|
||||||
|
#define ATOMIC_OR_FETCH(TYPE, MODE) \
|
||||||
|
ATOMIC_GEN_OP(TYPE, MODE, or_fetch, (cmp | value), xchg)
|
||||||
|
#define ATOMIC_XOR_FETCH(TYPE, MODE) \
|
||||||
|
ATOMIC_GEN_OP(TYPE, MODE, xor_fetch, (cmp ^ value), xchg)
|
||||||
|
#define ATOMIC_NAND_FETCH(TYPE, MODE) \
|
||||||
|
ATOMIC_GEN_OP(TYPE, MODE, nand_fetch, ~(cmp & value), xchg)
|
||||||
|
#define ATOMIC_FETCH_ADD(TYPE, MODE) \
|
||||||
|
ATOMIC_GEN_OP(TYPE, MODE, fetch_add, (cmp + value), cmp)
|
||||||
|
#define ATOMIC_FETCH_SUB(TYPE, MODE) \
|
||||||
|
ATOMIC_GEN_OP(TYPE, MODE, fetch_sub, (cmp - value), cmp)
|
||||||
|
#define ATOMIC_FETCH_AND(TYPE, MODE) \
|
||||||
|
ATOMIC_GEN_OP(TYPE, MODE, fetch_and, (cmp & value), cmp)
|
||||||
|
#define ATOMIC_FETCH_OR(TYPE, MODE) \
|
||||||
|
ATOMIC_GEN_OP(TYPE, MODE, fetch_or, (cmp | value), cmp)
|
||||||
|
#define ATOMIC_FETCH_XOR(TYPE, MODE) \
|
||||||
|
ATOMIC_GEN_OP(TYPE, MODE, fetch_xor, (cmp ^ value), cmp)
|
||||||
|
#define ATOMIC_FETCH_NAND(TYPE, MODE) \
|
||||||
|
ATOMIC_GEN_OP(TYPE, MODE, fetch_nand, ~(cmp & value), cmp)
|
||||||
|
|
||||||
|
#define ATOMIC_GEN(TYPE, SIZE) \
|
||||||
|
ATOMIC_EXCHANGE(TYPE, SIZE) \
|
||||||
|
ATOMIC_ADD_FETCH(TYPE, SIZE) \
|
||||||
|
ATOMIC_SUB_FETCH(TYPE, SIZE) \
|
||||||
|
ATOMIC_AND_FETCH(TYPE, SIZE) \
|
||||||
|
ATOMIC_OR_FETCH(TYPE, SIZE) \
|
||||||
|
ATOMIC_XOR_FETCH(TYPE, SIZE) \
|
||||||
|
ATOMIC_NAND_FETCH(TYPE, SIZE) \
|
||||||
|
ATOMIC_FETCH_ADD(TYPE, SIZE) \
|
||||||
|
ATOMIC_FETCH_SUB(TYPE, SIZE) \
|
||||||
|
ATOMIC_FETCH_AND(TYPE, SIZE) \
|
||||||
|
ATOMIC_FETCH_OR(TYPE, SIZE) \
|
||||||
|
ATOMIC_FETCH_XOR(TYPE, SIZE) \
|
||||||
|
ATOMIC_FETCH_NAND(TYPE, SIZE)
|
||||||
|
|
||||||
|
ATOMIC_GEN(uint8_t, 1)
|
||||||
|
ATOMIC_GEN(uint16_t, 2)
|
||||||
|
ATOMIC_GEN(uint32_t, 4)
|
||||||
|
ATOMIC_GEN(uint64_t, 8)
|
||||||
|
|
||||||
|
/* uses alias to allow building with gcc/clang */
|
||||||
|
#ifdef __TINYC__
|
||||||
|
#define ATOMIC(x) __atomic_##x
|
||||||
|
#else
|
||||||
|
#define ATOMIC(x) __tcc_atomic_##x
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool ATOMIC(is_lock_free) (unsigned long size, const volatile void *ptr)
|
||||||
|
{
|
||||||
|
bool ret;
|
||||||
|
|
||||||
|
switch (size) {
|
||||||
|
case 1: ret = true; break;
|
||||||
|
case 2: ret = true; break;
|
||||||
|
case 4: ret = true; break;
|
||||||
|
#if defined __x86_64__ || defined __aarch64__ || defined __riscv
|
||||||
|
case 8: ret = true; break;
|
||||||
|
#else
|
||||||
|
case 8: ret = false; break;
|
||||||
|
#endif
|
||||||
|
default: ret = false; break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef __TINYC__
|
||||||
|
bool __atomic_is_lock_free(unsigned long size, const volatile void *ptr) __attribute__((alias("__tcc_atomic_is_lock_free")));
|
||||||
|
#endif
|
||||||
428
lib/tcov.c
Normal file
428
lib/tcov.c
Normal file
@ -0,0 +1,428 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#else
|
||||||
|
#include <windows.h>
|
||||||
|
#include <io.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* section layout (all little endian):
|
||||||
|
32bit offset to executable/so file name
|
||||||
|
filename \0
|
||||||
|
function name \0
|
||||||
|
align to 64 bits
|
||||||
|
64bit function start line
|
||||||
|
64bits end_line(28bits) / start_line(28bits) / flag=0xff(8bits)
|
||||||
|
64bits counter
|
||||||
|
\0
|
||||||
|
\0
|
||||||
|
\0
|
||||||
|
executable/so file name \0
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct tcov_line {
|
||||||
|
unsigned int fline;
|
||||||
|
unsigned int lline;
|
||||||
|
unsigned long long count;
|
||||||
|
} tcov_line;
|
||||||
|
|
||||||
|
typedef struct tcov_function {
|
||||||
|
char *function;
|
||||||
|
unsigned int first_line;
|
||||||
|
unsigned int n_line;
|
||||||
|
unsigned int m_line;
|
||||||
|
tcov_line *line;
|
||||||
|
} tcov_function;
|
||||||
|
|
||||||
|
typedef struct tcov_file {
|
||||||
|
char *filename;
|
||||||
|
unsigned int n_func;
|
||||||
|
unsigned int m_func;
|
||||||
|
tcov_function *func;
|
||||||
|
struct tcov_file *next;
|
||||||
|
} tcov_file;
|
||||||
|
|
||||||
|
static FILE *open_tcov_file (char *cov_filename)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
#ifndef _WIN32
|
||||||
|
struct flock lock;
|
||||||
|
|
||||||
|
lock.l_type = F_WRLCK;
|
||||||
|
lock.l_whence = SEEK_SET;
|
||||||
|
lock.l_start = 0;
|
||||||
|
lock.l_len = 0; /* Until EOF. */
|
||||||
|
lock.l_pid = getpid ();
|
||||||
|
#endif
|
||||||
|
fd = open (cov_filename, O_RDWR | O_CREAT, 0666);
|
||||||
|
if (fd < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
while (fcntl (fd, F_SETLKW, &lock) && errno == EINTR)
|
||||||
|
continue;
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
OVERLAPPED overlapped = { 0 };
|
||||||
|
LockFileEx((HANDLE)_get_osfhandle(fd), LOCKFILE_EXCLUSIVE_LOCK,
|
||||||
|
0, 1, 0, &overlapped);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return fdopen (fd, "r+");
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long long get_value(unsigned char *p, int size)
|
||||||
|
{
|
||||||
|
unsigned long long value = 0;
|
||||||
|
|
||||||
|
p += size;
|
||||||
|
while (size--)
|
||||||
|
value = (value << 8) | *--p;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sort_func (const void *p, const void *q)
|
||||||
|
{
|
||||||
|
const tcov_function *pp = (const tcov_function *) p;
|
||||||
|
const tcov_function *pq = (const tcov_function *) q;
|
||||||
|
|
||||||
|
return pp->first_line > pq->first_line ? 1 :
|
||||||
|
pp->first_line < pq->first_line ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sort_line (const void *p, const void *q)
|
||||||
|
{
|
||||||
|
const tcov_line *pp = (const tcov_line *) p;
|
||||||
|
const tcov_line *pq = (const tcov_line *) q;
|
||||||
|
|
||||||
|
return pp->fline > pq->fline ? 1 :
|
||||||
|
pp->fline < pq->fline ? -1 :
|
||||||
|
pp->count < pq->count ? 1 :
|
||||||
|
pp->count > pq->count ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sort to let inline functions work */
|
||||||
|
static tcov_file *sort_test_coverage (unsigned char *p)
|
||||||
|
{
|
||||||
|
int i, j, k;
|
||||||
|
unsigned char *start = p;
|
||||||
|
tcov_file *file = NULL;
|
||||||
|
tcov_file *nfile;
|
||||||
|
|
||||||
|
p += 4;
|
||||||
|
while (*p) {
|
||||||
|
char *filename = (char *)p;
|
||||||
|
size_t len = strlen (filename);
|
||||||
|
|
||||||
|
nfile = file;
|
||||||
|
while (nfile) {
|
||||||
|
if (strcmp (nfile->filename, filename) == 0)
|
||||||
|
break;
|
||||||
|
nfile = nfile->next;
|
||||||
|
}
|
||||||
|
if (nfile == NULL) {
|
||||||
|
nfile = malloc (sizeof(tcov_file));
|
||||||
|
if (nfile == NULL) {
|
||||||
|
fprintf (stderr, "Malloc error test_coverage\n");
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
nfile->filename = filename;
|
||||||
|
nfile->n_func = 0;
|
||||||
|
nfile->m_func = 0;
|
||||||
|
nfile->func = NULL;
|
||||||
|
nfile->next = NULL;
|
||||||
|
if (file == NULL)
|
||||||
|
file = nfile;
|
||||||
|
else {
|
||||||
|
tcov_file *lfile = file;
|
||||||
|
|
||||||
|
while (lfile->next)
|
||||||
|
lfile = lfile->next;
|
||||||
|
lfile->next = nfile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p += len + 1;
|
||||||
|
while (*p) {
|
||||||
|
int i;
|
||||||
|
char *function = (char *)p;
|
||||||
|
tcov_function *func;
|
||||||
|
|
||||||
|
p += strlen (function) + 1;
|
||||||
|
p += -(p - start) & 7;
|
||||||
|
for (i = 0; i < nfile->n_func; i++) {
|
||||||
|
func = &nfile->func[i];
|
||||||
|
if (strcmp (func->function, function) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == nfile->n_func) {
|
||||||
|
if (nfile->n_func >= nfile->m_func) {
|
||||||
|
nfile->m_func = nfile->m_func == 0 ? 4 : nfile->m_func * 2;
|
||||||
|
nfile->func = realloc (nfile->func,
|
||||||
|
nfile->m_func *
|
||||||
|
sizeof (tcov_function));
|
||||||
|
if (nfile->func == NULL) {
|
||||||
|
fprintf (stderr, "Realloc error test_coverage\n");
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func = &nfile->func[nfile->n_func++];
|
||||||
|
func->function = function;
|
||||||
|
func->first_line = get_value (p, 8);
|
||||||
|
func->n_line = 0;
|
||||||
|
func->m_line = 0;
|
||||||
|
func->line = NULL;
|
||||||
|
}
|
||||||
|
p += 8;
|
||||||
|
while (*p) {
|
||||||
|
tcov_line *line;
|
||||||
|
unsigned long long val;
|
||||||
|
|
||||||
|
if (func->n_line >= func->m_line) {
|
||||||
|
func->m_line = func->m_line == 0 ? 4 : func->m_line * 2;
|
||||||
|
func->line = realloc (func->line,
|
||||||
|
func->m_line * sizeof (tcov_line));
|
||||||
|
if (func->line == NULL) {
|
||||||
|
fprintf (stderr, "Realloc error test_coverage\n");
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
line = &func->line[func->n_line++];
|
||||||
|
val = get_value (p, 8);
|
||||||
|
line->fline = (val >> 8) & 0xfffffffULL;
|
||||||
|
line->lline = val >> 36;
|
||||||
|
line->count = get_value (p + 8, 8);
|
||||||
|
p += 16;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
nfile = file;
|
||||||
|
while (nfile) {
|
||||||
|
qsort (nfile->func, nfile->n_func, sizeof (tcov_function), sort_func);
|
||||||
|
for (i = 0; i < nfile->n_func; i++) {
|
||||||
|
tcov_function *func = &nfile->func[i];
|
||||||
|
qsort (func->line, func->n_line, sizeof (tcov_line), sort_line);
|
||||||
|
}
|
||||||
|
nfile = nfile->next;
|
||||||
|
}
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* merge with previous tcov file */
|
||||||
|
static void merge_test_coverage (tcov_file *file, FILE *fp,
|
||||||
|
unsigned int *pruns)
|
||||||
|
{
|
||||||
|
unsigned int runs;
|
||||||
|
char *p;
|
||||||
|
char str[10000];
|
||||||
|
|
||||||
|
*pruns = 1;
|
||||||
|
if (fp == NULL)
|
||||||
|
return;
|
||||||
|
if (fgets(str, sizeof(str), fp) &&
|
||||||
|
(p = strrchr (str, ':')) &&
|
||||||
|
(sscanf (p + 1, "%u", &runs) == 1))
|
||||||
|
*pruns = runs + 1;
|
||||||
|
while (file) {
|
||||||
|
int i;
|
||||||
|
size_t len = strlen (file->filename);
|
||||||
|
|
||||||
|
while (fgets(str, sizeof(str), fp) &&
|
||||||
|
(p = strstr(str, "0:File:")) == NULL) {}
|
||||||
|
if ((p = strstr(str, "0:File:")) == NULL ||
|
||||||
|
strncmp (p + strlen("0:File:"), file->filename, len) != 0 ||
|
||||||
|
p[strlen("0:File:") + len] != ' ')
|
||||||
|
break;
|
||||||
|
for (i = 0; i < file->n_func; i++) {
|
||||||
|
int j;
|
||||||
|
tcov_function *func = &file->func[i];
|
||||||
|
unsigned int next_zero = 0;
|
||||||
|
unsigned int curline = 0;
|
||||||
|
|
||||||
|
for (j = 0; j < func->n_line; j++) {
|
||||||
|
tcov_line *line = &func->line[j];
|
||||||
|
unsigned int fline = line->fline;
|
||||||
|
unsigned long long count;
|
||||||
|
unsigned int tmp;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
while (curline < fline &&
|
||||||
|
fgets(str, sizeof(str), fp))
|
||||||
|
if ((p = strchr(str, ':')) &&
|
||||||
|
sscanf (p + 1, "%u", &tmp) == 1)
|
||||||
|
curline = tmp;
|
||||||
|
if (sscanf (str, "%llu%c\n", &count, &c) == 2) {
|
||||||
|
if (next_zero == 0)
|
||||||
|
line->count += count;
|
||||||
|
next_zero = c == '*';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file = file->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* store tcov data in file */
|
||||||
|
void __store_test_coverage (unsigned char * p)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
unsigned int files;
|
||||||
|
unsigned int funcs;
|
||||||
|
unsigned int blocks;
|
||||||
|
unsigned int blocks_run;
|
||||||
|
unsigned int runs;
|
||||||
|
char *cov_filename = (char *)p + get_value (p, 4);
|
||||||
|
FILE *fp;
|
||||||
|
char *q;
|
||||||
|
tcov_file *file;
|
||||||
|
tcov_file *nfile;
|
||||||
|
tcov_function *func;
|
||||||
|
|
||||||
|
fp = open_tcov_file (cov_filename);
|
||||||
|
if (fp == NULL) {
|
||||||
|
fprintf (stderr, "Cannot create coverage file: %s\n", cov_filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
file = sort_test_coverage (p);
|
||||||
|
merge_test_coverage (file, fp, &runs);
|
||||||
|
fseek (fp, 0, SEEK_SET);
|
||||||
|
fprintf (fp, " -: 0:Runs:%u\n", runs);
|
||||||
|
files = 0;
|
||||||
|
funcs = 0;
|
||||||
|
blocks = 0;
|
||||||
|
blocks_run = 0;
|
||||||
|
nfile = file;
|
||||||
|
while (nfile) {
|
||||||
|
files++;
|
||||||
|
for (i = 0; i < nfile->n_func; i++) {
|
||||||
|
func = &nfile->func[i];
|
||||||
|
funcs++;
|
||||||
|
for (j = 0; j < func->n_line; j++) {
|
||||||
|
blocks++;
|
||||||
|
blocks_run += func->line[j].count != 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nfile = nfile->next;
|
||||||
|
}
|
||||||
|
if (blocks == 0)
|
||||||
|
blocks = 1;
|
||||||
|
fprintf (fp, " -: 0:All:%s Files:%u Functions:%u %.02f%%\n",
|
||||||
|
cov_filename, files, funcs, 100.0 * (double) blocks_run / blocks);
|
||||||
|
nfile = file;
|
||||||
|
while (nfile) {
|
||||||
|
FILE *src = fopen (nfile->filename, "r");
|
||||||
|
unsigned int curline = 1;
|
||||||
|
char str[10000];
|
||||||
|
|
||||||
|
if (src == NULL)
|
||||||
|
goto next;
|
||||||
|
funcs = 0;
|
||||||
|
blocks = 0;
|
||||||
|
blocks_run = 0;
|
||||||
|
for (i = 0; i < nfile->n_func; i++) {
|
||||||
|
func = &nfile->func[i];
|
||||||
|
funcs++;
|
||||||
|
for (j = 0; j < func->n_line; j++) {
|
||||||
|
blocks++;
|
||||||
|
blocks_run += func->line[j].count != 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (blocks == 0)
|
||||||
|
blocks = 1;
|
||||||
|
fprintf (fp, " -: 0:File:%s Functions:%u %.02f%%\n",
|
||||||
|
nfile->filename, funcs, 100.0 * (double) blocks_run / blocks);
|
||||||
|
for (i = 0; i < nfile->n_func; i++) {
|
||||||
|
func = &nfile->func[i];
|
||||||
|
|
||||||
|
while (curline < func->first_line &&
|
||||||
|
fgets(str, sizeof(str), src))
|
||||||
|
fprintf (fp, " -:%5u:%s", curline++, str);
|
||||||
|
blocks = 0;
|
||||||
|
blocks_run = 0;
|
||||||
|
for (j = 0; j < func->n_line; j++) {
|
||||||
|
blocks++;
|
||||||
|
blocks_run += func->line[j].count != 0;
|
||||||
|
}
|
||||||
|
if (blocks == 0)
|
||||||
|
blocks = 1;
|
||||||
|
fprintf (fp, " -: 0:Function:%s %.02f%%\n",
|
||||||
|
func->function, 100.0 * (double) blocks_run / blocks);
|
||||||
|
#if 0
|
||||||
|
for (j = 0; j < func->n_line; j++) {
|
||||||
|
unsigned int fline = func->line[j].fline;
|
||||||
|
unsigned int lline = func->line[j].lline;
|
||||||
|
unsigned long long count = func->line[j].count;
|
||||||
|
|
||||||
|
fprintf (fp, "%u %u %llu\n", fline, lline, count);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
for (j = 0; j < func->n_line;) {
|
||||||
|
unsigned int fline = func->line[j].fline;
|
||||||
|
unsigned int lline = func->line[j].lline;
|
||||||
|
unsigned long long count = func->line[j].count;
|
||||||
|
unsigned int has_zero = 0;
|
||||||
|
unsigned int same_line = fline == lline;
|
||||||
|
|
||||||
|
j++;
|
||||||
|
while (j < func->n_line) {
|
||||||
|
unsigned int nfline = func->line[j].fline;
|
||||||
|
unsigned int nlline = func->line[j].lline;
|
||||||
|
unsigned long long ncount = func->line[j].count;
|
||||||
|
|
||||||
|
if (fline == nfline) {
|
||||||
|
if (ncount == 0)
|
||||||
|
has_zero = 1;
|
||||||
|
else if (ncount > count)
|
||||||
|
count = ncount;
|
||||||
|
same_line = nfline == nlline;
|
||||||
|
lline = nlline;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (same_line)
|
||||||
|
lline++;
|
||||||
|
|
||||||
|
while (curline < fline &&
|
||||||
|
fgets(str, sizeof(str), src))
|
||||||
|
fprintf (fp, " -:%5u:%s", curline++, str);
|
||||||
|
while (curline < lline &&
|
||||||
|
fgets(str, sizeof(str), src)) {
|
||||||
|
if (count == 0)
|
||||||
|
fprintf (fp, " #####:%5u:%s",
|
||||||
|
curline, str);
|
||||||
|
else if (has_zero)
|
||||||
|
fprintf (fp, "%8llu*:%5u:%s",
|
||||||
|
count, curline, str);
|
||||||
|
else
|
||||||
|
fprintf (fp, "%9llu:%5u:%s",
|
||||||
|
count, curline, str);
|
||||||
|
curline++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (fgets(str, sizeof(str), src))
|
||||||
|
fprintf (fp, " -:%5u:%s", curline++, str);
|
||||||
|
fclose (src);
|
||||||
|
next:
|
||||||
|
nfile = nfile->next;
|
||||||
|
}
|
||||||
|
while (file) {
|
||||||
|
for (i = 0; i < file->n_func; i++) {
|
||||||
|
func = &file->func[i];
|
||||||
|
free (func->line);
|
||||||
|
}
|
||||||
|
free (file->func);
|
||||||
|
nfile = file;
|
||||||
|
file = file->next;
|
||||||
|
free (nfile);
|
||||||
|
}
|
||||||
|
fclose (fp);
|
||||||
|
}
|
||||||
@ -3,7 +3,6 @@
|
|||||||
#if defined __x86_64__
|
#if defined __x86_64__
|
||||||
|
|
||||||
/* Avoid include files, they may not be available when cross compiling */
|
/* Avoid include files, they may not be available when cross compiling */
|
||||||
extern void *memset(void *s, int c, __SIZE_TYPE__ n);
|
|
||||||
extern void abort(void);
|
extern void abort(void);
|
||||||
|
|
||||||
/* This should be in sync with our include/stdarg.h */
|
/* This should be in sync with our include/stdarg.h */
|
||||||
@ -12,6 +11,7 @@ enum __va_arg_type {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* GCC compatible definition of va_list. */
|
/* GCC compatible definition of va_list. */
|
||||||
|
/*predefined by TCC (tcc_predefs.h):
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned int gp_offset;
|
unsigned int gp_offset;
|
||||||
unsigned int fp_offset;
|
unsigned int fp_offset;
|
||||||
@ -20,23 +20,18 @@ typedef struct {
|
|||||||
char *overflow_arg_area;
|
char *overflow_arg_area;
|
||||||
};
|
};
|
||||||
char *reg_save_area;
|
char *reg_save_area;
|
||||||
} __va_list_struct;
|
} __builtin_va_list[1];
|
||||||
|
*/
|
||||||
|
|
||||||
void __va_start(__va_list_struct *ap, void *fp)
|
extern void *memcpy(void *dest, const void *src, unsigned long n);
|
||||||
{
|
|
||||||
memset(ap, 0, sizeof(__va_list_struct));
|
|
||||||
*ap = *(__va_list_struct *)((char *)fp - 16);
|
|
||||||
ap->overflow_arg_area = (char *)fp + ap->overflow_offset;
|
|
||||||
ap->reg_save_area = (char *)fp - 176 - 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *__va_arg(__va_list_struct *ap,
|
void *__va_arg(__builtin_va_list ap,
|
||||||
enum __va_arg_type arg_type,
|
int arg_type,
|
||||||
int size, int align)
|
int size, int align)
|
||||||
{
|
{
|
||||||
size = (size + 7) & ~7;
|
size = (size + 7) & ~7;
|
||||||
align = (align + 7) & ~7;
|
align = (align + 7) & ~7;
|
||||||
switch (arg_type) {
|
switch ((enum __va_arg_type)arg_type) {
|
||||||
case __va_gen_reg:
|
case __va_gen_reg:
|
||||||
if (ap->gp_offset + size <= 48) {
|
if (ap->gp_offset + size <= 48) {
|
||||||
ap->gp_offset += size;
|
ap->gp_offset += size;
|
||||||
@ -47,9 +42,15 @@ void *__va_arg(__va_list_struct *ap,
|
|||||||
case __va_float_reg:
|
case __va_float_reg:
|
||||||
if (ap->fp_offset < 128 + 48) {
|
if (ap->fp_offset < 128 + 48) {
|
||||||
ap->fp_offset += 16;
|
ap->fp_offset += 16;
|
||||||
return ap->reg_save_area + ap->fp_offset - 16;
|
if (size == 8)
|
||||||
|
return ap->reg_save_area + ap->fp_offset - 16;
|
||||||
|
if (ap->fp_offset < 128 + 48) {
|
||||||
|
memcpy(ap->reg_save_area + ap->fp_offset - 8,
|
||||||
|
ap->reg_save_area + ap->fp_offset, 8);
|
||||||
|
ap->fp_offset += 16;
|
||||||
|
return ap->reg_save_area + ap->fp_offset - 32;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
size = 8;
|
|
||||||
goto use_overflow_area;
|
goto use_overflow_area;
|
||||||
|
|
||||||
case __va_stack:
|
case __va_stack:
|
||||||
@ -60,6 +61,7 @@ void *__va_arg(__va_list_struct *ap,
|
|||||||
|
|
||||||
default: /* should never happen */
|
default: /* should never happen */
|
||||||
abort();
|
abort();
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
50
libtcc.h
50
libtcc.h
@ -9,8 +9,12 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct TCCState;
|
/*****************************/
|
||||||
|
/* set custom allocator for all allocations (optional), NULL for default. */
|
||||||
|
typedef void *TCCReallocFunc(void *ptr, unsigned long size);
|
||||||
|
LIBTCCAPI void tcc_set_realloc(TCCReallocFunc *my_realloc);
|
||||||
|
|
||||||
|
/*****************************/
|
||||||
typedef struct TCCState TCCState;
|
typedef struct TCCState TCCState;
|
||||||
|
|
||||||
/* create a new TCC compilation context */
|
/* create a new TCC compilation context */
|
||||||
@ -22,12 +26,12 @@ LIBTCCAPI void tcc_delete(TCCState *s);
|
|||||||
/* set CONFIG_TCCDIR at runtime */
|
/* set CONFIG_TCCDIR at runtime */
|
||||||
LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path);
|
LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path);
|
||||||
|
|
||||||
/* set error/warning display callback */
|
/* set error/warning callback (optional) */
|
||||||
LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque,
|
typedef void TCCErrorFunc(void *opaque, const char *msg);
|
||||||
void (*error_func)(void *opaque, const char *msg));
|
LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc *error_func);
|
||||||
|
|
||||||
/* set options as from command line (multiple supported) */
|
/* set options as from command line (multiple supported) */
|
||||||
LIBTCCAPI void tcc_set_options(TCCState *s, const char *str);
|
LIBTCCAPI int tcc_set_options(TCCState *s, const char *str);
|
||||||
|
|
||||||
/*****************************/
|
/*****************************/
|
||||||
/* preprocessor */
|
/* preprocessor */
|
||||||
@ -38,7 +42,7 @@ LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname);
|
|||||||
/* add in system include path */
|
/* add in system include path */
|
||||||
LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname);
|
LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname);
|
||||||
|
|
||||||
/* define preprocessor symbol 'sym'. Can put optional value */
|
/* define preprocessor symbol 'sym'. value can be NULL, sym can be "sym=val" */
|
||||||
LIBTCCAPI void tcc_define_symbol(TCCState *s, const char *sym, const char *value);
|
LIBTCCAPI void tcc_define_symbol(TCCState *s, const char *sym, const char *value);
|
||||||
|
|
||||||
/* undefine preprocess symbol 'sym' */
|
/* undefine preprocess symbol 'sym' */
|
||||||
@ -53,16 +57,19 @@ LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename);
|
|||||||
/* compile a string containing a C source. Return -1 if error. */
|
/* compile a string containing a C source. Return -1 if error. */
|
||||||
LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf);
|
LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf);
|
||||||
|
|
||||||
|
/* Tip: to have more specific errors/warnings from tcc_compile_string(),
|
||||||
|
you can prefix the string with "#line <num> \"<filename>\"\n" */
|
||||||
|
|
||||||
/*****************************/
|
/*****************************/
|
||||||
/* linking commands */
|
/* linking commands */
|
||||||
|
|
||||||
/* set output type. MUST BE CALLED before any compilation */
|
/* set output type. MUST BE CALLED before any compilation */
|
||||||
LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type);
|
LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type);
|
||||||
#define TCC_OUTPUT_MEMORY 1 /* output will be run in memory (default) */
|
#define TCC_OUTPUT_MEMORY 1 /* output will be run in memory */
|
||||||
#define TCC_OUTPUT_EXE 2 /* executable file */
|
#define TCC_OUTPUT_EXE 2 /* executable file */
|
||||||
#define TCC_OUTPUT_DLL 3 /* dynamic library */
|
#define TCC_OUTPUT_DLL 4 /* dynamic library */
|
||||||
#define TCC_OUTPUT_OBJ 4 /* object file */
|
#define TCC_OUTPUT_OBJ 3 /* object file */
|
||||||
#define TCC_OUTPUT_PREPROCESS 5 /* only preprocess (used internally) */
|
#define TCC_OUTPUT_PREPROCESS 5 /* only preprocess */
|
||||||
|
|
||||||
/* equivalent to -Lpath option */
|
/* equivalent to -Lpath option */
|
||||||
LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname);
|
LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname);
|
||||||
@ -82,17 +89,26 @@ LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename);
|
|||||||
LIBTCCAPI int tcc_run(TCCState *s, int argc, char **argv);
|
LIBTCCAPI int tcc_run(TCCState *s, int argc, char **argv);
|
||||||
|
|
||||||
/* do all relocations (needed before using tcc_get_symbol()) */
|
/* do all relocations (needed before using tcc_get_symbol()) */
|
||||||
LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr);
|
LIBTCCAPI int tcc_relocate(TCCState *s1);
|
||||||
/* possible values for 'ptr':
|
|
||||||
- TCC_RELOCATE_AUTO : Allocate and manage memory internally
|
|
||||||
- NULL : return required memory size for the step below
|
|
||||||
- memory address : copy code to memory passed by the caller
|
|
||||||
returns -1 if error. */
|
|
||||||
#define TCC_RELOCATE_AUTO (void*)1
|
|
||||||
|
|
||||||
/* return symbol value or NULL if not found */
|
/* return symbol value or NULL if not found */
|
||||||
LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name);
|
LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name);
|
||||||
|
|
||||||
|
/* list all (global) symbols and their values via 'symbol_cb()' */
|
||||||
|
LIBTCCAPI void tcc_list_symbols(TCCState *s, void *ctx,
|
||||||
|
void (*symbol_cb)(void *ctx, const char *name, const void *val));
|
||||||
|
|
||||||
|
/* experimental/advanced section (see libtcc_test_mt.c for an example) */
|
||||||
|
|
||||||
|
/* catch runtime exceptions (optionally limit backtraces at top_func),
|
||||||
|
when using tcc_set_options("-bt") and when not using tcc_run() */
|
||||||
|
LIBTCCAPI void *_tcc_setjmp(TCCState *s1, void *jmp_buf, void *top_func, void *longjmp);
|
||||||
|
#define tcc_setjmp(s1,jb,f) setjmp(_tcc_setjmp(s1, jb, f, longjmp))
|
||||||
|
|
||||||
|
/* custom error printer for runtime exceptions. Returning 0 stops backtrace */
|
||||||
|
typedef int TCCBtFunc(void *udata, void *pc, const char *file, int line, const char* func, const char *msg);
|
||||||
|
LIBTCCAPI void tcc_set_backtrace_func(TCCState *s1, void* userdata, TCCBtFunc*);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
3059
riscv64-asm.c
Normal file
3059
riscv64-asm.c
Normal file
File diff suppressed because it is too large
Load Diff
1496
riscv64-gen.c
Normal file
1496
riscv64-gen.c
Normal file
File diff suppressed because it is too large
Load Diff
440
riscv64-link.c
Normal file
440
riscv64-link.c
Normal file
@ -0,0 +1,440 @@
|
|||||||
|
#ifdef TARGET_DEFS_ONLY
|
||||||
|
|
||||||
|
#define EM_TCC_TARGET EM_RISCV
|
||||||
|
|
||||||
|
#define R_DATA_32 R_RISCV_32
|
||||||
|
#define R_DATA_PTR R_RISCV_64
|
||||||
|
#define R_JMP_SLOT R_RISCV_JUMP_SLOT
|
||||||
|
#define R_GLOB_DAT R_RISCV_64
|
||||||
|
#define R_COPY R_RISCV_COPY
|
||||||
|
#define R_RELATIVE R_RISCV_RELATIVE
|
||||||
|
|
||||||
|
#define R_NUM R_RISCV_NUM
|
||||||
|
|
||||||
|
#define ELF_START_ADDR 0x00010000
|
||||||
|
#define ELF_PAGE_SIZE 0x1000
|
||||||
|
|
||||||
|
#define PCRELATIVE_DLLPLT 1
|
||||||
|
#define RELOCATE_DLLPLT 1
|
||||||
|
|
||||||
|
#else /* !TARGET_DEFS_ONLY */
|
||||||
|
|
||||||
|
//#define DEBUG_RELOC
|
||||||
|
#include "tcc.h"
|
||||||
|
|
||||||
|
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
|
||||||
|
relocations, returns -1. */
|
||||||
|
ST_FUNC int code_reloc (int reloc_type)
|
||||||
|
{
|
||||||
|
switch (reloc_type) {
|
||||||
|
|
||||||
|
case R_RISCV_BRANCH:
|
||||||
|
case R_RISCV_CALL:
|
||||||
|
case R_RISCV_JAL:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case R_RISCV_GOT_HI20:
|
||||||
|
case R_RISCV_PCREL_HI20:
|
||||||
|
case R_RISCV_PCREL_LO12_I:
|
||||||
|
case R_RISCV_PCREL_LO12_S:
|
||||||
|
case R_RISCV_32_PCREL:
|
||||||
|
case R_RISCV_SET6:
|
||||||
|
case R_RISCV_SET8:
|
||||||
|
case R_RISCV_SET16:
|
||||||
|
case R_RISCV_SUB6:
|
||||||
|
case R_RISCV_ADD16:
|
||||||
|
case R_RISCV_ADD32:
|
||||||
|
case R_RISCV_ADD64:
|
||||||
|
case R_RISCV_SUB8:
|
||||||
|
case R_RISCV_SUB16:
|
||||||
|
case R_RISCV_SUB32:
|
||||||
|
case R_RISCV_SUB64:
|
||||||
|
case R_RISCV_32:
|
||||||
|
case R_RISCV_64:
|
||||||
|
case R_RISCV_SET_ULEB128:
|
||||||
|
case R_RISCV_SUB_ULEB128:
|
||||||
|
case R_RISCV_TPREL_HI20:
|
||||||
|
case R_RISCV_TPREL_LO12_I:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case R_RISCV_CALL_PLT:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns an enumerator to describe whether and when the relocation needs a
|
||||||
|
GOT and/or PLT entry to be created. See tcc.h for a description of the
|
||||||
|
different values. */
|
||||||
|
ST_FUNC int gotplt_entry_type (int reloc_type)
|
||||||
|
{
|
||||||
|
switch (reloc_type) {
|
||||||
|
case R_RISCV_ALIGN:
|
||||||
|
case R_RISCV_RELAX:
|
||||||
|
case R_RISCV_RVC_BRANCH:
|
||||||
|
case R_RISCV_RVC_JUMP:
|
||||||
|
case R_RISCV_JUMP_SLOT:
|
||||||
|
case R_RISCV_SET6:
|
||||||
|
case R_RISCV_SET8:
|
||||||
|
case R_RISCV_SET16:
|
||||||
|
case R_RISCV_SUB6:
|
||||||
|
case R_RISCV_ADD16:
|
||||||
|
case R_RISCV_SUB8:
|
||||||
|
case R_RISCV_SUB16:
|
||||||
|
case R_RISCV_SET_ULEB128:
|
||||||
|
case R_RISCV_SUB_ULEB128:
|
||||||
|
return NO_GOTPLT_ENTRY;
|
||||||
|
|
||||||
|
case R_RISCV_BRANCH:
|
||||||
|
case R_RISCV_CALL:
|
||||||
|
case R_RISCV_PCREL_HI20:
|
||||||
|
case R_RISCV_PCREL_LO12_I:
|
||||||
|
case R_RISCV_PCREL_LO12_S:
|
||||||
|
case R_RISCV_32_PCREL:
|
||||||
|
case R_RISCV_ADD32:
|
||||||
|
case R_RISCV_ADD64:
|
||||||
|
case R_RISCV_SUB32:
|
||||||
|
case R_RISCV_SUB64:
|
||||||
|
case R_RISCV_32:
|
||||||
|
case R_RISCV_64:
|
||||||
|
case R_RISCV_JAL:
|
||||||
|
case R_RISCV_CALL_PLT:
|
||||||
|
return AUTO_GOTPLT_ENTRY;
|
||||||
|
|
||||||
|
case R_RISCV_GOT_HI20:
|
||||||
|
return ALWAYS_GOTPLT_ENTRY;
|
||||||
|
|
||||||
|
case R_RISCV_TPREL_HI20:
|
||||||
|
case R_RISCV_TPREL_LO12_I:
|
||||||
|
return NO_GOTPLT_ENTRY;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
|
||||||
|
{
|
||||||
|
Section *plt = s1->plt;
|
||||||
|
uint8_t *p;
|
||||||
|
unsigned plt_offset;
|
||||||
|
|
||||||
|
if (plt->data_offset == 0)
|
||||||
|
section_ptr_add(plt, 32);
|
||||||
|
plt_offset = plt->data_offset;
|
||||||
|
|
||||||
|
p = section_ptr_add(plt, 16);
|
||||||
|
write64le(p, got_offset);
|
||||||
|
return plt_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* relocate the PLT: compute addresses and offsets in the PLT now that final
|
||||||
|
address for PLT and GOT are known (see fill_program_header) */
|
||||||
|
ST_FUNC void relocate_plt(TCCState *s1)
|
||||||
|
{
|
||||||
|
uint8_t *p, *p_end;
|
||||||
|
|
||||||
|
if (!s1->plt)
|
||||||
|
return;
|
||||||
|
|
||||||
|
p = s1->plt->data;
|
||||||
|
p_end = p + s1->plt->data_offset;
|
||||||
|
|
||||||
|
if (p < p_end) {
|
||||||
|
uint64_t plt = s1->plt->sh_addr;
|
||||||
|
uint64_t got = s1->got->sh_addr;
|
||||||
|
uint64_t off = (got - plt + 0x800) >> 12;
|
||||||
|
if ((off + ((uint32_t)1 << 20)) >> 21)
|
||||||
|
tcc_error_noabort("Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", (long)off, (long)got, (long)plt);
|
||||||
|
write32le(p, 0x397 | (off << 12)); // auipc t2, %pcrel_hi(got)
|
||||||
|
write32le(p + 4, 0x41c30333); // sub t1, t1, t3
|
||||||
|
write32le(p + 8, 0x0003be03 // ld t3, %pcrel_lo(got)(t2)
|
||||||
|
| (((got - plt) & 0xfff) << 20));
|
||||||
|
write32le(p + 12, 0xfd430313); // addi t1, t1, -(32+12)
|
||||||
|
write32le(p + 16, 0x00038293 // addi t0, t2, %pcrel_lo(got)
|
||||||
|
| (((got - plt) & 0xfff) << 20));
|
||||||
|
write32le(p + 20, 0x00135313); // srli t1, t1, log2(16/PTRSIZE)
|
||||||
|
write32le(p + 24, 0x0082b283); // ld t0, PTRSIZE(t0)
|
||||||
|
write32le(p + 28, 0x000e0067); // jr t3
|
||||||
|
p += 32;
|
||||||
|
while (p < p_end) {
|
||||||
|
uint64_t pc = plt + (p - s1->plt->data);
|
||||||
|
uint64_t addr = got + read64le(p);
|
||||||
|
uint64_t off = (addr - pc + 0x800) >> 12;
|
||||||
|
if ((off + ((uint32_t)1 << 20)) >> 21)
|
||||||
|
tcc_error_noabort("Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", (long)off, (long)addr, (long)pc);
|
||||||
|
write32le(p, 0xe17 | (off << 12)); // auipc t3, %pcrel_hi(func@got)
|
||||||
|
write32le(p + 4, 0x000e3e03 // ld t3, %pcrel_lo(func@got)(t3)
|
||||||
|
| (((addr - pc) & 0xfff) << 20));
|
||||||
|
write32le(p + 8, 0x000e0367); // jalr t1, t3
|
||||||
|
write32le(p + 12, 0x00000013); // nop
|
||||||
|
p += 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s1->plt->reloc) {
|
||||||
|
ElfW_Rel *rel;
|
||||||
|
p = s1->got->data;
|
||||||
|
for_each_elem(s1->plt->reloc, 0, rel, ElfW_Rel) {
|
||||||
|
write64le(p + rel->r_offset, s1->plt->sh_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void riscv64_record_pcrel_hi(TCCState *s1, addr_t addr, addr_t val)
|
||||||
|
{
|
||||||
|
struct pcrel_hi *entry = tcc_malloc(sizeof *entry);
|
||||||
|
entry->addr = addr;
|
||||||
|
entry->val = val;
|
||||||
|
dynarray_add(&s1->pcrel_hi_entries, &s1->nb_pcrel_hi_entries, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int riscv64_lookup_pcrel_hi(TCCState *s1, addr_t hi_addr, addr_t *hi_val)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = s1->nb_pcrel_hi_entries; i > 0; ) {
|
||||||
|
struct pcrel_hi *entry = s1->pcrel_hi_entries[--i];
|
||||||
|
if (entry->addr == hi_addr) {
|
||||||
|
*hi_val = entry->val;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tcc_error_noabort("unsupported hi/lo pcrel reloc scheme");
|
||||||
|
}
|
||||||
|
|
||||||
|
ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
||||||
|
addr_t addr, addr_t val)
|
||||||
|
{
|
||||||
|
uint64_t off64;
|
||||||
|
uint32_t off32;
|
||||||
|
int sym_index = ELFW(R_SYM)(rel->r_info), esym_index;
|
||||||
|
ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case R_RISCV_ALIGN:
|
||||||
|
case R_RISCV_RELAX:
|
||||||
|
return;
|
||||||
|
|
||||||
|
case R_RISCV_BRANCH:
|
||||||
|
off64 = val - addr;
|
||||||
|
if ((off64 + (1 << 12)) & ~(uint64_t)0x1ffe)
|
||||||
|
tcc_error_noabort("R_RISCV_BRANCH relocation failed"
|
||||||
|
" (val=%lx, addr=%lx)", (long)val, (long)addr);
|
||||||
|
off32 = off64 >> 1;
|
||||||
|
write32le(ptr, (read32le(ptr) & ~0xfe000f80)
|
||||||
|
| ((off32 & 0x800) << 20)
|
||||||
|
| ((off32 & 0x3f0) << 21)
|
||||||
|
| ((off32 & 0x00f) << 8)
|
||||||
|
| ((off32 & 0x400) >> 3));
|
||||||
|
return;
|
||||||
|
case R_RISCV_JAL:
|
||||||
|
off64 = val - addr;
|
||||||
|
if ((off64 + (1 << 21)) & ~(((uint64_t)1 << 22) - 2))
|
||||||
|
tcc_error_noabort("R_RISCV_JAL relocation failed"
|
||||||
|
" (val=%lx, addr=%lx)", (long)val, (long)addr);
|
||||||
|
off32 = off64;
|
||||||
|
write32le(ptr, (read32le(ptr) & 0xfff)
|
||||||
|
| (((off32 >> 12) & 0xff) << 12)
|
||||||
|
| (((off32 >> 11) & 1) << 20)
|
||||||
|
| (((off32 >> 1) & 0x3ff) << 21)
|
||||||
|
| (((off32 >> 20) & 1) << 31));
|
||||||
|
return;
|
||||||
|
case R_RISCV_CALL:
|
||||||
|
case R_RISCV_CALL_PLT:
|
||||||
|
write32le(ptr, (read32le(ptr) & 0xfff)
|
||||||
|
| ((val - addr + 0x800) & ~0xfff));
|
||||||
|
write32le(ptr + 4, (read32le(ptr + 4) & 0xfffff)
|
||||||
|
| (((val - addr) & 0xfff) << 20));
|
||||||
|
return;
|
||||||
|
case R_RISCV_PCREL_HI20:
|
||||||
|
#ifdef DEBUG_RELOC
|
||||||
|
printf("PCREL_HI20: val=%lx addr=%lx\n", (long)val, (long)addr);
|
||||||
|
#endif
|
||||||
|
off64 = (int64_t)(val - addr + 0x800) >> 12;
|
||||||
|
if ((off64 + ((uint64_t)1 << 20)) >> 21)
|
||||||
|
tcc_error_noabort("R_RISCV_PCREL_HI20 relocation failed: off=%lx cond=%lx sym=%s",
|
||||||
|
(long)off64, (long)((int64_t)(off64 + ((uint64_t)1 << 20)) >> 21),
|
||||||
|
symtab_section->link->data + sym->st_name);
|
||||||
|
write32le(ptr, (read32le(ptr) & 0xfff)
|
||||||
|
| ((off64 & 0xfffff) << 12));
|
||||||
|
riscv64_record_pcrel_hi(s1, addr, val);
|
||||||
|
return;
|
||||||
|
case R_RISCV_GOT_HI20:
|
||||||
|
val = s1->got->sh_addr + get_sym_attr(s1, sym_index, 0)->got_offset;
|
||||||
|
off64 = (int64_t)(val - addr + 0x800) >> 12;
|
||||||
|
if ((off64 + ((uint64_t)1 << 20)) >> 21)
|
||||||
|
tcc_error_noabort("R_RISCV_GOT_HI20 relocation failed");
|
||||||
|
write32le(ptr, (read32le(ptr) & 0xfff)
|
||||||
|
| ((off64 & 0xfffff) << 12));
|
||||||
|
riscv64_record_pcrel_hi(s1, addr, val);
|
||||||
|
return;
|
||||||
|
case R_RISCV_PCREL_LO12_I:
|
||||||
|
#ifdef DEBUG_RELOC
|
||||||
|
printf("PCREL_LO12_I: val=%lx addr=%lx\n", (long)val, (long)addr);
|
||||||
|
#endif
|
||||||
|
addr = val;
|
||||||
|
riscv64_lookup_pcrel_hi(s1, addr, &val);
|
||||||
|
write32le(ptr, (read32le(ptr) & 0xfffff)
|
||||||
|
| (((val - addr) & 0xfff) << 20));
|
||||||
|
return;
|
||||||
|
case R_RISCV_PCREL_LO12_S:
|
||||||
|
addr = val;
|
||||||
|
riscv64_lookup_pcrel_hi(s1, addr, &val);
|
||||||
|
off32 = val - addr;
|
||||||
|
write32le(ptr, (read32le(ptr) & ~0xfe000f80)
|
||||||
|
| ((off32 & 0xfe0) << 20)
|
||||||
|
| ((off32 & 0x01f) << 7));
|
||||||
|
return;
|
||||||
|
|
||||||
|
case R_RISCV_RVC_BRANCH:
|
||||||
|
off64 = (val - addr);
|
||||||
|
if ((off64 + (1 << 8)) & ~(uint64_t)0x1fe)
|
||||||
|
tcc_error_noabort("R_RISCV_RVC_BRANCH relocation failed"
|
||||||
|
" (val=%lx, addr=%lx)", (long)val, (long)addr);
|
||||||
|
off32 = off64;
|
||||||
|
write16le(ptr, (read16le(ptr) & 0xe383)
|
||||||
|
| (((off32 >> 5) & 1) << 2)
|
||||||
|
| (((off32 >> 1) & 3) << 3)
|
||||||
|
| (((off32 >> 6) & 3) << 5)
|
||||||
|
| (((off32 >> 3) & 3) << 10)
|
||||||
|
| (((off32 >> 8) & 1) << 12));
|
||||||
|
return;
|
||||||
|
case R_RISCV_RVC_JUMP:
|
||||||
|
off64 = (val - addr);
|
||||||
|
if ((off64 + (1 << 11)) & ~(uint64_t)0xffe)
|
||||||
|
tcc_error_noabort("R_RISCV_RVC_BRANCH relocation failed"
|
||||||
|
" (val=%lx, addr=%lx)", (long)val, (long)addr);
|
||||||
|
off32 = off64;
|
||||||
|
write16le(ptr, (read16le(ptr) & 0xe003)
|
||||||
|
| (((off32 >> 5) & 1) << 2)
|
||||||
|
| (((off32 >> 1) & 7) << 3)
|
||||||
|
| (((off32 >> 7) & 1) << 6)
|
||||||
|
| (((off32 >> 6) & 1) << 7)
|
||||||
|
| (((off32 >> 10) & 1) << 8)
|
||||||
|
| (((off32 >> 8) & 3) << 9)
|
||||||
|
| (((off32 >> 4) & 1) << 11)
|
||||||
|
| (((off32 >> 11) & 1) << 12));
|
||||||
|
return;
|
||||||
|
|
||||||
|
case R_RISCV_32:
|
||||||
|
if (s1->output_type & TCC_OUTPUT_DYN) {
|
||||||
|
/* XXX: this logic may depend on TCC's codegen
|
||||||
|
now TCC uses R_RISCV_RELATIVE even for a 64bit pointer */
|
||||||
|
qrel->r_offset = rel->r_offset;
|
||||||
|
qrel->r_info = ELFW(R_INFO)(0, R_RISCV_RELATIVE);
|
||||||
|
/* Use sign extension! */
|
||||||
|
qrel->r_addend = (int)read32le(ptr) + val;
|
||||||
|
qrel++;
|
||||||
|
}
|
||||||
|
add32le(ptr, val);
|
||||||
|
return;
|
||||||
|
case R_RISCV_64:
|
||||||
|
if (s1->output_type & TCC_OUTPUT_DYN) {
|
||||||
|
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
|
||||||
|
qrel->r_offset = rel->r_offset;
|
||||||
|
if (esym_index) {
|
||||||
|
qrel->r_info = ELFW(R_INFO)(esym_index, R_RISCV_64);
|
||||||
|
qrel->r_addend = rel->r_addend;
|
||||||
|
qrel++;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
qrel->r_info = ELFW(R_INFO)(0, R_RISCV_RELATIVE);
|
||||||
|
qrel->r_addend = read64le(ptr) + val;
|
||||||
|
qrel++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case R_RISCV_JUMP_SLOT:
|
||||||
|
add64le(ptr, val);
|
||||||
|
return;
|
||||||
|
case R_RISCV_ADD64:
|
||||||
|
write64le(ptr, read64le(ptr) + val);
|
||||||
|
return;
|
||||||
|
case R_RISCV_ADD32:
|
||||||
|
write32le(ptr, read32le(ptr) + val);
|
||||||
|
return;
|
||||||
|
case R_RISCV_SUB64:
|
||||||
|
write64le(ptr, read64le(ptr) - val);
|
||||||
|
return;
|
||||||
|
case R_RISCV_SUB32:
|
||||||
|
write32le(ptr, read32le(ptr) - val);
|
||||||
|
return;
|
||||||
|
case R_RISCV_ADD16:
|
||||||
|
write16le(ptr, read16le(ptr) + val);
|
||||||
|
return;
|
||||||
|
case R_RISCV_SUB8:
|
||||||
|
*ptr -= val;
|
||||||
|
return;
|
||||||
|
case R_RISCV_SUB16:
|
||||||
|
write16le(ptr, read16le(ptr) - val);
|
||||||
|
return;
|
||||||
|
case R_RISCV_SET6:
|
||||||
|
*ptr = (*ptr & ~0x3f) | (val & 0x3f);
|
||||||
|
return;
|
||||||
|
case R_RISCV_SET8:
|
||||||
|
*ptr = (*ptr & ~0xff) | (val & 0xff);
|
||||||
|
return;
|
||||||
|
case R_RISCV_SET16:
|
||||||
|
write16le(ptr, val);
|
||||||
|
return;
|
||||||
|
case R_RISCV_SUB6:
|
||||||
|
*ptr = (*ptr & ~0x3f) | ((*ptr - val) & 0x3f);
|
||||||
|
return;
|
||||||
|
case R_RISCV_32_PCREL:
|
||||||
|
if (s1->output_type & TCC_OUTPUT_DYN) {
|
||||||
|
/* DLL relocation */
|
||||||
|
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
|
||||||
|
if (esym_index) {
|
||||||
|
qrel->r_offset = rel->r_offset;
|
||||||
|
qrel->r_info = ELFW(R_INFO)(esym_index, R_RISCV_32_PCREL);
|
||||||
|
/* Use sign extension! */
|
||||||
|
qrel->r_addend = (int)read32le(ptr) + rel->r_addend;
|
||||||
|
qrel++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
add32le(ptr, val - addr);
|
||||||
|
return;
|
||||||
|
case R_RISCV_SET_ULEB128:
|
||||||
|
case R_RISCV_SUB_ULEB128:
|
||||||
|
/* ignore. used in section .debug_loclists */
|
||||||
|
return;
|
||||||
|
case R_RISCV_COPY:
|
||||||
|
/* XXX */
|
||||||
|
return;
|
||||||
|
case R_RISCV_RELATIVE:
|
||||||
|
/* R_RISCV_RELATIVE value is already applied in R_RISCV_32/64
|
||||||
|
dynamic output paths, but we need this case for incoming
|
||||||
|
RELATIVE relocations from object files. */
|
||||||
|
return;
|
||||||
|
|
||||||
|
case R_RISCV_TPREL_HI20:
|
||||||
|
case R_RISCV_TPREL_LO12_I: {
|
||||||
|
addr_t tls_start = 0;
|
||||||
|
int64_t tp_offset;
|
||||||
|
int i;
|
||||||
|
for (i = 1; i < s1->nb_sections; i++) {
|
||||||
|
Section *s = s1->sections[i];
|
||||||
|
if (s->sh_flags & SHF_TLS && s->sh_size) {
|
||||||
|
if (!tls_start || s->sh_addr < tls_start)
|
||||||
|
tls_start = s->sh_addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tp_offset = val - tls_start;
|
||||||
|
if (type == R_RISCV_TPREL_HI20) {
|
||||||
|
off64 = (int64_t)(tp_offset + 0x800) >> 12;
|
||||||
|
if ((off64 + ((uint64_t)1 << 20)) >> 21)
|
||||||
|
tcc_error_noabort("R_RISCV_TPREL_HI20 relocation failed");
|
||||||
|
write32le(ptr, (read32le(ptr) & 0xfff)
|
||||||
|
| ((off64 & 0xfffff) << 12));
|
||||||
|
} else {
|
||||||
|
write32le(ptr, (read32le(ptr) & 0xfffff)
|
||||||
|
| (((tp_offset) & 0xfff) << 20));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "FIXME: handle reloc type %x at %x [%p] to %x\n",
|
||||||
|
type, (unsigned)addr, ptr, (unsigned)val);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
612
riscv64-tok.h
Normal file
612
riscv64-tok.h
Normal file
@ -0,0 +1,612 @@
|
|||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
/* WARNING: relative order of tokens is important. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The specifications are available under https://riscv.org/technical/specifications/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DEF_ASM_WITH_SUFFIX(x, y) \
|
||||||
|
DEF(TOK_ASM_ ## x ## _ ## y, #x "." #y)
|
||||||
|
|
||||||
|
#define DEF_ASM_WITH_SUFFIXES(x, y, z) \
|
||||||
|
DEF(TOK_ASM_ ## x ## _ ## y ## _ ## z, #x "." #y "." #z)
|
||||||
|
|
||||||
|
#define DEF_ASM_FENCE(x) \
|
||||||
|
DEF(TOK_ASM_ ## x ## _fence, #x)
|
||||||
|
|
||||||
|
/* register */
|
||||||
|
/* integer */
|
||||||
|
DEF_ASM(x0)
|
||||||
|
DEF_ASM(x1)
|
||||||
|
DEF_ASM(x2)
|
||||||
|
DEF_ASM(x3)
|
||||||
|
DEF_ASM(x4)
|
||||||
|
DEF_ASM(x5)
|
||||||
|
DEF_ASM(x6)
|
||||||
|
DEF_ASM(x7)
|
||||||
|
DEF_ASM(x8)
|
||||||
|
DEF_ASM(x9)
|
||||||
|
DEF_ASM(x10)
|
||||||
|
DEF_ASM(x11)
|
||||||
|
DEF_ASM(x12)
|
||||||
|
DEF_ASM(x13)
|
||||||
|
DEF_ASM(x14)
|
||||||
|
DEF_ASM(x15)
|
||||||
|
DEF_ASM(x16)
|
||||||
|
DEF_ASM(x17)
|
||||||
|
DEF_ASM(x18)
|
||||||
|
DEF_ASM(x19)
|
||||||
|
DEF_ASM(x20)
|
||||||
|
DEF_ASM(x21)
|
||||||
|
DEF_ASM(x22)
|
||||||
|
DEF_ASM(x23)
|
||||||
|
DEF_ASM(x24)
|
||||||
|
DEF_ASM(x25)
|
||||||
|
DEF_ASM(x26)
|
||||||
|
DEF_ASM(x27)
|
||||||
|
DEF_ASM(x28)
|
||||||
|
DEF_ASM(x29)
|
||||||
|
DEF_ASM(x30)
|
||||||
|
DEF_ASM(x31)
|
||||||
|
/* float */
|
||||||
|
DEF_ASM(f0)
|
||||||
|
DEF_ASM(f1)
|
||||||
|
DEF_ASM(f2)
|
||||||
|
DEF_ASM(f3)
|
||||||
|
DEF_ASM(f4)
|
||||||
|
DEF_ASM(f5)
|
||||||
|
DEF_ASM(f6)
|
||||||
|
DEF_ASM(f7)
|
||||||
|
DEF_ASM(f8)
|
||||||
|
DEF_ASM(f9)
|
||||||
|
DEF_ASM(f10)
|
||||||
|
DEF_ASM(f11)
|
||||||
|
DEF_ASM(f12)
|
||||||
|
DEF_ASM(f13)
|
||||||
|
DEF_ASM(f14)
|
||||||
|
DEF_ASM(f15)
|
||||||
|
DEF_ASM(f16)
|
||||||
|
DEF_ASM(f17)
|
||||||
|
DEF_ASM(f18)
|
||||||
|
DEF_ASM(f19)
|
||||||
|
DEF_ASM(f20)
|
||||||
|
DEF_ASM(f21)
|
||||||
|
DEF_ASM(f22)
|
||||||
|
DEF_ASM(f23)
|
||||||
|
DEF_ASM(f24)
|
||||||
|
DEF_ASM(f25)
|
||||||
|
DEF_ASM(f26)
|
||||||
|
DEF_ASM(f27)
|
||||||
|
DEF_ASM(f28)
|
||||||
|
DEF_ASM(f29)
|
||||||
|
DEF_ASM(f30)
|
||||||
|
DEF_ASM(f31)
|
||||||
|
|
||||||
|
/* register ABI mnemonics, refer to RISC-V ABI 1.0 */
|
||||||
|
/* integer */
|
||||||
|
DEF_ASM(zero)
|
||||||
|
DEF_ASM(ra)
|
||||||
|
DEF_ASM(sp)
|
||||||
|
DEF_ASM(gp)
|
||||||
|
DEF_ASM(tp)
|
||||||
|
DEF_ASM(t0)
|
||||||
|
DEF_ASM(t1)
|
||||||
|
DEF_ASM(t2)
|
||||||
|
DEF_ASM(s0)
|
||||||
|
DEF_ASM(s1)
|
||||||
|
DEF_ASM(a0)
|
||||||
|
DEF_ASM(a1)
|
||||||
|
DEF_ASM(a2)
|
||||||
|
DEF_ASM(a3)
|
||||||
|
DEF_ASM(a4)
|
||||||
|
DEF_ASM(a5)
|
||||||
|
DEF_ASM(a6)
|
||||||
|
DEF_ASM(a7)
|
||||||
|
DEF_ASM(s2)
|
||||||
|
DEF_ASM(s3)
|
||||||
|
DEF_ASM(s4)
|
||||||
|
DEF_ASM(s5)
|
||||||
|
DEF_ASM(s6)
|
||||||
|
DEF_ASM(s7)
|
||||||
|
DEF_ASM(s8)
|
||||||
|
DEF_ASM(s9)
|
||||||
|
DEF_ASM(s10)
|
||||||
|
DEF_ASM(s11)
|
||||||
|
DEF_ASM(t3)
|
||||||
|
DEF_ASM(t4)
|
||||||
|
DEF_ASM(t5)
|
||||||
|
DEF_ASM(t6)
|
||||||
|
/* float */
|
||||||
|
DEF_ASM(ft0)
|
||||||
|
DEF_ASM(ft1)
|
||||||
|
DEF_ASM(ft2)
|
||||||
|
DEF_ASM(ft3)
|
||||||
|
DEF_ASM(ft4)
|
||||||
|
DEF_ASM(ft5)
|
||||||
|
DEF_ASM(ft6)
|
||||||
|
DEF_ASM(ft7)
|
||||||
|
DEF_ASM(fs0)
|
||||||
|
DEF_ASM(fs1)
|
||||||
|
DEF_ASM(fa0)
|
||||||
|
DEF_ASM(fa1)
|
||||||
|
DEF_ASM(fa2)
|
||||||
|
DEF_ASM(fa3)
|
||||||
|
DEF_ASM(fa4)
|
||||||
|
DEF_ASM(fa5)
|
||||||
|
DEF_ASM(fa6)
|
||||||
|
DEF_ASM(fa7)
|
||||||
|
DEF_ASM(fs2)
|
||||||
|
DEF_ASM(fs3)
|
||||||
|
DEF_ASM(fs4)
|
||||||
|
DEF_ASM(fs5)
|
||||||
|
DEF_ASM(fs6)
|
||||||
|
DEF_ASM(fs7)
|
||||||
|
DEF_ASM(fs8)
|
||||||
|
DEF_ASM(fs9)
|
||||||
|
DEF_ASM(fs10)
|
||||||
|
DEF_ASM(fs11)
|
||||||
|
DEF_ASM(ft8)
|
||||||
|
DEF_ASM(ft9)
|
||||||
|
DEF_ASM(ft10)
|
||||||
|
DEF_ASM(ft11)
|
||||||
|
/* not in the ABI */
|
||||||
|
DEF_ASM(pc)
|
||||||
|
|
||||||
|
/* Loads */
|
||||||
|
|
||||||
|
DEF_ASM(lb)
|
||||||
|
DEF_ASM(lh)
|
||||||
|
DEF_ASM(lw)
|
||||||
|
DEF_ASM(lbu)
|
||||||
|
DEF_ASM(lhu)
|
||||||
|
/* RV64 */
|
||||||
|
DEF_ASM(ld)
|
||||||
|
DEF_ASM(lwu)
|
||||||
|
|
||||||
|
/* Stores */
|
||||||
|
|
||||||
|
DEF_ASM(sb)
|
||||||
|
DEF_ASM(sh)
|
||||||
|
DEF_ASM(sw)
|
||||||
|
/* RV64 */
|
||||||
|
DEF_ASM(sd)
|
||||||
|
|
||||||
|
/* Shifts */
|
||||||
|
|
||||||
|
DEF_ASM(sll)
|
||||||
|
DEF_ASM(srl)
|
||||||
|
DEF_ASM(sra)
|
||||||
|
/* RV64 */
|
||||||
|
DEF_ASM(slli)
|
||||||
|
DEF_ASM(srli)
|
||||||
|
DEF_ASM(sllw)
|
||||||
|
DEF_ASM(slliw)
|
||||||
|
DEF_ASM(srlw)
|
||||||
|
DEF_ASM(srliw)
|
||||||
|
DEF_ASM(srai)
|
||||||
|
DEF_ASM(sraw)
|
||||||
|
DEF_ASM(sraiw)
|
||||||
|
|
||||||
|
/* Arithmetic */
|
||||||
|
|
||||||
|
DEF_ASM(add)
|
||||||
|
DEF_ASM(addi)
|
||||||
|
DEF_ASM(sub)
|
||||||
|
DEF_ASM(lui)
|
||||||
|
DEF_ASM(auipc)
|
||||||
|
/* RV64 */
|
||||||
|
DEF_ASM(addw)
|
||||||
|
DEF_ASM(addiw)
|
||||||
|
DEF_ASM(subw)
|
||||||
|
|
||||||
|
/* Logical */
|
||||||
|
|
||||||
|
DEF_ASM(xor)
|
||||||
|
DEF_ASM(xori)
|
||||||
|
DEF_ASM(or)
|
||||||
|
DEF_ASM(ori)
|
||||||
|
DEF_ASM(and)
|
||||||
|
DEF_ASM(andi)
|
||||||
|
|
||||||
|
/* Compare */
|
||||||
|
|
||||||
|
DEF_ASM(slt)
|
||||||
|
DEF_ASM(slti)
|
||||||
|
DEF_ASM(sltu)
|
||||||
|
DEF_ASM(sltiu)
|
||||||
|
|
||||||
|
/* Branch */
|
||||||
|
|
||||||
|
DEF_ASM(beq)
|
||||||
|
DEF_ASM(bne)
|
||||||
|
DEF_ASM(blt)
|
||||||
|
DEF_ASM(bge)
|
||||||
|
DEF_ASM(bltu)
|
||||||
|
DEF_ASM(bgeu)
|
||||||
|
|
||||||
|
/* Jump */
|
||||||
|
|
||||||
|
DEF_ASM(jal)
|
||||||
|
DEF_ASM(jalr)
|
||||||
|
|
||||||
|
/* Sync */
|
||||||
|
|
||||||
|
DEF_ASM(fence)
|
||||||
|
/* Zifencei extension */
|
||||||
|
DEF_ASM_WITH_SUFFIX(fence, i)
|
||||||
|
|
||||||
|
/* System call */
|
||||||
|
|
||||||
|
/* used to be called scall and sbreak */
|
||||||
|
DEF_ASM(ecall)
|
||||||
|
DEF_ASM(ebreak)
|
||||||
|
|
||||||
|
/* Counters */
|
||||||
|
|
||||||
|
DEF_ASM(rdcycle)
|
||||||
|
DEF_ASM(rdcycleh)
|
||||||
|
DEF_ASM(rdtime)
|
||||||
|
DEF_ASM(rdtimeh)
|
||||||
|
DEF_ASM(rdinstret)
|
||||||
|
DEF_ASM(rdinstreth)
|
||||||
|
|
||||||
|
/* “M” Standard Extension for Integer Multiplication and Division, V2.0 */
|
||||||
|
DEF_ASM(mul)
|
||||||
|
DEF_ASM(mulh)
|
||||||
|
DEF_ASM(mulhsu)
|
||||||
|
DEF_ASM(mulhu)
|
||||||
|
DEF_ASM(div)
|
||||||
|
DEF_ASM(divu)
|
||||||
|
DEF_ASM(rem)
|
||||||
|
DEF_ASM(remu)
|
||||||
|
/* RV64 */
|
||||||
|
DEF_ASM(mulw)
|
||||||
|
DEF_ASM(divw)
|
||||||
|
DEF_ASM(divuw)
|
||||||
|
DEF_ASM(remw)
|
||||||
|
DEF_ASM(remuw)
|
||||||
|
|
||||||
|
/* "F"/"D" Extension for Single/Double-Precision Floating Point Arithmetic, V2.2 */
|
||||||
|
/* enough implemented for musl */
|
||||||
|
DEF_ASM_WITH_SUFFIX(fsgnj, s)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fsgnj, d)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fadd, s)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fadd, d)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fsub, s)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fsub, d)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fmul, s)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fmul, d)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fdiv, s)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fdiv, d)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fmadd, s)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fmadd, d)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fmax, s)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fmax, d)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fmin, s)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fmin, d)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fsqrt, s)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fsqrt, d)
|
||||||
|
|
||||||
|
/* F/D comparison and conversion (not needed by musl, added for completeness) */
|
||||||
|
DEF_ASM_WITH_SUFFIX(feq, s)
|
||||||
|
DEF_ASM_WITH_SUFFIX(feq, d)
|
||||||
|
DEF_ASM_WITH_SUFFIX(flt, s)
|
||||||
|
DEF_ASM_WITH_SUFFIX(flt, d)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fle, s)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fle, d)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fclass, s)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fclass, d)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(fcvt, w, s)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(fcvt, wu, s)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(fcvt, l, s)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(fcvt, lu, s)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(fcvt, s, w)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(fcvt, s, wu)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(fcvt, s, l)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(fcvt, s, lu)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(fcvt, w, d)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(fcvt, wu, d)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(fcvt, l, d)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(fcvt, lu, d)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(fcvt, d, w)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(fcvt, d, wu)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(fcvt, d, l)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(fcvt, d, lu)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(fcvt, s, d)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(fcvt, d, s)
|
||||||
|
|
||||||
|
/* "C" Extension for Compressed Instructions, V2.0 */
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, nop)
|
||||||
|
/* Loads */
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, li)
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, lw)
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, lwsp)
|
||||||
|
/* single float */
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, flw)
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, flwsp)
|
||||||
|
/* double float */
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, fld)
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, fldsp)
|
||||||
|
/* RV64 */
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, ld)
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, ldsp)
|
||||||
|
|
||||||
|
/* Stores */
|
||||||
|
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, sw)
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, sd)
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, swsp)
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, sdsp)
|
||||||
|
/* single float */
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, fsw)
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, fswsp)
|
||||||
|
/* double float */
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, fsd)
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, fsdsp)
|
||||||
|
|
||||||
|
/* Shifts */
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, slli)
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, srli)
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, srai)
|
||||||
|
|
||||||
|
/* Arithmetic */
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, add)
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, addi)
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, addi16sp)
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, addi4spn)
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, lui)
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, sub)
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, mv)
|
||||||
|
/* RV64 */
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, addw)
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, addiw)
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, subw)
|
||||||
|
|
||||||
|
/* Logical */
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, xor)
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, or)
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, and)
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, andi)
|
||||||
|
|
||||||
|
/* Branch */
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, beqz)
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, bnez)
|
||||||
|
|
||||||
|
/* Jump */
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, j)
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, jr)
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, jal)
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, jalr)
|
||||||
|
|
||||||
|
/* System call */
|
||||||
|
DEF_ASM_WITH_SUFFIX(c, ebreak)
|
||||||
|
|
||||||
|
/* XXX F Extension: Single-Precision Floating Point */
|
||||||
|
/* XXX D Extension: Double-Precision Floating Point */
|
||||||
|
/* from the spec: Tables 16.5–16.7 list the RVC instructions. */
|
||||||
|
|
||||||
|
/* “Zicsr”, Control and Status Register (CSR) Instructions, V2.0 */
|
||||||
|
DEF_ASM(csrrw)
|
||||||
|
DEF_ASM(csrrs)
|
||||||
|
DEF_ASM(csrrc)
|
||||||
|
DEF_ASM(csrrwi)
|
||||||
|
DEF_ASM(csrrsi)
|
||||||
|
DEF_ASM(csrrci)
|
||||||
|
/* registers */
|
||||||
|
DEF_ASM(cycle)
|
||||||
|
DEF_ASM(fcsr)
|
||||||
|
DEF_ASM(fflags)
|
||||||
|
DEF_ASM(frm)
|
||||||
|
DEF_ASM(instret)
|
||||||
|
DEF_ASM(time)
|
||||||
|
/* RV32I-only */
|
||||||
|
DEF_ASM(cycleh)
|
||||||
|
DEF_ASM(instreth)
|
||||||
|
DEF_ASM(timeh)
|
||||||
|
/* pseudo */
|
||||||
|
DEF_ASM(csrc)
|
||||||
|
DEF_ASM(csrci)
|
||||||
|
DEF_ASM(csrr)
|
||||||
|
DEF_ASM(csrs)
|
||||||
|
DEF_ASM(csrsi)
|
||||||
|
DEF_ASM(csrw)
|
||||||
|
DEF_ASM(csrwi)
|
||||||
|
DEF_ASM(frcsr)
|
||||||
|
DEF_ASM(frflags)
|
||||||
|
DEF_ASM(frrm)
|
||||||
|
DEF_ASM(fscsr)
|
||||||
|
DEF_ASM(fsflags)
|
||||||
|
DEF_ASM(fsrm)
|
||||||
|
|
||||||
|
/* Privileged Instructions */
|
||||||
|
|
||||||
|
DEF_ASM(mrts)
|
||||||
|
DEF_ASM(mrth)
|
||||||
|
DEF_ASM(hrts)
|
||||||
|
DEF_ASM(wfi)
|
||||||
|
|
||||||
|
/* pseudoinstructions */
|
||||||
|
DEF_ASM(beqz)
|
||||||
|
DEF_ASM(bgez)
|
||||||
|
DEF_ASM(bgt)
|
||||||
|
DEF_ASM(bgtu)
|
||||||
|
DEF_ASM(bgtz)
|
||||||
|
DEF_ASM(ble)
|
||||||
|
DEF_ASM(bleu)
|
||||||
|
DEF_ASM(blez)
|
||||||
|
DEF_ASM(bltz)
|
||||||
|
DEF_ASM(bnez)
|
||||||
|
DEF_ASM(call)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fabs, d)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fabs, s)
|
||||||
|
DEF_ASM(fld)
|
||||||
|
DEF_ASM(flw)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fmv, d)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fmv, s)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fneg, d)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fneg, s)
|
||||||
|
DEF_ASM(fsd)
|
||||||
|
DEF_ASM(fsw)
|
||||||
|
DEF_ASM(j)
|
||||||
|
DEF_ASM(jump)
|
||||||
|
DEF_ASM(jr)
|
||||||
|
DEF_ASM(la)
|
||||||
|
DEF_ASM(li)
|
||||||
|
DEF_ASM(lla)
|
||||||
|
DEF_ASM(mv)
|
||||||
|
DEF_ASM(neg)
|
||||||
|
DEF_ASM(negw)
|
||||||
|
DEF_ASM(nop)
|
||||||
|
DEF_ASM(not)
|
||||||
|
DEF_ASM(ret)
|
||||||
|
DEF_ASM(seqz)
|
||||||
|
DEF_ASM_WITH_SUFFIX(sext, w)
|
||||||
|
DEF_ASM(sgtz)
|
||||||
|
DEF_ASM(sltz)
|
||||||
|
DEF_ASM(snez)
|
||||||
|
DEF_ASM(tail)
|
||||||
|
|
||||||
|
/* Possible values for .option directive */
|
||||||
|
DEF_ASM(arch)
|
||||||
|
DEF_ASM(rvc)
|
||||||
|
DEF_ASM(norvc)
|
||||||
|
DEF_ASM(pic)
|
||||||
|
DEF_ASM(nopic)
|
||||||
|
DEF_ASM(relax)
|
||||||
|
DEF_ASM(norelax)
|
||||||
|
DEF_ASM(push)
|
||||||
|
DEF_ASM(pop)
|
||||||
|
|
||||||
|
/* “A” Standard Extension for Atomic Instructions, Version 2.1 */
|
||||||
|
/* XXX: Atomic memory operations */
|
||||||
|
DEF_ASM_WITH_SUFFIX(lr, w)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(lr, w, aq)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(lr, w, rl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(lr, w, aqrl)
|
||||||
|
|
||||||
|
DEF_ASM_WITH_SUFFIX(lr, d)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(lr, d, aq)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(lr, d, rl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(lr, d, aqrl)
|
||||||
|
|
||||||
|
|
||||||
|
DEF_ASM_WITH_SUFFIX(sc, w)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(sc, w, aq)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(sc, w, rl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(sc, w, aqrl)
|
||||||
|
|
||||||
|
DEF_ASM_WITH_SUFFIX(sc, d)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(sc, d, aq)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(sc, d, rl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(sc, d, aqrl)
|
||||||
|
|
||||||
|
/* "A" Extension for Atomic Operations, V2.1 (base, no aq/rl suffixes) */
|
||||||
|
DEF_ASM_WITH_SUFFIX(amoadd, w)
|
||||||
|
DEF_ASM_WITH_SUFFIX(amoadd, d)
|
||||||
|
DEF_ASM_WITH_SUFFIX(amoswap, w)
|
||||||
|
DEF_ASM_WITH_SUFFIX(amoswap, d)
|
||||||
|
DEF_ASM_WITH_SUFFIX(amoand, w)
|
||||||
|
DEF_ASM_WITH_SUFFIX(amoand, d)
|
||||||
|
DEF_ASM_WITH_SUFFIX(amoor, w)
|
||||||
|
DEF_ASM_WITH_SUFFIX(amoor, d)
|
||||||
|
DEF_ASM_WITH_SUFFIX(amoxor, w)
|
||||||
|
DEF_ASM_WITH_SUFFIX(amoxor, d)
|
||||||
|
DEF_ASM_WITH_SUFFIX(amomax, w)
|
||||||
|
DEF_ASM_WITH_SUFFIX(amomax, d)
|
||||||
|
DEF_ASM_WITH_SUFFIX(amomaxu, w)
|
||||||
|
DEF_ASM_WITH_SUFFIX(amomaxu, d)
|
||||||
|
DEF_ASM_WITH_SUFFIX(amomin, w)
|
||||||
|
DEF_ASM_WITH_SUFFIX(amomin, d)
|
||||||
|
DEF_ASM_WITH_SUFFIX(amominu, w)
|
||||||
|
DEF_ASM_WITH_SUFFIX(amominu, d)
|
||||||
|
|
||||||
|
|
||||||
|
/* AMO aq/rl ordering suffixes */
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoadd, w, aq)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoadd, w, rl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoadd, w, aqrl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoadd, d, aq)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoadd, d, rl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoadd, d, aqrl)
|
||||||
|
/* Complete AMO aq/rl ordering suffixes (all ops) */
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoswap, w, aq)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoswap, w, rl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoswap, w, aqrl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoswap, d, aq)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoswap, d, rl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoswap, d, aqrl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoand, w, aq)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoand, w, rl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoand, w, aqrl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoand, d, aq)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoand, d, rl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoand, d, aqrl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoor, w, aq)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoor, w, rl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoor, w, aqrl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoor, d, aq)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoor, d, rl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoor, d, aqrl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoxor, w, aq)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoxor, w, rl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoxor, w, aqrl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoxor, d, aq)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoxor, d, rl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amoxor, d, aqrl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amomax, w, aq)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amomax, w, rl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amomax, w, aqrl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amomax, d, aq)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amomax, d, rl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amomax, d, aqrl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amomaxu, w, aq)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amomaxu, w, rl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amomaxu, w, aqrl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amomaxu, d, aq)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amomaxu, d, rl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amomaxu, d, aqrl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amomin, w, aq)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amomin, w, rl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amomin, w, aqrl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amomin, d, aq)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amomin, d, rl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amomin, d, aqrl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amominu, w, aq)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amominu, w, rl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amominu, w, aqrl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amominu, d, aq)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amominu, d, rl)
|
||||||
|
DEF_ASM_WITH_SUFFIXES(amominu, d, aqrl)
|
||||||
|
|
||||||
|
|
||||||
|
/* rounding mode keywords (used as fcvt operand: fcvt.w.s rd, rs1, rtz) */
|
||||||
|
DEF_ASM(rne)
|
||||||
|
DEF_ASM(rtz)
|
||||||
|
DEF_ASM(rdn)
|
||||||
|
DEF_ASM(rup)
|
||||||
|
DEF_ASM(rmm)
|
||||||
|
|
||||||
|
/* `fence` arguments */
|
||||||
|
/* NOTE: Order is important */
|
||||||
|
DEF_ASM_FENCE(w)
|
||||||
|
DEF_ASM_FENCE(r)
|
||||||
|
DEF_ASM_FENCE(rw)
|
||||||
|
|
||||||
|
DEF_ASM_FENCE(o)
|
||||||
|
DEF_ASM_FENCE(ow)
|
||||||
|
DEF_ASM_FENCE(or)
|
||||||
|
DEF_ASM_FENCE(orw)
|
||||||
|
|
||||||
|
DEF_ASM_FENCE(i)
|
||||||
|
DEF_ASM_FENCE(iw)
|
||||||
|
DEF_ASM_FENCE(ir)
|
||||||
|
DEF_ASM_FENCE(irw)
|
||||||
|
|
||||||
|
DEF_ASM_FENCE(io)
|
||||||
|
DEF_ASM_FENCE(iow)
|
||||||
|
DEF_ASM_FENCE(ior)
|
||||||
|
DEF_ASM_FENCE(iorw)
|
||||||
|
|
||||||
|
#undef DEF_ASM_FENCE
|
||||||
|
#undef DEF_ASM_WITH_SUFFIX
|
||||||
|
#undef DEF_ASM_WITH_SUFFIXES
|
||||||
214
tcc-doc.texi
214
tcc-doc.texi
@ -83,7 +83,7 @@ usage: tcc [options] [@var{infile1} @var{infile2}@dots{}] [@option{-run} @var{in
|
|||||||
|
|
||||||
@noindent
|
@noindent
|
||||||
@c man begin DESCRIPTION
|
@c man begin DESCRIPTION
|
||||||
TCC options are a very much like gcc options. The main difference is that TCC
|
TCC options are very much like gcc options. The main difference is that TCC
|
||||||
can also execute directly the resulting program and give it runtime
|
can also execute directly the resulting program and give it runtime
|
||||||
arguments.
|
arguments.
|
||||||
|
|
||||||
@ -199,6 +199,16 @@ include paths are: @file{/usr/local/include}, @file{/usr/include}
|
|||||||
and @file{PREFIX/lib/tcc/include}. (@file{PREFIX} is usually
|
and @file{PREFIX/lib/tcc/include}. (@file{PREFIX} is usually
|
||||||
@file{/usr} or @file{/usr/local}).
|
@file{/usr} or @file{/usr/local}).
|
||||||
|
|
||||||
|
@item -isystem dir
|
||||||
|
Specify a system include path to be added to the defaults.
|
||||||
|
|
||||||
|
@item -nostdinc
|
||||||
|
Do not search the default system include paths; only search include paths
|
||||||
|
provided on the command line.
|
||||||
|
|
||||||
|
@item -include file
|
||||||
|
Include @option{file} above each input file.
|
||||||
|
|
||||||
@item -Dsym[=val]
|
@item -Dsym[=val]
|
||||||
Define preprocessor symbol @samp{sym} to
|
Define preprocessor symbol @samp{sym} to
|
||||||
val. If val is not present, its value is @samp{1}. Function-like macros can
|
val. If val is not present, its value is @samp{1}. Function-like macros can
|
||||||
@ -210,6 +220,18 @@ Undefine preprocessor symbol @samp{sym}.
|
|||||||
@item -E
|
@item -E
|
||||||
Preprocess only, to stdout or file (with -o).
|
Preprocess only, to stdout or file (with -o).
|
||||||
|
|
||||||
|
@item -P
|
||||||
|
Do not output @code{#line} directives.
|
||||||
|
|
||||||
|
@item -P1
|
||||||
|
Output alternative @code{#line} directives.
|
||||||
|
|
||||||
|
@item -dD, -dM
|
||||||
|
Output @code{#define} directives.
|
||||||
|
|
||||||
|
@item -Wp,-opt
|
||||||
|
Same as @option{-opt}.
|
||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
Compilation flags:
|
Compilation flags:
|
||||||
@ -238,6 +260,19 @@ behaves like an unnamed one.
|
|||||||
@item -fdollars-in-identifiers
|
@item -fdollars-in-identifiers
|
||||||
Allow dollar signs in identifiers
|
Allow dollar signs in identifiers
|
||||||
|
|
||||||
|
@item -freverse-funcargs
|
||||||
|
Evaluate function arguments right to left.
|
||||||
|
|
||||||
|
@item -fgnu89-inline
|
||||||
|
@code{extern inline} is like @code{static inline}.
|
||||||
|
|
||||||
|
@item -fasynchronous-unwind-tables
|
||||||
|
Create eh_frame section [on]
|
||||||
|
|
||||||
|
@item -ftest-coverage
|
||||||
|
Create code coverage code. After running the resulting code an executable.tcov
|
||||||
|
or sofile.tcov file is generated with code coverage.
|
||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
Warning options:
|
Warning options:
|
||||||
@ -253,7 +288,10 @@ Note: each of the following warning options has a negative form beginning with
|
|||||||
|
|
||||||
@table @option
|
@table @option
|
||||||
@item -Wimplicit-function-declaration
|
@item -Wimplicit-function-declaration
|
||||||
Warn about implicit function declaration.
|
Warn about implicit function declaration (missing prototype).
|
||||||
|
|
||||||
|
@item -Wdiscarded-qualifiers
|
||||||
|
Warn when const is dropped.
|
||||||
|
|
||||||
@item -Wunsupported
|
@item -Wunsupported
|
||||||
Warn about unsupported GCC features that are ignored by TCC.
|
Warn about unsupported GCC features that are ignored by TCC.
|
||||||
@ -263,11 +301,13 @@ Make string constants be of type @code{const char *} instead of @code{char
|
|||||||
*}.
|
*}.
|
||||||
|
|
||||||
@item -Werror
|
@item -Werror
|
||||||
Abort compilation if warnings are issued.
|
Abort compilation if a warning is issued. Can be given an option to enable
|
||||||
|
the specified warning and turn it into an error, for example
|
||||||
|
@option{-Werror=unsupported}.
|
||||||
|
|
||||||
@item -Wall
|
@item -Wall
|
||||||
Activate all warnings, except @option{-Werror}, @option{-Wunusupported} and
|
Activate some useful warnings (@option{-Wimplicit-function-declaration},
|
||||||
@option{-Wwrite-strings}.
|
@option{-Wdiscard-qualifiers}).
|
||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@ -304,9 +344,22 @@ opened with @code{dlopen()} needs to access executable symbols.
|
|||||||
@item -r
|
@item -r
|
||||||
Generate an object file combining all input files.
|
Generate an object file combining all input files.
|
||||||
|
|
||||||
|
@item -nostdlib
|
||||||
|
Don't implicitly link with libc, the C runtime files, and libtcc1.
|
||||||
|
|
||||||
|
@item -Wl,-nostdlib
|
||||||
|
Don't search the default paths for libraries (@file{/usr/local/lib},
|
||||||
|
@file{/usr/lib} and @file{/lib}). Only the paths specified with @option{-L}
|
||||||
|
and @env{LIBRARY_PATH} are searched.
|
||||||
|
|
||||||
@item -Wl,-rpath=path
|
@item -Wl,-rpath=path
|
||||||
Put custom search path for dynamic libraries into executable.
|
Put custom search path for dynamic libraries into executable.
|
||||||
|
|
||||||
|
@item -Wl,-Ipath
|
||||||
|
@item -Wl,--dynamic-linker=path
|
||||||
|
Set the ELF interpreter (dynamic linker). This defaults to the value of the
|
||||||
|
environment variable @env{LD_SO} if set, or a compiled-in default.
|
||||||
|
|
||||||
@item -Wl,--enable-new-dtags
|
@item -Wl,--enable-new-dtags
|
||||||
When putting a custom search path for dynamic libraries into the executable,
|
When putting a custom search path for dynamic libraries into the executable,
|
||||||
create the new ELF dynamic tag DT_RUNPATH instead of the old legacy DT_RPATH.
|
create the new ELF dynamic tag DT_RUNPATH instead of the old legacy DT_RPATH.
|
||||||
@ -322,12 +375,26 @@ Binary image (only for executable output)
|
|||||||
COFF output format (only for executable output for TMS320C67xx target)
|
COFF output format (only for executable output for TMS320C67xx target)
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
|
@item -Wl,--export-all-symbols
|
||||||
|
@item -Wl,--export-dynamic
|
||||||
|
Export global symbols to the dynamic linker. It is useful when a library
|
||||||
|
opened with @code{dlopen()} needs to access executable symbols.
|
||||||
|
|
||||||
@item -Wl,-subsystem=console/gui/wince/...
|
@item -Wl,-subsystem=console/gui/wince/...
|
||||||
Set type for PE (Windows) executables.
|
Set type for PE (Windows) executables.
|
||||||
|
|
||||||
@item -Wl,-[Ttext=# | section-alignment=# | file-alignment=# | image-base=# | stack=#]
|
@item -Wl,-[Ttext=# | section-alignment=# | file-alignment=# | image-base=# | stack=#]
|
||||||
Modify executable layout.
|
Modify executable layout.
|
||||||
|
|
||||||
|
@item -Wl,-[dynamicbase | nxcompat | high-entropy-va | tsaware]
|
||||||
|
@item -Wl,-[no-dynamicbase | no-nxcompat | no-high-entropy-va | no-tsaware]
|
||||||
|
@item -Wl,-[disable-dynamicbase | disable-nxcompat | disable-high-entropy-va | disable-tsaware]
|
||||||
|
Set or clear PE (Windows) executable header hardening flags. The
|
||||||
|
@option{-Wl,-high-entropy-va} option is supported on x86-64 and ARM64 PE
|
||||||
|
targets and implies @option{-Wl,-dynamicbase}. Clearing dynamicbase also
|
||||||
|
clears high-entropy-va. When @option{-Wl,-dynamicbase} is used for an
|
||||||
|
executable, TCC also enables base relocation emission for Windows ASLR.
|
||||||
|
|
||||||
@item -Wl,-Bsymbolic
|
@item -Wl,-Bsymbolic
|
||||||
Set DT_SYMBOLIC tag.
|
Set DT_SYMBOLIC tag.
|
||||||
|
|
||||||
@ -340,33 +407,63 @@ Debugger options:
|
|||||||
|
|
||||||
@table @option
|
@table @option
|
||||||
@item -g
|
@item -g
|
||||||
Generate run time debug information so that you get clear run time
|
Generate run time stab debug information so that you get clear run time
|
||||||
error messages: @code{ test.c:68: in function 'test5()': dereferencing
|
error messages: @code{ test.c:68: in function 'test5()': dereferencing
|
||||||
invalid pointer} instead of the laconic @code{Segmentation
|
invalid pointer} instead of the laconic @code{Segmentation
|
||||||
fault}.
|
fault}.
|
||||||
|
|
||||||
|
@item -gdwarf[-x]
|
||||||
|
Generate run time dwarf debug information instead of stab debug information.
|
||||||
|
|
||||||
@item -b
|
@item -b
|
||||||
Generate additional support code to check
|
Generate additional support code to check memory allocations and array/pointer
|
||||||
memory allocations and array/pointer bounds. @option{-g} is implied. Note
|
bounds (@pxref{Bounds}). @option{-g} is implied.
|
||||||
that the generated code is slower and bigger in this case.
|
|
||||||
|
|
||||||
Note: @option{-b} is only available on i386 when using libtcc for the moment.
|
@item -bt[N]
|
||||||
|
Display N callers in stack traces. This is useful with @option{-g} or @option{-b}.
|
||||||
|
When activated, @code{__TCC_BACKTRACE__} is defined.
|
||||||
|
|
||||||
@item -bt N
|
With executables, additional support for stack traces is included. A function
|
||||||
Display N callers in stack traces. This is useful with @option{-g} or
|
@code{ int tcc_backtrace(const char *fmt, ...); }
|
||||||
@option{-b}.
|
is provided to trigger a stack trace with a message on demand.
|
||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
Misc options:
|
Misc options:
|
||||||
|
|
||||||
@table @option
|
@table @option
|
||||||
|
|
||||||
|
@item -std=version
|
||||||
|
Define @code{__STDC_VERSION__}: @code{201112} if @option{version} is c11 or
|
||||||
|
gnu11; @code{199901} otherwise.
|
||||||
|
|
||||||
|
@item -x[c|a|b|n]
|
||||||
|
Specify content of next input file: respectively C, assembly, binary, or none.
|
||||||
|
|
||||||
|
@item -O[n]
|
||||||
|
Same as @option{-D__OPTIMIZE__} except for -O0.
|
||||||
|
|
||||||
|
@item -pthread
|
||||||
|
Preprocess with @option{-D_REENTRANT}, link with @option{-lpthread}.
|
||||||
|
|
||||||
|
@item -M
|
||||||
|
Just output makefile fragment with dependencies
|
||||||
|
|
||||||
|
@item -MM
|
||||||
|
Like -M except mention only user header files, not system header files.
|
||||||
|
|
||||||
@item -MD
|
@item -MD
|
||||||
Generate makefile fragment with dependencies.
|
Generate makefile fragment with dependencies.
|
||||||
|
|
||||||
|
@item -MMD
|
||||||
|
Like -MD except mention only user header files, not system header files.
|
||||||
|
|
||||||
@item -MF depfile
|
@item -MF depfile
|
||||||
Use @file{depfile} as output for -MD.
|
Use @file{depfile} as output for -MD.
|
||||||
|
|
||||||
|
@item -MP
|
||||||
|
Mention all dependencies as targets too.
|
||||||
|
|
||||||
@item -print-search-dirs
|
@item -print-search-dirs
|
||||||
Print the configured installation directory and a list of library
|
Print the configured installation directory and a list of library
|
||||||
and include directories tcc will search.
|
and include directories tcc will search.
|
||||||
@ -374,6 +471,9 @@ and include directories tcc will search.
|
|||||||
@item -dumpversion
|
@item -dumpversion
|
||||||
Print version.
|
Print version.
|
||||||
|
|
||||||
|
@item -dt
|
||||||
|
With @option{-run}/@option{-E}: auto-define 'test_...' macros
|
||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
Target specific options:
|
Target specific options:
|
||||||
@ -394,8 +494,7 @@ Pass command line to the i386/x86_64 cross compiler.
|
|||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
Note: GCC options @option{-Ox}, @option{-fx} and @option{-mx} are
|
Note: GCC options @option{-fx} and @option{-mx} are ignored.
|
||||||
ignored.
|
|
||||||
@c man end
|
@c man end
|
||||||
|
|
||||||
@c man begin ENVIRONMENT
|
@c man begin ENVIRONMENT
|
||||||
@ -543,6 +642,7 @@ instead of
|
|||||||
@cindex stdcall attribute
|
@cindex stdcall attribute
|
||||||
@cindex regparm attribute
|
@cindex regparm attribute
|
||||||
@cindex dllexport attribute
|
@cindex dllexport attribute
|
||||||
|
@cindex nodecorate attribute
|
||||||
|
|
||||||
@item The keyword @code{__attribute__} is handled to specify variable or
|
@item The keyword @code{__attribute__} is handled to specify variable or
|
||||||
function attributes. The following attributes are supported:
|
function attributes. The following attributes are supported:
|
||||||
@ -570,6 +670,8 @@ registers @code{%eax}, @code{%edx} and @code{%ecx}.
|
|||||||
|
|
||||||
@item @code{dllexport}: export function from dll/executable (win32 only)
|
@item @code{dllexport}: export function from dll/executable (win32 only)
|
||||||
|
|
||||||
|
@item @code{nodecorate}: do not apply any decorations that would otherwise be applied when exporting function from dll/executable (win32 only)
|
||||||
|
|
||||||
@end itemize
|
@end itemize
|
||||||
|
|
||||||
Here are some examples:
|
Here are some examples:
|
||||||
@ -660,8 +762,6 @@ are supported.
|
|||||||
@item Binary digits can be entered (@code{0b101} instead of
|
@item Binary digits can be entered (@code{0b101} instead of
|
||||||
@code{5}).
|
@code{5}).
|
||||||
|
|
||||||
@item @code{__BOUNDS_CHECKING_ON} is defined if bound checking is activated.
|
|
||||||
|
|
||||||
@end itemize
|
@end itemize
|
||||||
|
|
||||||
@node asm
|
@node asm
|
||||||
@ -855,16 +955,7 @@ GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a )
|
|||||||
@cindex bound checks
|
@cindex bound checks
|
||||||
@cindex memory checks
|
@cindex memory checks
|
||||||
|
|
||||||
This feature is activated with the @option{-b} (@pxref{Invoke}).
|
This feature is activated with the @option{-b} option (@pxref{Invoke}).
|
||||||
|
|
||||||
Note that pointer size is @emph{unchanged} and that code generated
|
|
||||||
with bound checks is @emph{fully compatible} with unchecked
|
|
||||||
code. When a pointer comes from unchecked code, it is assumed to be
|
|
||||||
valid. Even very obscure C code with casts should work correctly.
|
|
||||||
|
|
||||||
For more information about the ideas behind this method, see
|
|
||||||
@url{http://www.doc.ic.ac.uk/~phjk/BoundsChecking.html}.
|
|
||||||
|
|
||||||
Here are some examples of caught errors:
|
Here are some examples of caught errors:
|
||||||
|
|
||||||
@table @asis
|
@table @asis
|
||||||
@ -893,7 +984,7 @@ Here are some examples of caught errors:
|
|||||||
int *tab;
|
int *tab;
|
||||||
tab = malloc(20 * sizeof(int));
|
tab = malloc(20 * sizeof(int));
|
||||||
for(i=0;i<21;i++) @{
|
for(i=0;i<21;i++) @{
|
||||||
sum += tab4[i];
|
sum += tab[i];
|
||||||
@}
|
@}
|
||||||
free(tab);
|
free(tab);
|
||||||
@}
|
@}
|
||||||
@ -906,7 +997,7 @@ Here are some examples of caught errors:
|
|||||||
tab = malloc(20 * sizeof(int));
|
tab = malloc(20 * sizeof(int));
|
||||||
free(tab);
|
free(tab);
|
||||||
for(i=0;i<20;i++) @{
|
for(i=0;i<20;i++) @{
|
||||||
sum += tab4[i];
|
sum += tab[i];
|
||||||
@}
|
@}
|
||||||
@}
|
@}
|
||||||
@end example
|
@end example
|
||||||
@ -920,9 +1011,68 @@ Here are some examples of caught errors:
|
|||||||
free(tab);
|
free(tab);
|
||||||
@}
|
@}
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
|
TCC defines @code{__TCC_BCHECK__} if activated.
|
||||||
|
|
||||||
|
There are five environment variables that can be used to control the behavior:
|
||||||
|
@itemize
|
||||||
|
@item TCC_BOUNDS_WARN_POINTER_ADD
|
||||||
|
- Print warning when pointer add creates an illegal pointer.
|
||||||
|
@item TCC_BOUNDS_PRINT_CALLS
|
||||||
|
- Print bound checking calls. Can be used for debugging.
|
||||||
|
@item TCC_BOUNDS_PRINT_HEAP
|
||||||
|
- Print heap objects that are not freed at exit of program.
|
||||||
|
@item TCC_BOUNDS_PRINT_STATISTIC
|
||||||
|
- Print statistic information at exit of program.
|
||||||
|
@item TCC_BOUNDS_NEVER_FATAL
|
||||||
|
- Try to continue in case of a bound checking error.
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
Also, a function @code{__bounds_checking(x)} can be used to turn off/on bounds
|
||||||
|
checking from usercode (see below).
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
@itemize
|
||||||
|
@item Only available on i386 (linux and windows), x86_64 (linux and windows),
|
||||||
|
arm, arm64 and riscv64 for the moment.
|
||||||
|
@item The generated code is slower and bigger.
|
||||||
|
@item The bound checking code is not included in shared libraries. The main
|
||||||
|
executable should always be compiled with the @option{-b}.
|
||||||
|
@item Pointer size is @emph{unchanged} and code generated with bound checks is
|
||||||
|
@emph{fully compatible} with unchecked code. When a pointer comes from
|
||||||
|
unchecked code, it is assumed to be valid. Even very obscure C code with
|
||||||
|
casts should work correctly.
|
||||||
|
@item Signal handlers are not compatible with bounds checking. The
|
||||||
|
bounds checking code disables checking in signal/sigaction handlers.
|
||||||
|
The fork() function call in a multi threaded application is also a problem.
|
||||||
|
The bound checking code fixes this for the child process.
|
||||||
|
@item The reason that signals and fork have problems is that we use locking
|
||||||
|
inside the bounds checking code.
|
||||||
|
Inside a signal handler we can not use locks. Also in a multi threaded
|
||||||
|
application after a fork the child process can have the lock set
|
||||||
|
by another thread.
|
||||||
|
@item The BOUNDS_CHECKING_OFF and BOUNDS_CHECKING_ON can also be used to
|
||||||
|
disable bounds checking for some code.
|
||||||
|
@item The __bounds_checking call adds a value to a thread local value.
|
||||||
|
The value starts at 0. If the value is not 0 the code is not checked
|
||||||
|
for bounds checking errors.
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
@example
|
||||||
|
#ifdef __TCC_BCHECK__
|
||||||
|
extern void __bounds_checking (int x);
|
||||||
|
# define BOUNDS_CHECKING_OFF __bounds_checking(1)
|
||||||
|
# define BOUNDS_CHECKING_ON __bounds_checking(-1)
|
||||||
|
#else
|
||||||
|
# define BOUNDS_CHECKING_OFF
|
||||||
|
# define BOUNDS_CHECKING_ON
|
||||||
|
#endif
|
||||||
|
@end example
|
||||||
|
|
||||||
|
For more information about the ideas behind this method, see
|
||||||
|
@url{http://www.doc.ic.ac.uk/~phjk/BoundsChecking.html}.
|
||||||
|
|
||||||
@node Libtcc
|
@node Libtcc
|
||||||
@chapter The @code{libtcc} library
|
@chapter The @code{libtcc} library
|
||||||
|
|
||||||
@ -1294,10 +1444,6 @@ floating point to integer conversion.
|
|||||||
@item gen_cvt_ftof()
|
@item gen_cvt_ftof()
|
||||||
floating point to floating point of different size conversion.
|
floating point to floating point of different size conversion.
|
||||||
|
|
||||||
@item gen_bounded_ptr_add()
|
|
||||||
@item gen_bounded_ptr_deref()
|
|
||||||
are only used for bounds checking.
|
|
||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@section Optimizations done
|
@section Optimizations done
|
||||||
|
|||||||
289
tcc.c
289
tcc.c
@ -18,6 +18,10 @@
|
|||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef ONE_SOURCE
|
||||||
|
# define ONE_SOURCE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
#if ONE_SOURCE
|
#if ONE_SOURCE
|
||||||
# include "libtcc.c"
|
# include "libtcc.c"
|
||||||
@ -27,53 +31,64 @@
|
|||||||
static const char help[] =
|
static const char help[] =
|
||||||
"Tiny C Compiler "TCC_VERSION" - Copyright (C) 2001-2006 Fabrice Bellard\n"
|
"Tiny C Compiler "TCC_VERSION" - Copyright (C) 2001-2006 Fabrice Bellard\n"
|
||||||
"Usage: tcc [options...] [-o outfile] [-c] infile(s)...\n"
|
"Usage: tcc [options...] [-o outfile] [-c] infile(s)...\n"
|
||||||
" tcc [options...] -run infile [arguments...]\n"
|
" tcc [options...] -run infile (or --) [arguments...]\n"
|
||||||
"General options:\n"
|
"General options:\n"
|
||||||
" -c compile only - generate an object file\n"
|
" -c compile only - generate an object file\n"
|
||||||
" -o outfile set output filename\n"
|
" -o outfile set output filename\n"
|
||||||
" -run run compiled source\n"
|
" -run run compiled source\n"
|
||||||
" -fflag set or reset (with 'no-' prefix) 'flag' (see tcc -hh)\n"
|
" -fflag set or reset (with 'no-' prefix) 'flag' (see tcc -hh)\n"
|
||||||
" -Wwarning set or reset (with 'no-' prefix) 'warning' (see tcc -hh)\n"
|
" -Wwarning set or reset (with 'no-' prefix) 'warning' (see tcc -hh)\n"
|
||||||
" -w disable all warnings\n"
|
" -w disable all warnings\n"
|
||||||
" -v -vv show version, show search paths or loaded files\n"
|
" -v --version show version\n"
|
||||||
" -h -hh show this, show more help\n"
|
" -vv show search paths or loaded files\n"
|
||||||
" -bench show compilation statistics\n"
|
" -h -hh show this, show more help\n"
|
||||||
" - use stdin pipe as infile\n"
|
" -bench show compilation statistics\n"
|
||||||
" @listfile read arguments from listfile\n"
|
" - use stdin pipe as infile\n"
|
||||||
|
" @listfile read arguments from listfile\n"
|
||||||
"Preprocessor options:\n"
|
"Preprocessor options:\n"
|
||||||
" -Idir add include path 'dir'\n"
|
" -Idir add include path 'dir'\n"
|
||||||
" -Dsym[=val] define 'sym' with value 'val'\n"
|
" -Dsym[=val] define 'sym' with value 'val'\n"
|
||||||
" -Usym undefine 'sym'\n"
|
" -Usym undefine 'sym'\n"
|
||||||
" -E preprocess only\n"
|
" -E preprocess only\n"
|
||||||
|
" -nostdinc do not use standard system include paths\n"
|
||||||
"Linker options:\n"
|
"Linker options:\n"
|
||||||
" -Ldir add library path 'dir'\n"
|
" -Ldir add library path 'dir'\n"
|
||||||
" -llib link with dynamic or static library 'lib'\n"
|
" -llib link with dynamic or static library 'lib'\n"
|
||||||
" -r generate (relocatable) object file\n"
|
" -nostdlib do not link with standard crt and libraries\n"
|
||||||
" -shared generate a shared library/dll\n"
|
" -r generate (relocatable) object file\n"
|
||||||
" -rdynamic export all global symbols to dynamic linker\n"
|
" -rdynamic export all global symbols to dynamic linker\n"
|
||||||
" -soname set name for shared library to be used at runtime\n"
|
" -shared generate a shared library/dll\n"
|
||||||
|
" -soname set name for shared library to be used at runtime\n"
|
||||||
" -Wl,-opt[=val] set linker option (see tcc -hh)\n"
|
" -Wl,-opt[=val] set linker option (see tcc -hh)\n"
|
||||||
"Debugger options:\n"
|
"Debugger options:\n"
|
||||||
" -g generate runtime debug info\n"
|
" -g generate stab runtime debug info\n"
|
||||||
|
" -gdwarf[-x] generate dwarf runtime debug info\n"
|
||||||
|
#ifdef TCC_TARGET_PE
|
||||||
|
" -g.pdb create .pdb debug database\n"
|
||||||
|
#endif
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
" -b compile with built-in memory and bounds checker (implies -g)\n"
|
" -b compile with built-in memory and bounds checker (implies -g)\n"
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_TCC_BACKTRACE
|
#ifdef CONFIG_TCC_BACKTRACE
|
||||||
" -bt N show N callers in stack traces\n"
|
" -bt[N] link with backtrace (stack dump) support [show max N callers]\n"
|
||||||
#endif
|
#endif
|
||||||
"Misc. options:\n"
|
"Misc. options:\n"
|
||||||
" -x[c|a|n] specify type of the next infile\n"
|
" -std=version define __STDC_VERSION__ according to version (c11/gnu11)\n"
|
||||||
" -nostdinc do not use standard system include paths\n"
|
" -x[c|a|b|n] specify type of the next infile (C,ASM,BIN,NONE)\n"
|
||||||
" -nostdlib do not link with standard crt and libraries\n"
|
" -Bdir set tcc's private include/library dir\n"
|
||||||
" -Bdir set tcc's private include/library dir\n"
|
" -M[M]D generate make dependency file [ignore system files]\n"
|
||||||
" -MD generate dependency file for make\n"
|
" -M[M] as above but no other output\n"
|
||||||
" -MF file specify dependency file name\n"
|
" -MF file specify dependency file name\n"
|
||||||
" -m32/64 defer to i386/x86_64 cross compiler\n"
|
#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
|
||||||
|
" -m32/64 defer to i386/x86_64 cross compiler\n"
|
||||||
|
#endif
|
||||||
"Tools:\n"
|
"Tools:\n"
|
||||||
" create library : tcc -ar [rcsv] lib.a files\n"
|
" create library : tcc -ar [crstvx] lib [files]\n"
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
" create def file : tcc -impdef lib.dll [-v] [-o lib.def]\n"
|
" create def file : tcc -impdef lib.dll [-v] [-o lib.def]\n"
|
||||||
#endif
|
#endif
|
||||||
|
"Discussion & bug reports:\n"
|
||||||
|
" https://lists.nongnu.org/mailman/listinfo/tinycc-devel\n"
|
||||||
;
|
;
|
||||||
|
|
||||||
static const char help2[] =
|
static const char help2[] =
|
||||||
@ -85,19 +100,22 @@ static const char help2[] =
|
|||||||
" -On same as -D__OPTIMIZE__ for n > 0\n"
|
" -On same as -D__OPTIMIZE__ for n > 0\n"
|
||||||
" -Wp,-opt same as -opt\n"
|
" -Wp,-opt same as -opt\n"
|
||||||
" -include file include 'file' above each input file\n"
|
" -include file include 'file' above each input file\n"
|
||||||
|
" -nostdlib do not link with standard crt/libs\n"
|
||||||
" -isystem dir add 'dir' to system include path\n"
|
" -isystem dir add 'dir' to system include path\n"
|
||||||
" -static link to static libraries (not recommended)\n"
|
" -static link to static libraries (not recommended)\n"
|
||||||
" -dumpversion print version\n"
|
" -dumpversion print version\n"
|
||||||
" -print-search-dirs print search paths\n"
|
" -print-search-dirs print search paths\n"
|
||||||
|
" -rstdin file with -run: use 'file' as custom stdin\n"
|
||||||
" -dt with -run/-E: auto-define 'test_...' macros\n"
|
" -dt with -run/-E: auto-define 'test_...' macros\n"
|
||||||
"Ignored options:\n"
|
"Ignored options:\n"
|
||||||
" --param -pedantic -pipe -s -std -traditional\n"
|
" -arch -C --param -pedantic -pipe -s -traditional\n"
|
||||||
"-W... warnings:\n"
|
"-W[no-]... warnings:\n"
|
||||||
" all turn on some (*) warnings\n"
|
" all turn on some (*) warnings\n"
|
||||||
" error stop after first warning\n"
|
" error[=warning] stop after warning (any or specified)\n"
|
||||||
" unsupported warn about ignored options, pragmas, etc.\n"
|
|
||||||
" write-strings strings are const\n"
|
" write-strings strings are const\n"
|
||||||
|
" unsupported warn about ignored options, pragmas, etc.\n"
|
||||||
" implicit-function-declaration warn for missing prototype (*)\n"
|
" implicit-function-declaration warn for missing prototype (*)\n"
|
||||||
|
" discarded-qualifiers warn when const is dropped (*)\n"
|
||||||
"-f[no-]... flags:\n"
|
"-f[no-]... flags:\n"
|
||||||
" unsigned-char default char is unsigned\n"
|
" unsigned-char default char is unsigned\n"
|
||||||
" signed-char default char is signed\n"
|
" signed-char default char is signed\n"
|
||||||
@ -105,6 +123,10 @@ static const char help2[] =
|
|||||||
" leading-underscore decorate extern symbols\n"
|
" leading-underscore decorate extern symbols\n"
|
||||||
" ms-extensions allow anonymous struct in struct\n"
|
" ms-extensions allow anonymous struct in struct\n"
|
||||||
" dollars-in-identifiers allow '$' in C symbols\n"
|
" dollars-in-identifiers allow '$' in C symbols\n"
|
||||||
|
" reverse-funcargs evaluate function arguments right to left\n"
|
||||||
|
" gnu89-inline 'extern inline' is like 'static inline'\n"
|
||||||
|
" asynchronous-unwind-tables create eh_frame section [on]\n"
|
||||||
|
" test-coverage create code coverage code\n"
|
||||||
"-m... target specific options:\n"
|
"-m... target specific options:\n"
|
||||||
" ms-bitfields use MSVC bitfield layout\n"
|
" ms-bitfields use MSVC bitfield layout\n"
|
||||||
#ifdef TCC_TARGET_ARM
|
#ifdef TCC_TARGET_ARM
|
||||||
@ -114,9 +136,10 @@ static const char help2[] =
|
|||||||
" no-sse disable floats on x86_64\n"
|
" no-sse disable floats on x86_64\n"
|
||||||
#endif
|
#endif
|
||||||
"-Wl,... linker options:\n"
|
"-Wl,... linker options:\n"
|
||||||
" -nostdlib do not link with standard crt/libs\n"
|
" -nostdlib do not search standard library paths\n"
|
||||||
" -[no-]whole-archive load lib(s) fully/only as needed\n"
|
" -[no-]whole-archive load lib(s) fully/only as needed\n"
|
||||||
" -export-all-symbols same as -rdynamic\n"
|
" -export-all-symbols same as -rdynamic\n"
|
||||||
|
" -export-dynamic same as -rdynamic\n"
|
||||||
" -image-base= -Ttext= set base address of executable\n"
|
" -image-base= -Ttext= set base address of executable\n"
|
||||||
" -section-alignment= set section alignment in executable\n"
|
" -section-alignment= set section alignment in executable\n"
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
@ -131,9 +154,14 @@ static const char help2[] =
|
|||||||
" -rpath= set dynamic library search path\n"
|
" -rpath= set dynamic library search path\n"
|
||||||
" -enable-new-dtags set DT_RUNPATH instead of DT_RPATH\n"
|
" -enable-new-dtags set DT_RUNPATH instead of DT_RPATH\n"
|
||||||
" -soname= set DT_SONAME elf tag\n"
|
" -soname= set DT_SONAME elf tag\n"
|
||||||
|
#if defined(TCC_TARGET_MACHO)
|
||||||
|
" -install_name= set DT_SONAME elf tag (soname macOS alias)\n"
|
||||||
|
#else
|
||||||
|
" -Ipath, -dynamic-linker=path set ELF interpreter to path\n"
|
||||||
|
#endif
|
||||||
" -Bsymbolic set DT_SYMBOLIC elf tag\n"
|
" -Bsymbolic set DT_SYMBOLIC elf tag\n"
|
||||||
" -oformat=[elf32/64-* binary] set executable output format\n"
|
" -oformat=[elf32/64-* binary] set executable output format\n"
|
||||||
" -init= -fini= -as-needed -O (ignored)\n"
|
" -init= -fini= -Map= -as-needed -O -z= (ignored)\n"
|
||||||
"Predefined macros:\n"
|
"Predefined macros:\n"
|
||||||
" tcc -E -dM - < /dev/null\n"
|
" tcc -E -dM - < /dev/null\n"
|
||||||
#endif
|
#endif
|
||||||
@ -141,7 +169,11 @@ static const char help2[] =
|
|||||||
;
|
;
|
||||||
|
|
||||||
static const char version[] =
|
static const char version[] =
|
||||||
"tcc version "TCC_VERSION" ("
|
"tcc version "TCC_VERSION
|
||||||
|
#ifdef TCC_GITHASH
|
||||||
|
" "TCC_GITHASH
|
||||||
|
#endif
|
||||||
|
" ("
|
||||||
#ifdef TCC_TARGET_I386
|
#ifdef TCC_TARGET_I386
|
||||||
"i386"
|
"i386"
|
||||||
#elif defined TCC_TARGET_X86_64
|
#elif defined TCC_TARGET_X86_64
|
||||||
@ -150,18 +182,27 @@ static const char version[] =
|
|||||||
"C67"
|
"C67"
|
||||||
#elif defined TCC_TARGET_ARM
|
#elif defined TCC_TARGET_ARM
|
||||||
"ARM"
|
"ARM"
|
||||||
|
# ifdef TCC_ARM_EABI
|
||||||
|
" eabi"
|
||||||
|
# ifdef TCC_ARM_HARDFLOAT
|
||||||
|
"hf"
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
#elif defined TCC_TARGET_ARM64
|
#elif defined TCC_TARGET_ARM64
|
||||||
"AArch64"
|
"AArch64"
|
||||||
#endif
|
#elif defined TCC_TARGET_RISCV64
|
||||||
#ifdef TCC_ARM_HARDFLOAT
|
"riscv64"
|
||||||
" Hard Float"
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
" Windows"
|
" Windows"
|
||||||
#elif defined(TCC_TARGET_MACHO)
|
#elif defined(TCC_TARGET_MACHO)
|
||||||
" Darwin"
|
" Darwin"
|
||||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
#elif TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel
|
||||||
" FreeBSD"
|
" FreeBSD"
|
||||||
|
#elif TARGETOS_OpenBSD
|
||||||
|
" OpenBSD"
|
||||||
|
#elif TARGETOS_NetBSD
|
||||||
|
" NetBSD"
|
||||||
#else
|
#else
|
||||||
" Linux"
|
" Linux"
|
||||||
#endif
|
#endif
|
||||||
@ -182,10 +223,10 @@ static void print_search_dirs(TCCState *s)
|
|||||||
/* print_dirs("programs", NULL, 0); */
|
/* print_dirs("programs", NULL, 0); */
|
||||||
print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths);
|
print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths);
|
||||||
print_dirs("libraries", s->library_paths, s->nb_library_paths);
|
print_dirs("libraries", s->library_paths, s->nb_library_paths);
|
||||||
printf("libtcc1:\n %s/"TCC_LIBTCC1"\n", s->tcc_lib_path);
|
printf("libtcc1:\n %s/%s\n", s->library_paths[0], CONFIG_TCC_CROSSPREFIX TCC_LIBTCC1);
|
||||||
#ifndef TCC_TARGET_PE
|
#ifdef TCC_TARGET_UNIX
|
||||||
print_dirs("crt", s->crt_paths, s->nb_crt_paths);
|
print_dirs("crt", s->crt_paths, s->nb_crt_paths);
|
||||||
printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s));
|
printf("elfinterp:\n %s\n", s->elfint);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,7 +256,9 @@ static char *default_outputfile(TCCState *s, const char *first_file)
|
|||||||
|
|
||||||
if (first_file && strcmp(first_file, "-"))
|
if (first_file && strcmp(first_file, "-"))
|
||||||
name = tcc_basename(first_file);
|
name = tcc_basename(first_file);
|
||||||
snprintf(buf, sizeof(buf), "%s", name);
|
if (strlen(name) + 4 >= sizeof buf)
|
||||||
|
name = "a";
|
||||||
|
strcpy(buf, name);
|
||||||
ext = tcc_fileextension(buf);
|
ext = tcc_fileextension(buf);
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
if (s->output_type == TCC_OUTPUT_DLL)
|
if (s->output_type == TCC_OUTPUT_DLL)
|
||||||
@ -225,7 +268,7 @@ static char *default_outputfile(TCCState *s, const char *first_file)
|
|||||||
strcpy(ext, ".exe");
|
strcpy(ext, ".exe");
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r && *ext)
|
if ((s->just_deps || s->output_type == TCC_OUTPUT_OBJ) && !s->option_r && *ext)
|
||||||
strcpy(ext, ".o");
|
strcpy(ext, ".o");
|
||||||
else
|
else
|
||||||
strcpy(buf, "a.out");
|
strcpy(buf, "a.out");
|
||||||
@ -243,65 +286,68 @@ static unsigned getclock_ms(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc0, char **argv0)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
TCCState *s;
|
TCCState *s, *s1;
|
||||||
int ret, opt, n = 0, t = 0;
|
int ret, opt, n = 0, t = 0, done;
|
||||||
unsigned start_time = 0;
|
unsigned start_time = 0, end_time = 0;
|
||||||
const char *first_file;
|
const char *first_file;
|
||||||
int argc; char **argv;
|
int argc0 = argc;
|
||||||
FILE *ppfp = stdout;
|
char **argv0 = argv;
|
||||||
|
FILE *ppfp = NULL;
|
||||||
|
|
||||||
redo:
|
redo:
|
||||||
argc = argc0, argv = argv0;
|
argc = argc0, argv = argv0;
|
||||||
s = tcc_new();
|
s = s1 = tcc_new();
|
||||||
opt = tcc_parse_args(s, &argc, &argv, 1);
|
opt = tcc_parse_args(s, &argc, &argv);
|
||||||
|
|
||||||
|
if (n == 0) {
|
||||||
|
ret = 0;
|
||||||
|
if (opt == OPT_HELP) {
|
||||||
|
fputs(help, stdout);
|
||||||
|
if (s->verbose)
|
||||||
|
goto help2;
|
||||||
|
} else if (opt == OPT_HELP2) {
|
||||||
|
help2: fputs(help2, stdout);
|
||||||
|
} else if (opt == OPT_M32 || opt == OPT_M64) {
|
||||||
|
ret = tcc_tool_cross(argv, opt);
|
||||||
|
} else if (s->verbose)
|
||||||
|
printf("%s", version);
|
||||||
|
|
||||||
if ((n | t) == 0) {
|
|
||||||
if (opt == OPT_HELP)
|
|
||||||
return printf(help), 1;
|
|
||||||
if (opt == OPT_HELP2)
|
|
||||||
return printf(help2), 1;
|
|
||||||
if (opt == OPT_M32 || opt == OPT_M64)
|
|
||||||
tcc_tool_cross(s, argv, opt); /* never returns */
|
|
||||||
if (s->verbose)
|
|
||||||
printf(version);
|
|
||||||
if (opt == OPT_AR)
|
if (opt == OPT_AR)
|
||||||
return tcc_tool_ar(s, argc, argv);
|
ret = tcc_tool_ar(argc, argv);
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
if (opt == OPT_IMPDEF)
|
if (opt == OPT_IMPDEF)
|
||||||
return tcc_tool_impdef(s, argc, argv);
|
ret = tcc_tool_impdef(argc, argv);
|
||||||
#endif
|
#endif
|
||||||
if (opt == OPT_V)
|
|
||||||
return 0;
|
|
||||||
if (opt == OPT_PRINT_DIRS) {
|
if (opt == OPT_PRINT_DIRS) {
|
||||||
/* initialize search dirs */
|
/* initialize search dirs */
|
||||||
set_environment(s);
|
set_environment(s);
|
||||||
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
|
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
|
||||||
print_search_dirs(s);
|
print_search_dirs(s);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
if (opt) {
|
||||||
n = s->nb_files;
|
if (opt < 0) err:
|
||||||
if (n == 0)
|
ret = 1;
|
||||||
tcc_error("no input files\n");
|
tcc_delete(s);
|
||||||
|
return ret;
|
||||||
if (s->output_type == TCC_OUTPUT_PREPROCESS) {
|
}
|
||||||
if (s->outfile) {
|
if (s->nb_files == 0) {
|
||||||
ppfp = fopen(s->outfile, "w");
|
tcc_error_noabort("no input files");
|
||||||
|
} else if (s->output_type == TCC_OUTPUT_PREPROCESS) {
|
||||||
|
if (s->outfile && 0!=strcmp("-",s->outfile)) {
|
||||||
|
ppfp = tcc_fopen(s->outfile, "wb");
|
||||||
if (!ppfp)
|
if (!ppfp)
|
||||||
tcc_error("could not write '%s'", s->outfile);
|
tcc_error_noabort("could not write '%s'", s->outfile);
|
||||||
}
|
}
|
||||||
} else if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) {
|
} else if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) {
|
||||||
if (s->nb_libraries)
|
if (s->nb_libraries)
|
||||||
tcc_error("cannot specify libraries with -c");
|
tcc_error_noabort("cannot specify libraries with -c");
|
||||||
if (n > 1 && s->outfile)
|
else if (s->nb_files > 1 && s->outfile)
|
||||||
tcc_error("cannot specify output file with -c many files");
|
tcc_error_noabort("cannot specify output file with -c many files");
|
||||||
} else {
|
|
||||||
if (s->option_pthread)
|
|
||||||
tcc_set_options(s, "-lpthread");
|
|
||||||
}
|
}
|
||||||
|
if (s->nb_errors)
|
||||||
|
goto err;
|
||||||
if (s->do_bench)
|
if (s->do_bench)
|
||||||
start_time = getclock_ms();
|
start_time = getclock_ms();
|
||||||
}
|
}
|
||||||
@ -309,36 +355,43 @@ redo:
|
|||||||
set_environment(s);
|
set_environment(s);
|
||||||
if (s->output_type == 0)
|
if (s->output_type == 0)
|
||||||
s->output_type = TCC_OUTPUT_EXE;
|
s->output_type = TCC_OUTPUT_EXE;
|
||||||
tcc_set_output_type(s, s->output_type);
|
ret = tcc_set_output_type(s, s->output_type);
|
||||||
s->ppfp = ppfp;
|
if (ppfp)
|
||||||
|
s->ppfp = ppfp;
|
||||||
|
|
||||||
if ((s->output_type == TCC_OUTPUT_MEMORY
|
if ((s->output_type == TCC_OUTPUT_MEMORY
|
||||||
|| s->output_type == TCC_OUTPUT_PREPROCESS) && (s->dflag & 16))
|
|| s->output_type == TCC_OUTPUT_PREPROCESS)
|
||||||
s->dflag |= t ? 32 : 0, s->run_test = ++t, n = s->nb_files;
|
&& (s->dflag & 16)) { /* -dt option */
|
||||||
|
if (t)
|
||||||
|
s->dflag |= 32;
|
||||||
|
s->run_test = ++t;
|
||||||
|
if (n)
|
||||||
|
--n;
|
||||||
|
}
|
||||||
|
|
||||||
/* compile or add each files or library */
|
/* compile or add each files or library */
|
||||||
for (first_file = NULL, ret = 0;;) {
|
first_file = NULL;
|
||||||
struct filespec *f = s->files[s->nb_files - n];
|
while (0 == ret) {
|
||||||
|
struct filespec *f = s->files[n];
|
||||||
s->filetype = f->type;
|
s->filetype = f->type;
|
||||||
s->alacarte_link = f->alacarte;
|
if (f->type & AFF_TYPE_LIB) {
|
||||||
if (f->type == AFF_TYPE_LIB) {
|
ret = tcc_add_library(s, f->name);
|
||||||
if (tcc_add_library_err(s, f->name) < 0)
|
|
||||||
ret = 1;
|
|
||||||
} else {
|
} else {
|
||||||
if (1 == s->verbose)
|
if (1 == s->verbose)
|
||||||
printf("-> %s\n", f->name);
|
printf("-> %s\n", f->name);
|
||||||
if (!first_file)
|
if (!first_file)
|
||||||
first_file = f->name;
|
first_file = f->name;
|
||||||
if (tcc_add_file(s, f->name) < 0)
|
ret = tcc_add_file(s, f->name);
|
||||||
ret = 1;
|
|
||||||
}
|
}
|
||||||
s->filetype = 0;
|
if (++n == s->nb_files)
|
||||||
s->alacarte_link = 1;
|
break;
|
||||||
if (--n == 0 || ret
|
if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r)
|
||||||
|| (s->output_type == TCC_OUTPUT_OBJ && !s->option_r))
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s->do_bench)
|
||||||
|
end_time = getclock_ms();
|
||||||
|
|
||||||
if (s->run_test) {
|
if (s->run_test) {
|
||||||
t = 0;
|
t = 0;
|
||||||
} else if (s->output_type == TCC_OUTPUT_PREPROCESS) {
|
} else if (s->output_type == TCC_OUTPUT_PREPROCESS) {
|
||||||
@ -351,21 +404,29 @@ redo:
|
|||||||
} else {
|
} else {
|
||||||
if (!s->outfile)
|
if (!s->outfile)
|
||||||
s->outfile = default_outputfile(s, first_file);
|
s->outfile = default_outputfile(s, first_file);
|
||||||
if (tcc_output_file(s, s->outfile))
|
if (!s->just_deps)
|
||||||
ret = 1;
|
ret = tcc_output_file(s, s->outfile);
|
||||||
else if (s->gen_deps)
|
if (!ret && s->gen_deps)
|
||||||
gen_makedeps(s, s->outfile, s->deps_outfile);
|
gen_makedeps(s, s->outfile, s->deps_outfile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->do_bench && (n | t | ret) == 0)
|
done = 1;
|
||||||
tcc_print_stats(s, getclock_ms() - start_time);
|
|
||||||
tcc_delete(s);
|
|
||||||
if (ret == 0 && n)
|
|
||||||
goto redo; /* compile more files with -c */
|
|
||||||
if (t)
|
if (t)
|
||||||
goto redo; /* run more tests with -dt -run */
|
done = 0; /* run more tests with -dt -run */
|
||||||
if (ppfp && ppfp != stdout)
|
else if (ret) {
|
||||||
fclose(ppfp);
|
if (s->nb_errors)
|
||||||
|
ret = 1;
|
||||||
|
/* else keep the original exit code from tcc_run() */
|
||||||
|
} else if (n < s->nb_files)
|
||||||
|
done = 0; /* compile more files with -c */
|
||||||
|
else if (s->do_bench)
|
||||||
|
tcc_print_stats(s, end_time - start_time);
|
||||||
|
|
||||||
|
tcc_delete(s);
|
||||||
|
if (!done)
|
||||||
|
goto redo;
|
||||||
|
if (ppfp)
|
||||||
|
tcc_fclose(ppfp);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
470
tccasm.c
470
tccasm.c
@ -18,38 +18,91 @@
|
|||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define USING_GLOBALS
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
#ifdef CONFIG_TCC_ASM
|
#ifdef CONFIG_TCC_ASM
|
||||||
|
|
||||||
ST_FUNC int asm_get_local_label_name(TCCState *s1, unsigned int n)
|
static Section *last_text_section; /* to handle .previous asm directive */
|
||||||
{
|
static int asmgoto_n;
|
||||||
char buf[64];
|
|
||||||
TokenSym *ts;
|
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), "L..%u", n);
|
|
||||||
ts = tok_alloc(buf, strlen(buf));
|
|
||||||
return ts->tok;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global);
|
static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global);
|
||||||
static Sym* asm_new_label(TCCState *s1, int label, int is_local);
|
static Sym* asm_new_label(TCCState *s1, int label, int is_local);
|
||||||
static Sym* asm_new_label1(TCCState *s1, int label, int is_local, int sh_num, int value);
|
static Sym* asm_new_label1(TCCState *s1, int label, int is_local, int sh_num, int value);
|
||||||
|
|
||||||
|
#if PTR_SIZE == 8
|
||||||
|
/* output constant with relocation if 'r & VT_SYM' is true */
|
||||||
|
ST_FUNC void gen_addr64(int r, Sym *sym, int64_t c)
|
||||||
|
{
|
||||||
|
if (r & VT_SYM)
|
||||||
|
greloca(cur_text_section, sym, ind, R_DATA_PTR, c), c=0;
|
||||||
|
gen_le32(c);
|
||||||
|
gen_le32(c>>32);
|
||||||
|
}
|
||||||
|
|
||||||
|
ST_FUNC void gen_expr64(ExprValue *pe)
|
||||||
|
{
|
||||||
|
gen_addr64(pe->sym ? VT_SYM : 0, pe->sym, pe->v);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int asm_get_prefix_name(TCCState *s1, const char *prefix, unsigned int n)
|
||||||
|
{
|
||||||
|
char buf[64];
|
||||||
|
snprintf(buf, sizeof(buf), "%s%u", prefix, n);
|
||||||
|
return tok_alloc_const(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
ST_FUNC int asm_get_local_label_name(TCCState *s1, unsigned int n)
|
||||||
|
{
|
||||||
|
return asm_get_prefix_name(s1, "L..", n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If a C name has an _ prepended then only asm labels that start
|
||||||
|
with _ are representable in C, by removing the first _. ASM names
|
||||||
|
without _ at the beginning don't correspond to C names, but we use
|
||||||
|
the global C symbol table to track ASM names as well, so we need to
|
||||||
|
transform those into ones that don't conflict with a C name,
|
||||||
|
so prepend a '.' for them, but force the ELF asm name to be set. */
|
||||||
|
static int asm2cname(int v, int *addeddot)
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
*addeddot = 0;
|
||||||
|
if (!tcc_state->leading_underscore)
|
||||||
|
return v;
|
||||||
|
name = get_tok_str(v, NULL);
|
||||||
|
if (!name)
|
||||||
|
return v;
|
||||||
|
if (name[0] == '_') {
|
||||||
|
v = tok_alloc_const(name + 1);
|
||||||
|
} else if (!strchr(name, '.')) {
|
||||||
|
char newname[256];
|
||||||
|
snprintf(newname, sizeof newname, ".%s", name);
|
||||||
|
v = tok_alloc_const(newname);
|
||||||
|
*addeddot = 1;
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
static Sym *asm_label_find(int v)
|
static Sym *asm_label_find(int v)
|
||||||
{
|
{
|
||||||
Sym *sym = sym_find(v);
|
Sym *sym;
|
||||||
while (sym && sym->sym_scope)
|
int addeddot;
|
||||||
|
v = asm2cname(v, &addeddot);
|
||||||
|
sym = sym_find(v);
|
||||||
|
while (sym && sym->sym_scope && !(sym->type.t & VT_STATIC))
|
||||||
sym = sym->prev_tok;
|
sym = sym->prev_tok;
|
||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Sym *asm_label_push(int v)
|
static Sym *asm_label_push(int v)
|
||||||
{
|
{
|
||||||
|
int addeddot, v2 = asm2cname(v, &addeddot);
|
||||||
/* We always add VT_EXTERN, for sym definition that's tentative
|
/* We always add VT_EXTERN, for sym definition that's tentative
|
||||||
(for .set, removed for real defs), for mere references it's correct
|
(for .set, removed for real defs), for mere references it's correct
|
||||||
as is. */
|
as is. */
|
||||||
Sym *sym = global_identifier_push(v, VT_ASM | VT_EXTERN | VT_STATIC, 0);
|
Sym *sym = global_identifier_push(v2, VT_ASM | VT_EXTERN | VT_STATIC, 0);
|
||||||
sym->r = VT_CONST | VT_SYM;
|
if (addeddot)
|
||||||
|
sym->asm_label = v;
|
||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,11 +129,10 @@ ST_FUNC Sym* get_asm_sym(int name, Sym *csym)
|
|||||||
|
|
||||||
static Sym* asm_section_sym(TCCState *s1, Section *sec)
|
static Sym* asm_section_sym(TCCState *s1, Section *sec)
|
||||||
{
|
{
|
||||||
char buf[100];
|
char buf[100]; int label; Sym *sym;
|
||||||
int label = tok_alloc(buf,
|
snprintf(buf, sizeof buf, "L.%s", sec->name);
|
||||||
snprintf(buf, sizeof buf, "L.%s", sec->name)
|
label = tok_alloc_const(buf);
|
||||||
)->tok;
|
sym = asm_label_find(label);
|
||||||
Sym *sym = asm_label_find(label);
|
|
||||||
return sym ? sym : asm_new_label1(s1, label, 1, sec->sh_num, 0);
|
return sym ? sym : asm_new_label1(s1, label, 1, sec->sh_num, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +159,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
|
|||||||
if (sym && (!sym->c || elfsym(sym)->st_shndx == SHN_UNDEF))
|
if (sym && (!sym->c || elfsym(sym)->st_shndx == SHN_UNDEF))
|
||||||
sym = sym->prev_tok;
|
sym = sym->prev_tok;
|
||||||
if (!sym)
|
if (!sym)
|
||||||
tcc_error("local label '%d' not found backward", n);
|
tcc_error("local label '%d' not found backward", (int)n);
|
||||||
} else {
|
} else {
|
||||||
/* forward */
|
/* forward */
|
||||||
if (!sym || (sym->c && elfsym(sym)->st_shndx != SHN_UNDEF)) {
|
if (!sym || (sym->c && elfsym(sym)->st_shndx != SHN_UNDEF)) {
|
||||||
@ -287,15 +339,17 @@ static inline void asm_expr_sum(TCCState *s1, ExprValue *pe)
|
|||||||
ElfSym *esym1, *esym2;
|
ElfSym *esym1, *esym2;
|
||||||
esym1 = elfsym(pe->sym);
|
esym1 = elfsym(pe->sym);
|
||||||
esym2 = elfsym(e2.sym);
|
esym2 = elfsym(e2.sym);
|
||||||
|
if (!esym2)
|
||||||
|
goto cannot_relocate;
|
||||||
if (esym1 && esym1->st_shndx == esym2->st_shndx
|
if (esym1 && esym1->st_shndx == esym2->st_shndx
|
||||||
&& esym1->st_shndx != SHN_UNDEF) {
|
&& esym1->st_shndx != SHN_UNDEF) {
|
||||||
/* we also accept defined symbols in the same section */
|
/* we also accept defined symbols in the same section */
|
||||||
pe->v += esym1->st_value - esym2->st_value;
|
pe->v += (int)(esym1->st_value - esym2->st_value);
|
||||||
pe->sym = NULL;
|
pe->sym = NULL;
|
||||||
} else if (esym2->st_shndx == cur_text_section->sh_num) {
|
} else if (esym2->st_shndx == cur_text_section->sh_num) {
|
||||||
/* When subtracting a defined symbol in current section
|
/* When subtracting a defined symbol in current section
|
||||||
this actually makes the value PC-relative. */
|
this actually makes the value PC-relative. */
|
||||||
pe->v -= esym2->st_value - ind - 4;
|
pe->v += (int)(0 - esym2->st_value);
|
||||||
pe->pcrel = 1;
|
pe->pcrel = 1;
|
||||||
e2.sym = NULL;
|
e2.sym = NULL;
|
||||||
} else {
|
} else {
|
||||||
@ -360,6 +414,8 @@ ST_FUNC int asm_int_expr(TCCState *s1)
|
|||||||
asm_expr(s1, &e);
|
asm_expr(s1, &e);
|
||||||
if (e.sym)
|
if (e.sym)
|
||||||
expect("constant");
|
expect("constant");
|
||||||
|
if ((int)e.v != e.v)
|
||||||
|
tcc_error("integer out of range %lld", (long long)e.v);
|
||||||
return e.v;
|
return e.v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,7 +445,7 @@ static Sym* asm_new_label1(TCCState *s1, int label, int is_local,
|
|||||||
sym = asm_label_push(label);
|
sym = asm_label_push(label);
|
||||||
}
|
}
|
||||||
if (!sym->c)
|
if (!sym->c)
|
||||||
put_extern_sym2(sym, SHN_UNDEF, 0, 0, 0);
|
put_extern_sym2(sym, SHN_UNDEF, 0, 0, 1);
|
||||||
esym = elfsym(sym);
|
esym = elfsym(sym);
|
||||||
esym->st_shndx = sh_num;
|
esym->st_shndx = sh_num;
|
||||||
esym->st_value = value;
|
esym->st_value = value;
|
||||||
@ -454,7 +510,7 @@ static void pop_section(TCCState *s1)
|
|||||||
|
|
||||||
static void asm_parse_directive(TCCState *s1, int global)
|
static void asm_parse_directive(TCCState *s1, int global)
|
||||||
{
|
{
|
||||||
int n, offset, v, size, tok1;
|
int n, offset, v, size, tok1, c;
|
||||||
Section *sec;
|
Section *sec;
|
||||||
uint8_t *ptr;
|
uint8_t *ptr;
|
||||||
|
|
||||||
@ -477,25 +533,32 @@ static void asm_parse_directive(TCCState *s1, int global)
|
|||||||
tok1 = TOK_ASMDIR_align;
|
tok1 = TOK_ASMDIR_align;
|
||||||
}
|
}
|
||||||
if (tok1 == TOK_ASMDIR_align || tok1 == TOK_ASMDIR_balign) {
|
if (tok1 == TOK_ASMDIR_align || tok1 == TOK_ASMDIR_balign) {
|
||||||
if (n < 0 || (n & (n-1)) != 0)
|
if (n <= 0 || (n & (n-1)) != 0)
|
||||||
tcc_error("alignment must be a positive power of two");
|
tcc_error("alignment must be a positive power of two");
|
||||||
offset = (ind + n - 1) & -n;
|
offset = (ind + n - 1) & -n;
|
||||||
size = offset - ind;
|
size = offset - ind;
|
||||||
/* the section must have a compatible alignment */
|
/* the section must have a compatible alignment */
|
||||||
if (sec->sh_addralign < n)
|
if (sec->sh_addralign < n)
|
||||||
sec->sh_addralign = n;
|
sec->sh_addralign = n;
|
||||||
|
c = sec->sh_flags & SHF_EXECINSTR;
|
||||||
} else {
|
} else {
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
n = 0;
|
n = 0;
|
||||||
size = n;
|
size = n, c = 0;
|
||||||
}
|
}
|
||||||
v = 0;
|
v = 0;
|
||||||
if (tok == ',') {
|
if (tok == ',') {
|
||||||
next();
|
next();
|
||||||
v = asm_int_expr(s1);
|
v = asm_int_expr(s1), c = 0;
|
||||||
}
|
}
|
||||||
zero_pad:
|
zero_pad:
|
||||||
|
if ((uint64_t)ind + size >= 1<<30)
|
||||||
|
tcc_error("too much data");
|
||||||
if (sec->sh_type != SHT_NOBITS) {
|
if (sec->sh_type != SHT_NOBITS) {
|
||||||
|
if (c) {
|
||||||
|
gen_fill_nops(size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
sec->data_offset = ind;
|
sec->data_offset = ind;
|
||||||
ptr = section_ptr_add(sec, size);
|
ptr = section_ptr_add(sec, size);
|
||||||
memset(ptr, v, size);
|
memset(ptr, v, size);
|
||||||
@ -503,7 +566,7 @@ static void asm_parse_directive(TCCState *s1, int global)
|
|||||||
ind += size;
|
ind += size;
|
||||||
break;
|
break;
|
||||||
case TOK_ASMDIR_quad:
|
case TOK_ASMDIR_quad:
|
||||||
#ifdef TCC_TARGET_X86_64
|
#if PTR_SIZE == 8
|
||||||
size = 8;
|
size = 8;
|
||||||
goto asm_data;
|
goto asm_data;
|
||||||
#else
|
#else
|
||||||
@ -552,7 +615,7 @@ static void asm_parse_directive(TCCState *s1, int global)
|
|||||||
if (sec->sh_type != SHT_NOBITS) {
|
if (sec->sh_type != SHT_NOBITS) {
|
||||||
if (size == 4) {
|
if (size == 4) {
|
||||||
gen_expr32(&e);
|
gen_expr32(&e);
|
||||||
#ifdef TCC_TARGET_X86_64
|
#if PTR_SIZE == 8
|
||||||
} else if (size == 8) {
|
} else if (size == 8) {
|
||||||
gen_expr64(&e);
|
gen_expr64(&e);
|
||||||
#endif
|
#endif
|
||||||
@ -626,8 +689,7 @@ static void asm_parse_directive(TCCState *s1, int global)
|
|||||||
tcc_error("we at end of file, .endr not found");
|
tcc_error("we at end of file, .endr not found");
|
||||||
tok_str_add_tok(init_str);
|
tok_str_add_tok(init_str);
|
||||||
}
|
}
|
||||||
tok_str_add(init_str, -1);
|
tok_str_add(init_str, TOK_EOF);
|
||||||
tok_str_add(init_str, 0);
|
|
||||||
begin_macro(init_str, 1);
|
begin_macro(init_str, 1);
|
||||||
while (repeat-- > 0) {
|
while (repeat-- > 0) {
|
||||||
tcc_assemble_internal(s1, (parse_flags & PARSE_FLAG_PREPROCESS),
|
tcc_assemble_internal(s1, (parse_flags & PARSE_FLAG_PREPROCESS),
|
||||||
@ -640,7 +702,6 @@ static void asm_parse_directive(TCCState *s1, int global)
|
|||||||
}
|
}
|
||||||
case TOK_ASMDIR_org:
|
case TOK_ASMDIR_org:
|
||||||
{
|
{
|
||||||
unsigned long n;
|
|
||||||
ExprValue e;
|
ExprValue e;
|
||||||
ElfSym *esym;
|
ElfSym *esym;
|
||||||
next();
|
next();
|
||||||
@ -654,7 +715,7 @@ static void asm_parse_directive(TCCState *s1, int global)
|
|||||||
}
|
}
|
||||||
if (n < ind)
|
if (n < ind)
|
||||||
tcc_error("attempt to .org backwards");
|
tcc_error("attempt to .org backwards");
|
||||||
v = 0;
|
v = c = 0;
|
||||||
size = n - ind;
|
size = n - ind;
|
||||||
goto zero_pad;
|
goto zero_pad;
|
||||||
}
|
}
|
||||||
@ -676,6 +737,8 @@ static void asm_parse_directive(TCCState *s1, int global)
|
|||||||
do {
|
do {
|
||||||
Sym *sym;
|
Sym *sym;
|
||||||
next();
|
next();
|
||||||
|
if (tok < TOK_IDENT)
|
||||||
|
expect("identifier");
|
||||||
sym = get_asm_sym(tok, NULL);
|
sym = get_asm_sym(tok, NULL);
|
||||||
if (tok1 != TOK_ASMDIR_hidden)
|
if (tok1 != TOK_ASMDIR_hidden)
|
||||||
sym->type.t &= ~VT_STATIC;
|
sym->type.t &= ~VT_STATIC;
|
||||||
@ -691,7 +754,7 @@ static void asm_parse_directive(TCCState *s1, int global)
|
|||||||
case TOK_ASMDIR_ascii:
|
case TOK_ASMDIR_ascii:
|
||||||
case TOK_ASMDIR_asciz:
|
case TOK_ASMDIR_asciz:
|
||||||
{
|
{
|
||||||
const uint8_t *p;
|
const char *p;
|
||||||
int i, size, t;
|
int i, size, t;
|
||||||
|
|
||||||
t = tok;
|
t = tok;
|
||||||
@ -735,19 +798,21 @@ static void asm_parse_directive(TCCState *s1, int global)
|
|||||||
break;
|
break;
|
||||||
case TOK_ASMDIR_file:
|
case TOK_ASMDIR_file:
|
||||||
{
|
{
|
||||||
char filename[512];
|
const char *p;
|
||||||
|
parse_flags &= ~PARSE_FLAG_TOK_STR;
|
||||||
filename[0] = '\0';
|
|
||||||
next();
|
next();
|
||||||
|
if (tok == TOK_PPNUM)
|
||||||
if (tok == TOK_STR)
|
next();
|
||||||
pstrcat(filename, sizeof(filename), tokc.str.data);
|
if (tok == TOK_PPSTR && tokc.str.data[0] == '"') {
|
||||||
else
|
tokc.str.data[tokc.str.size - 2] = 0;
|
||||||
pstrcat(filename, sizeof(filename), get_tok_str(tok, NULL));
|
p = tokc.str.data + 1;
|
||||||
|
} else if (tok >= TOK_IDENT) {
|
||||||
if (s1->warn_unsupported)
|
p = get_tok_str(tok, &tokc);
|
||||||
tcc_warning("ignoring .file %s", filename);
|
} else {
|
||||||
|
skip_to_eol(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tccpp_putfile(p);
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -757,36 +822,33 @@ static void asm_parse_directive(TCCState *s1, int global)
|
|||||||
|
|
||||||
ident[0] = '\0';
|
ident[0] = '\0';
|
||||||
next();
|
next();
|
||||||
|
|
||||||
if (tok == TOK_STR)
|
if (tok == TOK_STR)
|
||||||
pstrcat(ident, sizeof(ident), tokc.str.data);
|
pstrcat(ident, sizeof(ident), tokc.str.data);
|
||||||
else
|
else
|
||||||
pstrcat(ident, sizeof(ident), get_tok_str(tok, NULL));
|
pstrcat(ident, sizeof(ident), get_tok_str(tok, &tokc));
|
||||||
|
tcc_warning_c(warn_unsupported)("ignoring .ident %s", ident);
|
||||||
if (s1->warn_unsupported)
|
|
||||||
tcc_warning("ignoring .ident %s", ident);
|
|
||||||
|
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TOK_ASMDIR_size:
|
case TOK_ASMDIR_size:
|
||||||
{
|
{
|
||||||
Sym *sym;
|
Sym *sym;
|
||||||
|
ElfSym *esym;
|
||||||
|
|
||||||
next();
|
next();
|
||||||
|
if (tok < TOK_IDENT)
|
||||||
|
expect("identifier");
|
||||||
sym = asm_label_find(tok);
|
sym = asm_label_find(tok);
|
||||||
if (!sym) {
|
if (!sym)
|
||||||
tcc_error("label not found: %s", get_tok_str(tok, NULL));
|
tcc_error("label not found: %s", get_tok_str(tok, NULL));
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX .size name,label2-label1 */
|
/* XXX .size name,label2-label1 */
|
||||||
if (s1->warn_unsupported)
|
tcc_warning_c(warn_unsupported)("ignoring .size %s,*", get_tok_str(tok, NULL));
|
||||||
tcc_warning("ignoring .size %s,*", get_tok_str(tok, NULL));
|
|
||||||
|
|
||||||
next();
|
next();
|
||||||
skip(',');
|
skip(',');
|
||||||
while (tok != TOK_LINEFEED && tok != ';' && tok != CH_EOF) {
|
n = asm_int_expr(s1);
|
||||||
next();
|
esym = elfsym(sym);
|
||||||
|
if (esym) {
|
||||||
|
esym->st_size = n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -794,8 +856,11 @@ static void asm_parse_directive(TCCState *s1, int global)
|
|||||||
{
|
{
|
||||||
Sym *sym;
|
Sym *sym;
|
||||||
const char *newtype;
|
const char *newtype;
|
||||||
|
int st_type;
|
||||||
|
|
||||||
next();
|
next();
|
||||||
|
if (tok < TOK_IDENT)
|
||||||
|
expect("identifier");
|
||||||
sym = get_asm_sym(tok, NULL);
|
sym = get_asm_sym(tok, NULL);
|
||||||
next();
|
next();
|
||||||
skip(',');
|
skip(',');
|
||||||
@ -808,10 +873,19 @@ static void asm_parse_directive(TCCState *s1, int global)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(newtype, "function") || !strcmp(newtype, "STT_FUNC")) {
|
if (!strcmp(newtype, "function") || !strcmp(newtype, "STT_FUNC")) {
|
||||||
sym->type.t = (sym->type.t & ~VT_BTYPE) | VT_FUNC;
|
if (IS_ASM_SYM(sym))
|
||||||
}
|
sym->type.t |= VT_ASM_FUNC;
|
||||||
else if (s1->warn_unsupported)
|
st_type = STT_FUNC;
|
||||||
tcc_warning("change type of '%s' from 0x%x to '%s' ignored",
|
set_st_type:
|
||||||
|
if (sym->c) {
|
||||||
|
ElfSym *esym = elfsym(sym);
|
||||||
|
esym->st_info = ELFW(ST_INFO)(ELFW(ST_BIND)(esym->st_info), st_type);
|
||||||
|
}
|
||||||
|
} else if (!strcmp(newtype, "object") || !strcmp(newtype, "STT_OBJECT")) {
|
||||||
|
st_type = STT_OBJECT;
|
||||||
|
goto set_st_type;
|
||||||
|
} else
|
||||||
|
tcc_warning_c(warn_unsupported)("change type of '%s' from 0x%x to '%s' ignored",
|
||||||
get_tok_str(sym->v, NULL), sym->type.t, newtype);
|
get_tok_str(sym->v, NULL), sym->type.t, newtype);
|
||||||
|
|
||||||
next();
|
next();
|
||||||
@ -822,6 +896,7 @@ static void asm_parse_directive(TCCState *s1, int global)
|
|||||||
{
|
{
|
||||||
char sname[256];
|
char sname[256];
|
||||||
int old_nb_section = s1->nb_sections;
|
int old_nb_section = s1->nb_sections;
|
||||||
|
int flags = SHF_ALLOC;
|
||||||
|
|
||||||
tok1 = tok;
|
tok1 = tok;
|
||||||
/* XXX: support more options */
|
/* XXX: support more options */
|
||||||
@ -835,10 +910,17 @@ static void asm_parse_directive(TCCState *s1, int global)
|
|||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
if (tok == ',') {
|
if (tok == ',') {
|
||||||
|
const char *p;
|
||||||
/* skip section options */
|
/* skip section options */
|
||||||
next();
|
next();
|
||||||
if (tok != TOK_STR)
|
if (tok != TOK_STR)
|
||||||
expect("string constant");
|
expect("string constant");
|
||||||
|
for (p = tokc.str.data; *p; ++p) {
|
||||||
|
if (*p == 'w')
|
||||||
|
flags |= SHF_WRITE;
|
||||||
|
if (*p == 'x')
|
||||||
|
flags |= SHF_EXECINSTR;
|
||||||
|
}
|
||||||
next();
|
next();
|
||||||
if (tok == ',') {
|
if (tok == ',') {
|
||||||
next();
|
next();
|
||||||
@ -855,8 +937,14 @@ static void asm_parse_directive(TCCState *s1, int global)
|
|||||||
/* If we just allocated a new section reset its alignment to
|
/* If we just allocated a new section reset its alignment to
|
||||||
1. new_section normally acts for GCC compatibility and
|
1. new_section normally acts for GCC compatibility and
|
||||||
sets alignment to PTR_SIZE. The assembler behaves different. */
|
sets alignment to PTR_SIZE. The assembler behaves different. */
|
||||||
if (old_nb_section != s1->nb_sections)
|
if (old_nb_section != s1->nb_sections) {
|
||||||
cur_text_section->sh_addralign = 1;
|
cur_text_section->sh_addralign = 1;
|
||||||
|
/* Make .init and .fini sections executable by default.
|
||||||
|
GAS does so, too, and musl relies on it. */
|
||||||
|
if (!strcmp(sname, ".init") || !strcmp(sname, ".fini"))
|
||||||
|
flags |= SHF_EXECINSTR;
|
||||||
|
cur_text_section->sh_flags = flags;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TOK_ASMDIR_previous:
|
case TOK_ASMDIR_previous:
|
||||||
@ -888,12 +976,87 @@ static void asm_parse_directive(TCCState *s1, int global)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef TCC_TARGET_X86_64
|
#if PTR_SIZE == 8
|
||||||
/* added for compatibility with GAS */
|
/* added for compatibility with GAS */
|
||||||
case TOK_ASMDIR_code64:
|
case TOK_ASMDIR_code64:
|
||||||
next();
|
next();
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef TCC_TARGET_RISCV64
|
||||||
|
case TOK_ASMDIR_option:
|
||||||
|
next();
|
||||||
|
switch(tok){
|
||||||
|
case TOK_ASM_rvc: /* Will be deprecated soon in favor of arch */
|
||||||
|
case TOK_ASM_norvc: /* Will be deprecated soon in favor of arch */
|
||||||
|
case TOK_ASM_pic:
|
||||||
|
case TOK_ASM_nopic:
|
||||||
|
case TOK_ASM_relax:
|
||||||
|
case TOK_ASM_norelax:
|
||||||
|
case TOK_ASM_push:
|
||||||
|
case TOK_ASM_pop:
|
||||||
|
/* TODO: unimplemented */
|
||||||
|
next();
|
||||||
|
break;
|
||||||
|
case TOK_ASM_arch:
|
||||||
|
/* TODO: unimplemented, requires extra parsing */
|
||||||
|
tcc_error("unimp .option '.%s'", get_tok_str(tok, NULL));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
tcc_error("unknown .option '.%s'", get_tok_str(tok, NULL));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
/* TODO: Implement symvar support. FreeBSD >= 14 needs this */
|
||||||
|
case TOK_ASMDIR_symver:
|
||||||
|
next();
|
||||||
|
next();
|
||||||
|
skip(',');
|
||||||
|
next();
|
||||||
|
skip('@');
|
||||||
|
next();
|
||||||
|
break;
|
||||||
|
case TOK_ASMDIR_reloc:
|
||||||
|
{
|
||||||
|
ExprValue e;
|
||||||
|
const char *reloc_name;
|
||||||
|
int reloc_type = -1;
|
||||||
|
|
||||||
|
next();
|
||||||
|
asm_expr(s1, &e);
|
||||||
|
skip(',');
|
||||||
|
reloc_name = get_tok_str(tok, NULL);
|
||||||
|
#if defined(TCC_TARGET_ARM64)
|
||||||
|
if (!strcmp(reloc_name, "R_AARCH64_CALL26"))
|
||||||
|
reloc_type = R_AARCH64_CALL26;
|
||||||
|
#elif defined(TCC_TARGET_RISCV64)
|
||||||
|
if (!strcmp(reloc_name, "R_RISCV_CALL") || !strcmp(reloc_name, "R_RISCV_CALL_PLT"))
|
||||||
|
reloc_type = R_RISCV_CALL;
|
||||||
|
else if (!strcmp(reloc_name, "R_RISCV_BRANCH"))
|
||||||
|
reloc_type = R_RISCV_BRANCH;
|
||||||
|
else if (!strcmp(reloc_name, "R_RISCV_JAL"))
|
||||||
|
reloc_type = R_RISCV_JAL;
|
||||||
|
else if (!strcmp(reloc_name, "R_RISCV_PCREL_HI20"))
|
||||||
|
reloc_type = R_RISCV_PCREL_HI20;
|
||||||
|
else if (!strcmp(reloc_name, "R_RISCV_PCREL_LO12_I"))
|
||||||
|
reloc_type = R_RISCV_PCREL_LO12_I;
|
||||||
|
else if (!strcmp(reloc_name, "R_RISCV_PCREL_LO12_S"))
|
||||||
|
reloc_type = R_RISCV_PCREL_LO12_S;
|
||||||
|
else if (!strcmp(reloc_name, "R_RISCV_32_PCREL"))
|
||||||
|
reloc_type = R_RISCV_32_PCREL;
|
||||||
|
else if (!strcmp(reloc_name, "R_RISCV_32"))
|
||||||
|
reloc_type = R_RISCV_32;
|
||||||
|
else if (!strcmp(reloc_name, "R_RISCV_64"))
|
||||||
|
reloc_type = R_RISCV_64;
|
||||||
|
#endif
|
||||||
|
if (reloc_type < 0)
|
||||||
|
tcc_error("unimp: reloc '%s' unknown", reloc_name);
|
||||||
|
next();
|
||||||
|
skip(',');
|
||||||
|
greloca(cur_text_section, get_asm_sym(tok, NULL), e.v, reloc_type, 0);
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
tcc_error("unknown assembler directive '.%s'", get_tok_str(tok, NULL));
|
tcc_error("unknown assembler directive '.%s'", get_tok_str(tok, NULL));
|
||||||
break;
|
break;
|
||||||
@ -914,16 +1077,17 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global)
|
|||||||
next();
|
next();
|
||||||
if (tok == TOK_EOF)
|
if (tok == TOK_EOF)
|
||||||
break;
|
break;
|
||||||
/* generate line number info */
|
tcc_debug_line(s1);
|
||||||
if (global && s1->do_debug)
|
|
||||||
tcc_debug_line(s1);
|
|
||||||
parse_flags |= PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */
|
parse_flags |= PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */
|
||||||
redo:
|
redo:
|
||||||
|
#if !defined(TCC_TARGET_ARM64)
|
||||||
if (tok == '#') {
|
if (tok == '#') {
|
||||||
/* horrible gas comment */
|
/* horrible gas comment */
|
||||||
while (tok != TOK_LINEFEED)
|
while (tok != TOK_LINEFEED)
|
||||||
next();
|
next();
|
||||||
} else if (tok >= TOK_ASMDIR_FIRST && tok <= TOK_ASMDIR_LAST) {
|
} else
|
||||||
|
#endif
|
||||||
|
if (tok >= TOK_ASMDIR_FIRST && tok <= TOK_ASMDIR_LAST) {
|
||||||
asm_parse_directive(s1, global);
|
asm_parse_directive(s1, global);
|
||||||
} else if (tok == TOK_PPNUM) {
|
} else if (tok == TOK_PPNUM) {
|
||||||
const char *p;
|
const char *p;
|
||||||
@ -982,12 +1146,14 @@ ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess)
|
|||||||
/* GCC inline asm support */
|
/* GCC inline asm support */
|
||||||
|
|
||||||
/* assemble the string 'str' in the current C compilation unit without
|
/* assemble the string 'str' in the current C compilation unit without
|
||||||
C preprocessing. NOTE: str is modified by modifying the '\0' at the
|
C preprocessing. */
|
||||||
end */
|
static void tcc_assemble_inline(TCCState *s1, const char *str, int len, int global)
|
||||||
static void tcc_assemble_inline(TCCState *s1, char *str, int len, int global)
|
|
||||||
{
|
{
|
||||||
const int *saved_macro_ptr = macro_ptr;
|
const int *saved_macro_ptr = macro_ptr;
|
||||||
int dotid = set_idnum('.', IS_ID);
|
int dotid = set_idnum('.', IS_ID);
|
||||||
|
#if !defined(TCC_TARGET_RISCV64) && !defined(TCC_TARGET_X86_64)
|
||||||
|
int dolid = set_idnum('$', 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
tcc_open_bf(s1, ":asm:", len);
|
tcc_open_bf(s1, ":asm:", len);
|
||||||
memcpy(file->buffer, str, len);
|
memcpy(file->buffer, str, len);
|
||||||
@ -995,6 +1161,9 @@ static void tcc_assemble_inline(TCCState *s1, char *str, int len, int global)
|
|||||||
tcc_assemble_internal(s1, 0, global);
|
tcc_assemble_internal(s1, 0, global);
|
||||||
tcc_close();
|
tcc_close();
|
||||||
|
|
||||||
|
#if !defined(TCC_TARGET_RISCV64) && !defined(TCC_TARGET_X86_64)
|
||||||
|
set_idnum('$', dolid);
|
||||||
|
#endif
|
||||||
set_idnum('.', dotid);
|
set_idnum('.', dotid);
|
||||||
macro_ptr = saved_macro_ptr;
|
macro_ptr = saved_macro_ptr;
|
||||||
}
|
}
|
||||||
@ -1041,15 +1210,12 @@ ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void subst_asm_operands(ASMOperand *operands, int nb_operands,
|
static void subst_asm_operands(ASMOperand *operands, int nb_operands,
|
||||||
CString *out_str, CString *in_str)
|
CString *out_str, const char *str)
|
||||||
{
|
{
|
||||||
int c, index, modifier;
|
int c, index, modifier;
|
||||||
const char *str;
|
|
||||||
ASMOperand *op;
|
ASMOperand *op;
|
||||||
SValue sv;
|
SValue sv;
|
||||||
|
|
||||||
cstr_new(out_str);
|
|
||||||
str = in_str->data;
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
c = *str++;
|
c = *str++;
|
||||||
if (c == '%') {
|
if (c == '%') {
|
||||||
@ -1060,22 +1226,35 @@ static void subst_asm_operands(ASMOperand *operands, int nb_operands,
|
|||||||
modifier = 0;
|
modifier = 0;
|
||||||
if (*str == 'c' || *str == 'n' ||
|
if (*str == 'c' || *str == 'n' ||
|
||||||
*str == 'b' || *str == 'w' || *str == 'h' || *str == 'k' ||
|
*str == 'b' || *str == 'w' || *str == 'h' || *str == 'k' ||
|
||||||
*str == 'q' ||
|
*str == 'q' || *str == 'l' ||
|
||||||
|
#ifdef TCC_TARGET_ARM64
|
||||||
|
*str == 'x' || *str == 's' || *str == 'd' || *str == 'Z' ||
|
||||||
|
#endif
|
||||||
|
#ifdef TCC_TARGET_RISCV64
|
||||||
|
*str == 'z' ||
|
||||||
|
#endif
|
||||||
/* P in GCC would add "@PLT" to symbol refs in PIC mode,
|
/* P in GCC would add "@PLT" to symbol refs in PIC mode,
|
||||||
and make literal operands not be decorated with '$'. */
|
and make literal operands not be decorated with '$'. */
|
||||||
*str == 'P')
|
*str == 'P')
|
||||||
modifier = *str++;
|
modifier = *str++;
|
||||||
index = find_constraint(operands, nb_operands, str, &str);
|
index = find_constraint(operands, nb_operands, str, &str);
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
|
error:
|
||||||
tcc_error("invalid operand reference after %%");
|
tcc_error("invalid operand reference after %%");
|
||||||
op = &operands[index];
|
op = &operands[index];
|
||||||
sv = *op->vt;
|
if (modifier == 'l') {
|
||||||
if (op->reg >= 0) {
|
cstr_cat(out_str, get_tok_str(op->is_label, NULL), -1);
|
||||||
sv.r = op->reg;
|
} else {
|
||||||
if ((op->vt->r & VT_VALMASK) == VT_LLOCAL && op->is_memory)
|
if (op->vt == NULL)
|
||||||
sv.r |= VT_LVAL;
|
goto error;
|
||||||
|
sv = *op->vt;
|
||||||
|
if (op->reg >= 0) {
|
||||||
|
sv.r = op->reg;
|
||||||
|
if (op->is_memory)
|
||||||
|
sv.r |= VT_LVAL;
|
||||||
|
}
|
||||||
|
subst_asm_operand(out_str, &sv, modifier);
|
||||||
}
|
}
|
||||||
subst_asm_operand(out_str, &sv, modifier);
|
|
||||||
} else {
|
} else {
|
||||||
add_char:
|
add_char:
|
||||||
cstr_ccat(out_str, c);
|
cstr_ccat(out_str, c);
|
||||||
@ -1091,11 +1270,11 @@ static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr,
|
|||||||
{
|
{
|
||||||
ASMOperand *op;
|
ASMOperand *op;
|
||||||
int nb_operands;
|
int nb_operands;
|
||||||
|
char* astr;
|
||||||
|
|
||||||
if (tok != ':') {
|
if (tok != ':') {
|
||||||
nb_operands = *nb_operands_ptr;
|
nb_operands = *nb_operands_ptr;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
CString astr;
|
|
||||||
if (nb_operands >= MAX_ASM_OPERANDS)
|
if (nb_operands >= MAX_ASM_OPERANDS)
|
||||||
tcc_error("too many asm operands");
|
tcc_error("too many asm operands");
|
||||||
op = &operands[nb_operands++];
|
op = &operands[nb_operands++];
|
||||||
@ -1108,10 +1287,8 @@ static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr,
|
|||||||
next();
|
next();
|
||||||
skip(']');
|
skip(']');
|
||||||
}
|
}
|
||||||
parse_mult_str(&astr, "string constant");
|
astr = parse_mult_str("string constant")->data;
|
||||||
op->constraint = tcc_malloc(astr.size);
|
pstrcpy(op->constraint, sizeof op->constraint, astr);
|
||||||
strcpy(op->constraint, astr.data);
|
|
||||||
cstr_free(&astr);
|
|
||||||
skip('(');
|
skip('(');
|
||||||
gexpr();
|
gexpr();
|
||||||
if (is_output) {
|
if (is_output) {
|
||||||
@ -1125,7 +1302,12 @@ static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr,
|
|||||||
if ((vtop->r & VT_LVAL) &&
|
if ((vtop->r & VT_LVAL) &&
|
||||||
((vtop->r & VT_VALMASK) == VT_LLOCAL ||
|
((vtop->r & VT_VALMASK) == VT_LLOCAL ||
|
||||||
(vtop->r & VT_VALMASK) < VT_CONST) &&
|
(vtop->r & VT_VALMASK) < VT_CONST) &&
|
||||||
!strchr(op->constraint, 'm')) {
|
!strchr(op->constraint, 'm')
|
||||||
|
#ifdef TCC_TARGET_ARM64
|
||||||
|
&& !strchr(op->constraint, 'Q')
|
||||||
|
&& !strstr(op->constraint, "Ump")
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
gv(RC_INT);
|
gv(RC_INT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1144,20 +1326,27 @@ static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr,
|
|||||||
/* parse the GCC asm() instruction */
|
/* parse the GCC asm() instruction */
|
||||||
ST_FUNC void asm_instr(void)
|
ST_FUNC void asm_instr(void)
|
||||||
{
|
{
|
||||||
CString astr, astr1;
|
CString astr, *astr1;
|
||||||
ASMOperand operands[MAX_ASM_OPERANDS];
|
|
||||||
int nb_outputs, nb_operands, i, must_subst, out_reg;
|
ASMOperand operands[MAX_ASM_OPERANDS];
|
||||||
uint8_t clobber_regs[NB_ASM_REGS];
|
int nb_outputs, nb_operands, i, must_subst, out_reg, nb_labels;
|
||||||
|
uint8_t clobber_regs[NB_ASM_REGS];
|
||||||
|
Section *sec;
|
||||||
|
|
||||||
next();
|
|
||||||
/* since we always generate the asm() instruction, we can ignore
|
/* since we always generate the asm() instruction, we can ignore
|
||||||
volatile */
|
volatile */
|
||||||
if (tok == TOK_VOLATILE1 || tok == TOK_VOLATILE2 || tok == TOK_VOLATILE3) {
|
while (tok == TOK_VOLATILE1 || tok == TOK_VOLATILE2 || tok == TOK_VOLATILE3
|
||||||
|
|| tok == TOK_GOTO) {
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
parse_asm_str(&astr);
|
|
||||||
|
astr1 = parse_asm_str();
|
||||||
|
cstr_new_s(&astr);
|
||||||
|
cstr_cat(&astr, astr1->data, astr1->size);
|
||||||
|
|
||||||
nb_operands = 0;
|
nb_operands = 0;
|
||||||
nb_outputs = 0;
|
nb_outputs = 0;
|
||||||
|
nb_labels = 0;
|
||||||
must_subst = 0;
|
must_subst = 0;
|
||||||
memset(clobber_regs, 0, sizeof(clobber_regs));
|
memset(clobber_regs, 0, sizeof(clobber_regs));
|
||||||
if (tok == ':') {
|
if (tok == ':') {
|
||||||
@ -1176,6 +1365,8 @@ ST_FUNC void asm_instr(void)
|
|||||||
/* XXX: handle registers */
|
/* XXX: handle registers */
|
||||||
next();
|
next();
|
||||||
for(;;) {
|
for(;;) {
|
||||||
|
if (tok == ':')
|
||||||
|
break;
|
||||||
if (tok != TOK_STR)
|
if (tok != TOK_STR)
|
||||||
expect("string constant");
|
expect("string constant");
|
||||||
asm_clobber(clobber_regs, tokc.str.data);
|
asm_clobber(clobber_regs, tokc.str.data);
|
||||||
@ -1187,6 +1378,41 @@ ST_FUNC void asm_instr(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (tok == ':') {
|
||||||
|
/* goto labels */
|
||||||
|
next();
|
||||||
|
for (;;) {
|
||||||
|
Sym *csym;
|
||||||
|
int asmname;
|
||||||
|
if (nb_operands + nb_labels >= MAX_ASM_OPERANDS)
|
||||||
|
tcc_error("too many asm operands");
|
||||||
|
if (tok < TOK_UIDENT)
|
||||||
|
expect("label identifier");
|
||||||
|
memset(operands + nb_operands + nb_labels, 0,
|
||||||
|
sizeof(operands[0]));
|
||||||
|
operands[nb_operands + nb_labels++].id = tok;
|
||||||
|
|
||||||
|
csym = label_find(tok);
|
||||||
|
if (!csym) {
|
||||||
|
csym = label_push(&global_label_stack, tok,
|
||||||
|
LABEL_FORWARD);
|
||||||
|
} else {
|
||||||
|
if (csym->r == LABEL_DECLARED)
|
||||||
|
csym->r = LABEL_FORWARD;
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
asmname = asm_get_prefix_name(tcc_state, "LG.",
|
||||||
|
++asmgoto_n);
|
||||||
|
if (!csym->c)
|
||||||
|
put_extern_sym2(csym, SHN_UNDEF, 0, 0, 1);
|
||||||
|
get_asm_sym(asmname, csym);
|
||||||
|
operands[nb_operands + nb_labels - 1].is_label = asmname;
|
||||||
|
|
||||||
|
if (tok != ',')
|
||||||
|
break;
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1209,21 +1435,30 @@ ST_FUNC void asm_instr(void)
|
|||||||
printf("asm: \"%s\"\n", (char *)astr.data);
|
printf("asm: \"%s\"\n", (char *)astr.data);
|
||||||
#endif
|
#endif
|
||||||
if (must_subst) {
|
if (must_subst) {
|
||||||
subst_asm_operands(operands, nb_operands, &astr1, &astr);
|
cstr_reset(astr1);
|
||||||
cstr_free(&astr);
|
cstr_cat(astr1, astr.data, astr.size);
|
||||||
} else {
|
cstr_reset(&astr);
|
||||||
astr1 = astr;
|
subst_asm_operands(operands, nb_operands + nb_labels, &astr, astr1->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ASM_DEBUG
|
#ifdef ASM_DEBUG
|
||||||
printf("subst_asm: \"%s\"\n", (char *)astr1.data);
|
printf("subst_asm: \"%s\"\n", (char *)astr.data);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* generate loads */
|
/* generate loads */
|
||||||
asm_gen_code(operands, nb_operands, nb_outputs, 0,
|
asm_gen_code(operands, nb_operands, nb_outputs, 0,
|
||||||
clobber_regs, out_reg);
|
clobber_regs, out_reg);
|
||||||
|
|
||||||
|
/* We don't allow switching section within inline asm to
|
||||||
|
bleed out to surrounding code. */
|
||||||
|
sec = cur_text_section;
|
||||||
/* assemble the string with tcc internal assembler */
|
/* assemble the string with tcc internal assembler */
|
||||||
tcc_assemble_inline(tcc_state, astr1.data, astr1.size - 1, 0);
|
tcc_assemble_inline(tcc_state, astr.data, astr.size - 1, 0);
|
||||||
|
cstr_free_s(&astr);
|
||||||
|
if (sec != cur_text_section) {
|
||||||
|
tcc_warning("inline asm tries to change current section");
|
||||||
|
use_section1(tcc_state, sec);
|
||||||
|
}
|
||||||
|
|
||||||
/* restore the current C token */
|
/* restore the current C token */
|
||||||
next();
|
next();
|
||||||
@ -1234,23 +1469,20 @@ ST_FUNC void asm_instr(void)
|
|||||||
|
|
||||||
/* free everything */
|
/* free everything */
|
||||||
for(i=0;i<nb_operands;i++) {
|
for(i=0;i<nb_operands;i++) {
|
||||||
ASMOperand *op;
|
|
||||||
op = &operands[i];
|
|
||||||
tcc_free(op->constraint);
|
|
||||||
vpop();
|
vpop();
|
||||||
}
|
}
|
||||||
cstr_free(&astr1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void asm_global_instr(void)
|
ST_FUNC void asm_global_instr(void)
|
||||||
{
|
{
|
||||||
CString astr;
|
CString *astr;
|
||||||
int saved_nocode_wanted = nocode_wanted;
|
int saved_nocode_wanted = nocode_wanted;
|
||||||
|
|
||||||
/* Global asm blocks are always emitted. */
|
/* Global asm blocks are always emitted. */
|
||||||
nocode_wanted = 0;
|
nocode_wanted = 0;
|
||||||
next();
|
next();
|
||||||
parse_asm_str(&astr);
|
astr = parse_asm_str();
|
||||||
skip(')');
|
skip(')');
|
||||||
/* NOTE: we do not eat the ';' so that we can restore the current
|
/* NOTE: we do not eat the ';' so that we can restore the current
|
||||||
token after the assembler parsing */
|
token after the assembler parsing */
|
||||||
@ -1258,20 +1490,36 @@ ST_FUNC void asm_global_instr(void)
|
|||||||
expect("';'");
|
expect("';'");
|
||||||
|
|
||||||
#ifdef ASM_DEBUG
|
#ifdef ASM_DEBUG
|
||||||
printf("asm_global: \"%s\"\n", (char *)astr.data);
|
printf("asm_global: \"%s\"\n", (char *)astr->data);
|
||||||
#endif
|
#endif
|
||||||
cur_text_section = text_section;
|
cur_text_section = text_section;
|
||||||
ind = cur_text_section->data_offset;
|
ind = cur_text_section->data_offset;
|
||||||
|
|
||||||
/* assemble the string with tcc internal assembler */
|
/* assemble the string with tcc internal assembler */
|
||||||
tcc_assemble_inline(tcc_state, astr.data, astr.size - 1, 1);
|
tcc_assemble_inline(tcc_state, astr->data, astr->size - 1, 1);
|
||||||
|
|
||||||
cur_text_section->data_offset = ind;
|
cur_text_section->data_offset = ind;
|
||||||
|
|
||||||
/* restore the current C token */
|
/* restore the current C token */
|
||||||
next();
|
next();
|
||||||
|
|
||||||
cstr_free(&astr);
|
|
||||||
nocode_wanted = saved_nocode_wanted;
|
nocode_wanted = saved_nocode_wanted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************************************/
|
||||||
|
#else
|
||||||
|
ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess)
|
||||||
|
{
|
||||||
|
tcc_error("asm not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
ST_FUNC void asm_instr(void)
|
||||||
|
{
|
||||||
|
tcc_error("inline asm() not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
ST_FUNC void asm_global_instr(void)
|
||||||
|
{
|
||||||
|
tcc_error("inline asm() not supported");
|
||||||
|
}
|
||||||
#endif /* CONFIG_TCC_ASM */
|
#endif /* CONFIG_TCC_ASM */
|
||||||
|
|||||||
17
tcccoff.c
17
tcccoff.c
@ -21,6 +21,9 @@
|
|||||||
|
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
|
|
||||||
|
/* XXX: this file uses tcc_error() to the effect of exit(1) */
|
||||||
|
#undef _tcc_error
|
||||||
|
|
||||||
#define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */
|
#define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */
|
||||||
#define MAX_STR_TABLE 1000000
|
#define MAX_STR_TABLE 1000000
|
||||||
AOUTHDR o_filehdr; /* OPTIONAL (A.OUT) FILE HEADER */
|
AOUTHDR o_filehdr; /* OPTIONAL (A.OUT) FILE HEADER */
|
||||||
@ -40,12 +43,12 @@ int FuncEntries[MAX_FUNCS];
|
|||||||
|
|
||||||
int OutputTheSection(Section * sect);
|
int OutputTheSection(Section * sect);
|
||||||
short int GetCoffFlags(const char *s);
|
short int GetCoffFlags(const char *s);
|
||||||
void SortSymbolTable(void);
|
void SortSymbolTable(TCCState *s1);
|
||||||
Section *FindSection(TCCState * s1, const char *sname);
|
Section *FindSection(TCCState * s1, const char *sname);
|
||||||
|
|
||||||
int C67_main_entry_point;
|
int C67_main_entry_point;
|
||||||
|
|
||||||
int FindCoffSymbolIndex(const char *func_name);
|
int FindCoffSymbolIndex(TCCState * s1, const char *func_name);
|
||||||
int nb_syms;
|
int nb_syms;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -92,7 +95,7 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
|
|||||||
sbss = FindSection(s1, ".bss");
|
sbss = FindSection(s1, ".bss");
|
||||||
|
|
||||||
nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym);
|
nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym);
|
||||||
coff_nb_syms = FindCoffSymbolIndex("XXXXXXXXXX1");
|
coff_nb_syms = FindCoffSymbolIndex(s1, "XXXXXXXXXX1");
|
||||||
|
|
||||||
file_hdr.f_magic = COFF_C67_MAGIC; /* magic number */
|
file_hdr.f_magic = COFF_C67_MAGIC; /* magic number */
|
||||||
file_hdr.f_timdat = 0; /* time & date stamp */
|
file_hdr.f_timdat = 0; /* time & date stamp */
|
||||||
@ -366,7 +369,7 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
|
|||||||
// finally global symbols
|
// finally global symbols
|
||||||
|
|
||||||
if (s1->do_debug)
|
if (s1->do_debug)
|
||||||
SortSymbolTable();
|
SortSymbolTable(s1);
|
||||||
|
|
||||||
// write line no data
|
// write line no data
|
||||||
|
|
||||||
@ -437,7 +440,7 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
|
|||||||
// output a function begin
|
// output a function begin
|
||||||
|
|
||||||
CoffLineNo.l_addr.l_symndx =
|
CoffLineNo.l_addr.l_symndx =
|
||||||
FindCoffSymbolIndex(func_name);
|
FindCoffSymbolIndex(s1, func_name);
|
||||||
CoffLineNo.l_lnno = 0;
|
CoffLineNo.l_lnno = 0;
|
||||||
|
|
||||||
fwrite(&CoffLineNo, 6, 1, f);
|
fwrite(&CoffLineNo, 6, 1, f);
|
||||||
@ -690,7 +693,7 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
|
|||||||
// group the symbols in order of filename, func1, func2, etc
|
// group the symbols in order of filename, func1, func2, etc
|
||||||
// finally global symbols
|
// finally global symbols
|
||||||
|
|
||||||
void SortSymbolTable(void)
|
void SortSymbolTable(TCCState *s1)
|
||||||
{
|
{
|
||||||
int i, j, k, n = 0;
|
int i, j, k, n = 0;
|
||||||
Elf32_Sym *p, *p2, *NewTable;
|
Elf32_Sym *p, *p2, *NewTable;
|
||||||
@ -770,7 +773,7 @@ void SortSymbolTable(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int FindCoffSymbolIndex(const char *func_name)
|
int FindCoffSymbolIndex(TCCState *s1, const char *func_name)
|
||||||
{
|
{
|
||||||
int i, n = 0;
|
int i, n = 0;
|
||||||
Elf32_Sym *p;
|
Elf32_Sym *p;
|
||||||
|
|||||||
2
tcclib.h
2
tcclib.h
@ -19,6 +19,7 @@ int atoi(const char *nptr);
|
|||||||
long int strtol(const char *nptr, char **endptr, int base);
|
long int strtol(const char *nptr, char **endptr, int base);
|
||||||
unsigned long int strtoul(const char *nptr, char **endptr, int base);
|
unsigned long int strtoul(const char *nptr, char **endptr, int base);
|
||||||
void exit(int);
|
void exit(int);
|
||||||
|
void *alloca(size_t);
|
||||||
|
|
||||||
/* stdio.h */
|
/* stdio.h */
|
||||||
typedef struct __FILE FILE;
|
typedef struct __FILE FILE;
|
||||||
@ -39,6 +40,7 @@ int getchar(void);
|
|||||||
char *gets(char *s);
|
char *gets(char *s);
|
||||||
int ungetc(int c, FILE *stream);
|
int ungetc(int c, FILE *stream);
|
||||||
int fflush(FILE *stream);
|
int fflush(FILE *stream);
|
||||||
|
int puts(const char *s);
|
||||||
int putchar (int c);
|
int putchar (int c);
|
||||||
|
|
||||||
int printf(const char *format, ...);
|
int printf(const char *format, ...);
|
||||||
|
|||||||
2477
tccmacho.c
Normal file
2477
tccmacho.c
Normal file
File diff suppressed because it is too large
Load Diff
167
tcctok.h
167
tcctok.h
@ -1,29 +1,31 @@
|
|||||||
|
/*********************************************************************/
|
||||||
/* keywords */
|
/* keywords */
|
||||||
DEF(TOK_INT, "int")
|
|
||||||
DEF(TOK_VOID, "void")
|
|
||||||
DEF(TOK_CHAR, "char")
|
|
||||||
DEF(TOK_IF, "if")
|
DEF(TOK_IF, "if")
|
||||||
DEF(TOK_ELSE, "else")
|
DEF(TOK_ELSE, "else")
|
||||||
DEF(TOK_WHILE, "while")
|
DEF(TOK_WHILE, "while")
|
||||||
|
DEF(TOK_FOR, "for")
|
||||||
|
DEF(TOK_DO, "do")
|
||||||
|
DEF(TOK_CONTINUE, "continue")
|
||||||
DEF(TOK_BREAK, "break")
|
DEF(TOK_BREAK, "break")
|
||||||
DEF(TOK_RETURN, "return")
|
DEF(TOK_RETURN, "return")
|
||||||
DEF(TOK_FOR, "for")
|
DEF(TOK_GOTO, "goto")
|
||||||
|
DEF(TOK_SWITCH, "switch")
|
||||||
|
DEF(TOK_CASE, "case")
|
||||||
|
DEF(TOK_DEFAULT, "default")
|
||||||
|
DEF(TOK_ASM1, "asm")
|
||||||
|
DEF(TOK_ASM2, "__asm")
|
||||||
|
DEF(TOK_ASM3, "__asm__")
|
||||||
|
|
||||||
DEF(TOK_EXTERN, "extern")
|
DEF(TOK_EXTERN, "extern")
|
||||||
DEF(TOK_STATIC, "static")
|
DEF(TOK_STATIC, "static")
|
||||||
DEF(TOK_UNSIGNED, "unsigned")
|
DEF(TOK_UNSIGNED, "unsigned")
|
||||||
DEF(TOK_GOTO, "goto")
|
DEF(TOK__Atomic, "_Atomic")
|
||||||
DEF(TOK_DO, "do")
|
|
||||||
DEF(TOK_CONTINUE, "continue")
|
|
||||||
DEF(TOK_SWITCH, "switch")
|
|
||||||
DEF(TOK_CASE, "case")
|
|
||||||
|
|
||||||
DEF(TOK_CONST1, "const")
|
DEF(TOK_CONST1, "const")
|
||||||
DEF(TOK_CONST2, "__const") /* gcc keyword */
|
DEF(TOK_CONST2, "__const") /* gcc keyword */
|
||||||
DEF(TOK_CONST3, "__const__") /* gcc keyword */
|
DEF(TOK_CONST3, "__const__") /* gcc keyword */
|
||||||
DEF(TOK_VOLATILE1, "volatile")
|
DEF(TOK_VOLATILE1, "volatile")
|
||||||
DEF(TOK_VOLATILE2, "__volatile") /* gcc keyword */
|
DEF(TOK_VOLATILE2, "__volatile") /* gcc keyword */
|
||||||
DEF(TOK_VOLATILE3, "__volatile__") /* gcc keyword */
|
DEF(TOK_VOLATILE3, "__volatile__") /* gcc keyword */
|
||||||
DEF(TOK_LONG, "long")
|
|
||||||
DEF(TOK_REGISTER, "register")
|
DEF(TOK_REGISTER, "register")
|
||||||
DEF(TOK_SIGNED1, "signed")
|
DEF(TOK_SIGNED1, "signed")
|
||||||
DEF(TOK_SIGNED2, "__signed") /* gcc keyword */
|
DEF(TOK_SIGNED2, "__signed") /* gcc keyword */
|
||||||
@ -36,34 +38,36 @@
|
|||||||
DEF(TOK_RESTRICT2, "__restrict")
|
DEF(TOK_RESTRICT2, "__restrict")
|
||||||
DEF(TOK_RESTRICT3, "__restrict__")
|
DEF(TOK_RESTRICT3, "__restrict__")
|
||||||
DEF(TOK_EXTENSION, "__extension__") /* gcc keyword */
|
DEF(TOK_EXTENSION, "__extension__") /* gcc keyword */
|
||||||
|
DEF(TOK_THREAD_LOCAL, "_Thread_local") /* C11 thread-local storage */
|
||||||
|
DEF(TOK___thread, "__thread") /* GCC thread-local storage extension */
|
||||||
|
|
||||||
DEF(TOK_GENERIC, "_Generic")
|
DEF(TOK_GENERIC, "_Generic")
|
||||||
|
DEF(TOK_STATIC_ASSERT, "_Static_assert")
|
||||||
|
|
||||||
|
DEF(TOK_VOID, "void")
|
||||||
|
DEF(TOK_CHAR, "char")
|
||||||
|
DEF(TOK_INT, "int")
|
||||||
DEF(TOK_FLOAT, "float")
|
DEF(TOK_FLOAT, "float")
|
||||||
DEF(TOK_DOUBLE, "double")
|
DEF(TOK_DOUBLE, "double")
|
||||||
DEF(TOK_BOOL, "_Bool")
|
DEF(TOK_BOOL, "_Bool")
|
||||||
|
DEF(TOK_COMPLEX, "_Complex")
|
||||||
DEF(TOK_SHORT, "short")
|
DEF(TOK_SHORT, "short")
|
||||||
|
DEF(TOK_LONG, "long")
|
||||||
DEF(TOK_STRUCT, "struct")
|
DEF(TOK_STRUCT, "struct")
|
||||||
DEF(TOK_UNION, "union")
|
DEF(TOK_UNION, "union")
|
||||||
DEF(TOK_TYPEDEF, "typedef")
|
DEF(TOK_TYPEDEF, "typedef")
|
||||||
DEF(TOK_DEFAULT, "default")
|
|
||||||
DEF(TOK_ENUM, "enum")
|
DEF(TOK_ENUM, "enum")
|
||||||
DEF(TOK_SIZEOF, "sizeof")
|
DEF(TOK_SIZEOF, "sizeof")
|
||||||
DEF(TOK_ATTRIBUTE1, "__attribute")
|
DEF(TOK_ATTRIBUTE1, "__attribute")
|
||||||
DEF(TOK_ATTRIBUTE2, "__attribute__")
|
DEF(TOK_ATTRIBUTE2, "__attribute__")
|
||||||
DEF(TOK_ALIGNOF1, "__alignof")
|
DEF(TOK_ALIGNOF1, "__alignof")
|
||||||
DEF(TOK_ALIGNOF2, "__alignof__")
|
DEF(TOK_ALIGNOF2, "__alignof__")
|
||||||
|
DEF(TOK_ALIGNOF3, "_Alignof")
|
||||||
|
DEF(TOK_ALIGNAS, "_Alignas")
|
||||||
DEF(TOK_TYPEOF1, "typeof")
|
DEF(TOK_TYPEOF1, "typeof")
|
||||||
DEF(TOK_TYPEOF2, "__typeof")
|
DEF(TOK_TYPEOF2, "__typeof")
|
||||||
DEF(TOK_TYPEOF3, "__typeof__")
|
DEF(TOK_TYPEOF3, "__typeof__")
|
||||||
DEF(TOK_LABEL, "__label__")
|
DEF(TOK_LABEL, "__label__")
|
||||||
DEF(TOK_ASM1, "asm")
|
|
||||||
DEF(TOK_ASM2, "__asm")
|
|
||||||
DEF(TOK_ASM3, "__asm__")
|
|
||||||
|
|
||||||
#ifdef TCC_TARGET_ARM64
|
|
||||||
DEF(TOK_UINT128, "__uint128_t")
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
/* the following are not keywords. They are included to ease parsing */
|
/* the following are not keywords. They are included to ease parsing */
|
||||||
@ -88,6 +92,8 @@
|
|||||||
DEF(TOK___FUNCTION__, "__FUNCTION__")
|
DEF(TOK___FUNCTION__, "__FUNCTION__")
|
||||||
DEF(TOK___VA_ARGS__, "__VA_ARGS__")
|
DEF(TOK___VA_ARGS__, "__VA_ARGS__")
|
||||||
DEF(TOK___COUNTER__, "__COUNTER__")
|
DEF(TOK___COUNTER__, "__COUNTER__")
|
||||||
|
DEF(TOK___HAS_INCLUDE, "__has_include")
|
||||||
|
DEF(TOK___HAS_INCLUDE_NEXT, "__has_include_next")
|
||||||
|
|
||||||
/* special identifiers */
|
/* special identifiers */
|
||||||
DEF(TOK___FUNC__, "__func__")
|
DEF(TOK___FUNC__, "__func__")
|
||||||
@ -109,8 +115,14 @@
|
|||||||
DEF(TOK_WEAK2, "__weak__")
|
DEF(TOK_WEAK2, "__weak__")
|
||||||
DEF(TOK_ALIAS1, "alias")
|
DEF(TOK_ALIAS1, "alias")
|
||||||
DEF(TOK_ALIAS2, "__alias__")
|
DEF(TOK_ALIAS2, "__alias__")
|
||||||
|
DEF(TOK_USED1, "used")
|
||||||
|
DEF(TOK_USED2, "__used__")
|
||||||
DEF(TOK_UNUSED1, "unused")
|
DEF(TOK_UNUSED1, "unused")
|
||||||
DEF(TOK_UNUSED2, "__unused__")
|
DEF(TOK_UNUSED2, "__unused__")
|
||||||
|
DEF(TOK_FORMAT1, "format")
|
||||||
|
DEF(TOK_FORMAT2, "__format__")
|
||||||
|
DEF(TOK_NODEBUG1, "nodebug")
|
||||||
|
DEF(TOK_NODEBUG2, "__nodebug__")
|
||||||
DEF(TOK_CDECL1, "cdecl")
|
DEF(TOK_CDECL1, "cdecl")
|
||||||
DEF(TOK_CDECL2, "__cdecl")
|
DEF(TOK_CDECL2, "__cdecl")
|
||||||
DEF(TOK_CDECL3, "__cdecl__")
|
DEF(TOK_CDECL3, "__cdecl__")
|
||||||
@ -120,8 +132,22 @@
|
|||||||
DEF(TOK_FASTCALL1, "fastcall")
|
DEF(TOK_FASTCALL1, "fastcall")
|
||||||
DEF(TOK_FASTCALL2, "__fastcall")
|
DEF(TOK_FASTCALL2, "__fastcall")
|
||||||
DEF(TOK_FASTCALL3, "__fastcall__")
|
DEF(TOK_FASTCALL3, "__fastcall__")
|
||||||
|
DEF(TOK_THISCALL1, "thiscall")
|
||||||
|
DEF(TOK_THISCALL2, "__thiscall")
|
||||||
|
DEF(TOK_THISCALL3, "__thiscall__")
|
||||||
DEF(TOK_REGPARM1, "regparm")
|
DEF(TOK_REGPARM1, "regparm")
|
||||||
DEF(TOK_REGPARM2, "__regparm__")
|
DEF(TOK_REGPARM2, "__regparm__")
|
||||||
|
DEF(TOK_CLEANUP1, "cleanup")
|
||||||
|
DEF(TOK_CLEANUP2, "__cleanup__")
|
||||||
|
DEF(TOK_CONSTRUCTOR1, "constructor")
|
||||||
|
DEF(TOK_CONSTRUCTOR2, "__constructor__")
|
||||||
|
DEF(TOK_DESTRUCTOR1, "destructor")
|
||||||
|
DEF(TOK_DESTRUCTOR2, "__destructor__")
|
||||||
|
DEF(TOK_ALWAYS_INLINE1, "always_inline")
|
||||||
|
DEF(TOK_ALWAYS_INLINE2, "__always_inline__")
|
||||||
|
DEF(TOK_NOINLINE, "__noinline__")
|
||||||
|
DEF(TOK_PURE1, "pure")
|
||||||
|
DEF(TOK_PURE2, "__pure__")
|
||||||
|
|
||||||
DEF(TOK_MODE, "__mode__")
|
DEF(TOK_MODE, "__mode__")
|
||||||
DEF(TOK_MODE_QI, "__QI__")
|
DEF(TOK_MODE_QI, "__QI__")
|
||||||
@ -132,8 +158,10 @@
|
|||||||
|
|
||||||
DEF(TOK_DLLEXPORT, "dllexport")
|
DEF(TOK_DLLEXPORT, "dllexport")
|
||||||
DEF(TOK_DLLIMPORT, "dllimport")
|
DEF(TOK_DLLIMPORT, "dllimport")
|
||||||
|
DEF(TOK_NODECORATE, "nodecorate")
|
||||||
DEF(TOK_NORETURN1, "noreturn")
|
DEF(TOK_NORETURN1, "noreturn")
|
||||||
DEF(TOK_NORETURN2, "__noreturn__")
|
DEF(TOK_NORETURN2, "__noreturn__")
|
||||||
|
DEF(TOK_NORETURN3, "_Noreturn")
|
||||||
DEF(TOK_VISIBILITY1, "visibility")
|
DEF(TOK_VISIBILITY1, "visibility")
|
||||||
DEF(TOK_VISIBILITY2, "__visibility__")
|
DEF(TOK_VISIBILITY2, "__visibility__")
|
||||||
|
|
||||||
@ -143,19 +171,43 @@
|
|||||||
DEF(TOK_builtin_frame_address, "__builtin_frame_address")
|
DEF(TOK_builtin_frame_address, "__builtin_frame_address")
|
||||||
DEF(TOK_builtin_return_address, "__builtin_return_address")
|
DEF(TOK_builtin_return_address, "__builtin_return_address")
|
||||||
DEF(TOK_builtin_expect, "__builtin_expect")
|
DEF(TOK_builtin_expect, "__builtin_expect")
|
||||||
|
DEF(TOK_builtin_unreachable, "__builtin_unreachable")
|
||||||
/*DEF(TOK_builtin_va_list, "__builtin_va_list")*/
|
/*DEF(TOK_builtin_va_list, "__builtin_va_list")*/
|
||||||
#if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64
|
#if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64
|
||||||
DEF(TOK_builtin_va_start, "__builtin_va_start")
|
DEF(TOK_builtin_va_start, "__builtin_va_start")
|
||||||
#elif defined TCC_TARGET_X86_64
|
#elif defined TCC_TARGET_X86_64
|
||||||
DEF(TOK_builtin_va_arg_types, "__builtin_va_arg_types")
|
DEF(TOK_builtin_va_arg_types, "__builtin_va_arg_types")
|
||||||
#elif defined TCC_TARGET_ARM64
|
#elif defined TCC_TARGET_ARM64
|
||||||
DEF(TOK___va_start, "__va_start")
|
DEF(TOK_builtin_va_start, "__builtin_va_start")
|
||||||
DEF(TOK___va_arg, "__va_arg")
|
DEF(TOK_builtin_va_arg, "__builtin_va_arg")
|
||||||
|
#elif defined TCC_TARGET_RISCV64
|
||||||
|
DEF(TOK_builtin_va_start, "__builtin_va_start")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* atomic operations */
|
||||||
|
#define DEF_ATOMIC(ID) DEF(TOK_##__##ID, "__"#ID)
|
||||||
|
DEF_ATOMIC(atomic_store)
|
||||||
|
DEF_ATOMIC(atomic_load)
|
||||||
|
DEF_ATOMIC(atomic_exchange)
|
||||||
|
DEF_ATOMIC(atomic_compare_exchange)
|
||||||
|
DEF_ATOMIC(atomic_fetch_add)
|
||||||
|
DEF_ATOMIC(atomic_fetch_sub)
|
||||||
|
DEF_ATOMIC(atomic_fetch_or)
|
||||||
|
DEF_ATOMIC(atomic_fetch_xor)
|
||||||
|
DEF_ATOMIC(atomic_fetch_and)
|
||||||
|
DEF_ATOMIC(atomic_fetch_nand)
|
||||||
|
DEF_ATOMIC(atomic_add_fetch)
|
||||||
|
DEF_ATOMIC(atomic_sub_fetch)
|
||||||
|
DEF_ATOMIC(atomic_or_fetch)
|
||||||
|
DEF_ATOMIC(atomic_xor_fetch)
|
||||||
|
DEF_ATOMIC(atomic_and_fetch)
|
||||||
|
DEF_ATOMIC(atomic_nand_fetch)
|
||||||
|
|
||||||
/* pragma */
|
/* pragma */
|
||||||
DEF(TOK_pack, "pack")
|
DEF(TOK_pack, "pack")
|
||||||
#if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_X86_64)
|
#if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_X86_64) && \
|
||||||
|
!defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_ARM64) && \
|
||||||
|
!defined(TCC_TARGET_RISCV64)
|
||||||
/* already defined for assembler */
|
/* already defined for assembler */
|
||||||
DEF(TOK_ASM_push, "push")
|
DEF(TOK_ASM_push, "push")
|
||||||
DEF(TOK_ASM_pop, "pop")
|
DEF(TOK_ASM_pop, "pop")
|
||||||
@ -192,9 +244,9 @@
|
|||||||
#if defined TCC_TARGET_ARM
|
#if defined TCC_TARGET_ARM
|
||||||
# ifdef TCC_ARM_EABI
|
# ifdef TCC_ARM_EABI
|
||||||
DEF(TOK_memcpy, "__aeabi_memcpy")
|
DEF(TOK_memcpy, "__aeabi_memcpy")
|
||||||
DEF(TOK_memcpy4, "__aeabi_memcpy4")
|
|
||||||
DEF(TOK_memcpy8, "__aeabi_memcpy8")
|
|
||||||
DEF(TOK_memmove, "__aeabi_memmove")
|
DEF(TOK_memmove, "__aeabi_memmove")
|
||||||
|
DEF(TOK_memmove4, "__aeabi_memmove4")
|
||||||
|
DEF(TOK_memmove8, "__aeabi_memmove8")
|
||||||
DEF(TOK_memset, "__aeabi_memset")
|
DEF(TOK_memset, "__aeabi_memset")
|
||||||
DEF(TOK___aeabi_ldivmod, "__aeabi_ldivmod")
|
DEF(TOK___aeabi_ldivmod, "__aeabi_ldivmod")
|
||||||
DEF(TOK___aeabi_uldivmod, "__aeabi_uldivmod")
|
DEF(TOK___aeabi_uldivmod, "__aeabi_uldivmod")
|
||||||
@ -246,16 +298,22 @@
|
|||||||
DEF(TOK___fixdfdi, "__fixdfdi")
|
DEF(TOK___fixdfdi, "__fixdfdi")
|
||||||
DEF(TOK___fixxfdi, "__fixxfdi")
|
DEF(TOK___fixxfdi, "__fixxfdi")
|
||||||
#endif
|
#endif
|
||||||
|
#if defined TCC_TARGET_X86_64
|
||||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
DEF(TOK___fixxfdi, "__fixxfdi")
|
||||||
DEF(TOK_alloca, "alloca")
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
DEF(TOK_alloca, "alloca")
|
||||||
|
|
||||||
#if defined TCC_TARGET_PE
|
#if defined TCC_TARGET_PE
|
||||||
DEF(TOK___chkstk, "__chkstk")
|
DEF(TOK___chkstk, "__chkstk")
|
||||||
#endif
|
#endif
|
||||||
#ifdef TCC_TARGET_ARM64
|
#ifdef TCC_TARGET_ARM64
|
||||||
DEF(TOK___arm64_clear_cache, "__arm64_clear_cache")
|
DEF(TOK___arm64_clear_cache, "__arm64_clear_cache")
|
||||||
|
#endif
|
||||||
|
#ifdef TCC_TARGET_RISCV64
|
||||||
|
DEF(TOK___riscv64_clear_cache, "__riscv64_clear_cache")
|
||||||
|
#endif
|
||||||
|
#if defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64
|
||||||
DEF(TOK___addtf3, "__addtf3")
|
DEF(TOK___addtf3, "__addtf3")
|
||||||
DEF(TOK___subtf3, "__subtf3")
|
DEF(TOK___subtf3, "__subtf3")
|
||||||
DEF(TOK___multf3, "__multf3")
|
DEF(TOK___multf3, "__multf3")
|
||||||
@ -264,6 +322,7 @@
|
|||||||
DEF(TOK___extenddftf2, "__extenddftf2")
|
DEF(TOK___extenddftf2, "__extenddftf2")
|
||||||
DEF(TOK___trunctfsf2, "__trunctfsf2")
|
DEF(TOK___trunctfsf2, "__trunctfsf2")
|
||||||
DEF(TOK___trunctfdf2, "__trunctfdf2")
|
DEF(TOK___trunctfdf2, "__trunctfdf2")
|
||||||
|
DEF(TOK___negtf2, "__negtf2")
|
||||||
DEF(TOK___fixtfsi, "__fixtfsi")
|
DEF(TOK___fixtfsi, "__fixtfsi")
|
||||||
DEF(TOK___fixtfdi, "__fixtfdi")
|
DEF(TOK___fixtfdi, "__fixtfdi")
|
||||||
DEF(TOK___fixunstfsi, "__fixunstfsi")
|
DEF(TOK___fixunstfsi, "__fixunstfsi")
|
||||||
@ -292,19 +351,34 @@
|
|||||||
DEF(TOK___bound_main_arg, "__bound_main_arg")
|
DEF(TOK___bound_main_arg, "__bound_main_arg")
|
||||||
DEF(TOK___bound_local_new, "__bound_local_new")
|
DEF(TOK___bound_local_new, "__bound_local_new")
|
||||||
DEF(TOK___bound_local_delete, "__bound_local_delete")
|
DEF(TOK___bound_local_delete, "__bound_local_delete")
|
||||||
|
DEF(TOK___bound_setjmp, "__bound_setjmp")
|
||||||
|
DEF(TOK___bound_longjmp, "__bound_longjmp")
|
||||||
|
DEF(TOK___bound_new_region, "__bound_new_region")
|
||||||
# ifdef TCC_TARGET_PE
|
# ifdef TCC_TARGET_PE
|
||||||
DEF(TOK_malloc, "malloc")
|
# ifdef TCC_TARGET_X86_64
|
||||||
DEF(TOK_free, "free")
|
DEF(TOK___bound_alloca_nr, "__bound_alloca_nr")
|
||||||
DEF(TOK_realloc, "realloc")
|
# endif
|
||||||
DEF(TOK_memalign, "memalign")
|
# else
|
||||||
DEF(TOK_calloc, "calloc")
|
DEF(TOK_sigsetjmp, "sigsetjmp")
|
||||||
|
DEF(TOK___sigsetjmp, "__sigsetjmp")
|
||||||
|
DEF(TOK_siglongjmp, "siglongjmp")
|
||||||
# endif
|
# endif
|
||||||
DEF(TOK_strlen, "strlen")
|
DEF(TOK_setjmp, "setjmp")
|
||||||
DEF(TOK_strcpy, "strcpy")
|
DEF(TOK__setjmp, "_setjmp")
|
||||||
|
DEF(TOK_longjmp, "longjmp")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*********************************************************************/
|
||||||
/* Tiny Assembler */
|
/* Tiny Assembler */
|
||||||
DEF_ASMDIR(byte) /* must be first directive */
|
#define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
|
||||||
|
#define DEF_ASMDIR(x) DEF(TOK_ASMDIR_ ## x, "." #x)
|
||||||
|
#define TOK_ASM_int TOK_INT
|
||||||
|
|
||||||
|
#define TOK_ASMDIR_FIRST TOK_ASMDIR_byte
|
||||||
|
#define TOK_ASMDIR_LAST TOK_ASMDIR_section
|
||||||
|
|
||||||
|
DEF_ASMDIR(byte) /* must be first directive */
|
||||||
DEF_ASMDIR(word)
|
DEF_ASMDIR(word)
|
||||||
DEF_ASMDIR(align)
|
DEF_ASMDIR(align)
|
||||||
DEF_ASMDIR(balign)
|
DEF_ASMDIR(balign)
|
||||||
@ -334,17 +408,34 @@
|
|||||||
DEF_ASMDIR(endr)
|
DEF_ASMDIR(endr)
|
||||||
DEF_ASMDIR(org)
|
DEF_ASMDIR(org)
|
||||||
DEF_ASMDIR(quad)
|
DEF_ASMDIR(quad)
|
||||||
#if defined(TCC_TARGET_I386)
|
#if PTR_SIZE == 4
|
||||||
DEF_ASMDIR(code16)
|
DEF_ASMDIR(code16)
|
||||||
DEF_ASMDIR(code32)
|
DEF_ASMDIR(code32)
|
||||||
#elif defined(TCC_TARGET_X86_64)
|
#else
|
||||||
DEF_ASMDIR(code64)
|
DEF_ASMDIR(code64)
|
||||||
|
#endif
|
||||||
|
#if defined(TCC_TARGET_RISCV64)
|
||||||
|
DEF_ASMDIR(option)
|
||||||
#endif
|
#endif
|
||||||
DEF_ASMDIR(short)
|
DEF_ASMDIR(short)
|
||||||
DEF_ASMDIR(long)
|
DEF_ASMDIR(long)
|
||||||
DEF_ASMDIR(int)
|
DEF_ASMDIR(int)
|
||||||
DEF_ASMDIR(section) /* must be last directive */
|
DEF_ASMDIR(symver)
|
||||||
|
DEF_ASMDIR(reloc)
|
||||||
|
DEF_ASMDIR(section) /* must be last directive */
|
||||||
|
|
||||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
||||||
#include "i386-tok.h"
|
#include "i386-tok.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined TCC_TARGET_ARM
|
||||||
|
#include "arm-tok.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined TCC_TARGET_ARM64
|
||||||
|
#include "arm64-tok.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined TCC_TARGET_RISCV64
|
||||||
|
#include "riscv64-tok.h"
|
||||||
|
#endif
|
||||||
|
|||||||
267
tcctools.c
267
tcctools.c
@ -48,52 +48,34 @@ static unsigned long le2belong(unsigned long ul) {
|
|||||||
((ul & 0xFF)<<24)+((ul & 0xFF00)<<8);
|
((ul & 0xFF)<<24)+((ul & 0xFF00)<<8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns 1 if s contains any of the chars of list, else 0 */
|
|
||||||
static int contains_any(const char *s, const char *list) {
|
|
||||||
const char *l;
|
|
||||||
for (; *s; s++) {
|
|
||||||
for (l = list; *l; l++) {
|
|
||||||
if (*s == *l)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ar_usage(int ret) {
|
static int ar_usage(int ret) {
|
||||||
fprintf(stderr, "usage: tcc -ar [rcsv] lib file...\n");
|
fprintf(stderr, "usage: tcc -ar [crstvx] lib [files]\n");
|
||||||
fprintf(stderr, "create library ([abdioptxN] not supported).\n");
|
fprintf(stderr, "create library ([abdiopN] not supported).\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
|
ST_FUNC int tcc_tool_ar(int argc, char **argv)
|
||||||
{
|
{
|
||||||
static ArHdr arhdr = {
|
static const ArHdr arhdr_init = {
|
||||||
"/ ",
|
"/ ",
|
||||||
" ",
|
"0 ",
|
||||||
"0 ",
|
"0 ",
|
||||||
"0 ",
|
"0 ",
|
||||||
"0 ",
|
"0 ",
|
||||||
" ",
|
"0 ",
|
||||||
ARFMAG
|
ARFMAG
|
||||||
};
|
};
|
||||||
|
|
||||||
static ArHdr arhdro = {
|
ArHdr arhdr = arhdr_init;
|
||||||
" ",
|
ArHdr arhdro = arhdr_init;
|
||||||
" ",
|
|
||||||
"0 ",
|
|
||||||
"0 ",
|
|
||||||
"0 ",
|
|
||||||
" ",
|
|
||||||
ARFMAG
|
|
||||||
};
|
|
||||||
|
|
||||||
FILE *fi, *fh = NULL, *fo = NULL;
|
FILE *fi, *fh = NULL, *fo = NULL;
|
||||||
|
const char *created_file = NULL; // must delete on error
|
||||||
ElfW(Ehdr) *ehdr;
|
ElfW(Ehdr) *ehdr;
|
||||||
ElfW(Shdr) *shdr;
|
ElfW(Shdr) *shdr;
|
||||||
ElfW(Sym) *sym;
|
ElfW(Sym) *sym;
|
||||||
int i, fsize, i_lib, i_obj;
|
int i, fsize, i_lib, i_obj;
|
||||||
char *buf, *shstr, *symtab = NULL, *strtab = NULL;
|
char *buf, *shstr, *symtab, *strtab;
|
||||||
int symtabsize = 0;//, strtabsize = 0;
|
int symtabsize = 0;//, strtabsize = 0;
|
||||||
char *anames = NULL;
|
char *anames = NULL;
|
||||||
int *afpos = NULL;
|
int *afpos = NULL;
|
||||||
@ -101,18 +83,24 @@ ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
|
|||||||
char tfile[260], stmp[20];
|
char tfile[260], stmp[20];
|
||||||
char *file, *name;
|
char *file, *name;
|
||||||
int ret = 2;
|
int ret = 2;
|
||||||
const char *ops_conflict = "habdioptxN"; // unsupported but destructive if ignored.
|
const char *ops_conflict = "habdiopN"; // unsupported but destructive if ignored.
|
||||||
|
int extract = 0;
|
||||||
|
int table = 0;
|
||||||
int verbose = 0;
|
int verbose = 0;
|
||||||
|
|
||||||
i_lib = 0; i_obj = 0; // will hold the index of the lib and first obj
|
i_lib = 0; i_obj = 0; // will hold the index of the lib and first obj
|
||||||
for (i = 1; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
const char *a = argv[i];
|
const char *a = argv[i];
|
||||||
if (*a == '-' && strstr(a, "."))
|
if (*a == '-' && strchr(a, '.'))
|
||||||
ret = 1; // -x.y is always invalid (same as gnu ar)
|
ret = 1; // -x.y is always invalid (same as gnu ar)
|
||||||
if ((*a == '-') || (i == 1 && !strstr(a, "."))) { // options argument
|
if ((*a == '-') || (i == 1 && !strchr(a, '.'))) { // options argument
|
||||||
if (contains_any(a, ops_conflict))
|
if (strpbrk(a, ops_conflict))
|
||||||
ret = 1;
|
ret = 1;
|
||||||
if (strstr(a, "v"))
|
if (strchr(a, 'x'))
|
||||||
|
extract = 1;
|
||||||
|
if (strchr(a, 't'))
|
||||||
|
table = 1;
|
||||||
|
if (strchr(a, 'v'))
|
||||||
verbose = 1;
|
verbose = 1;
|
||||||
} else { // lib or obj files: don't abort - keep validating all args.
|
} else { // lib or obj files: don't abort - keep validating all args.
|
||||||
if (!i_lib) // first file is the lib
|
if (!i_lib) // first file is the lib
|
||||||
@ -122,17 +110,75 @@ ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!i_obj) // i_obj implies also i_lib. we require both.
|
if (!i_lib) // i_obj implies also i_lib.
|
||||||
ret = 1;
|
ret = 1;
|
||||||
|
i_obj = i_obj ? i_obj : argc; // An empty archive will be generated if no input file is given
|
||||||
|
|
||||||
if (ret == 1)
|
if (ret == 1)
|
||||||
return ar_usage(ret);
|
return ar_usage(ret);
|
||||||
|
|
||||||
|
if (extract || table) {
|
||||||
|
if ((fh = fopen(argv[i_lib], "rb")) == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "tcc: ar: can't open file %s\n", argv[i_lib]);
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
fread(stmp, 1, 8, fh);
|
||||||
|
if (memcmp(stmp,ARMAG,8))
|
||||||
|
{
|
||||||
|
no_ar:
|
||||||
|
fprintf(stderr, "tcc: ar: not an ar archive %s\n", argv[i_lib]);
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
while (fread(&arhdr, 1, sizeof(arhdr), fh) == sizeof(arhdr)) {
|
||||||
|
char *p, *e;
|
||||||
|
|
||||||
|
if (memcmp(arhdr.ar_fmag, ARFMAG, 2))
|
||||||
|
goto no_ar;
|
||||||
|
p = arhdr.ar_name;
|
||||||
|
for (e = p + sizeof arhdr.ar_name; e > p && e[-1] == ' ';)
|
||||||
|
e--;
|
||||||
|
*e = '\0';
|
||||||
|
arhdr.ar_size[sizeof arhdr.ar_size-1] = 0;
|
||||||
|
fsize = atoi(arhdr.ar_size);
|
||||||
|
buf = tcc_malloc(fsize + 1);
|
||||||
|
fread(buf, fsize, 1, fh);
|
||||||
|
if (strcmp(arhdr.ar_name,"/") && strcmp(arhdr.ar_name,"/SYM64/")) {
|
||||||
|
if (e > p && e[-1] == '/')
|
||||||
|
e[-1] = '\0';
|
||||||
|
/* tv not implemented */
|
||||||
|
if (table || verbose)
|
||||||
|
printf("%s%s\n", extract ? "x - " : "", arhdr.ar_name);
|
||||||
|
if (extract) {
|
||||||
|
if ((fo = fopen(arhdr.ar_name, "wb")) == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "tcc: ar: can't create file %s\n",
|
||||||
|
arhdr.ar_name);
|
||||||
|
tcc_free(buf);
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
fwrite(buf, fsize, 1, fo);
|
||||||
|
fclose(fo);
|
||||||
|
/* ignore date/uid/gid/mode */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fsize & 1)
|
||||||
|
fgetc(fh);
|
||||||
|
tcc_free(buf);
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
finish:
|
||||||
|
if (fh)
|
||||||
|
fclose(fh);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
if ((fh = fopen(argv[i_lib], "wb")) == NULL)
|
if ((fh = fopen(argv[i_lib], "wb")) == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "tcc: ar: can't open file %s \n", argv[i_lib]);
|
fprintf(stderr, "tcc: ar: can't create file %s\n", argv[i_lib]);
|
||||||
goto the_end;
|
goto the_end;
|
||||||
}
|
}
|
||||||
|
created_file = argv[i_lib];
|
||||||
|
|
||||||
sprintf(tfile, "%s.tmp", argv[i_lib]);
|
sprintf(tfile, "%s.tmp", argv[i_lib]);
|
||||||
if ((fo = fopen(tfile, "wb+")) == NULL)
|
if ((fo = fopen(tfile, "wb+")) == NULL)
|
||||||
@ -143,7 +189,7 @@ ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
|
|||||||
|
|
||||||
funcmax = 250;
|
funcmax = 250;
|
||||||
afpos = tcc_realloc(NULL, funcmax * sizeof *afpos); // 250 func
|
afpos = tcc_realloc(NULL, funcmax * sizeof *afpos); // 250 func
|
||||||
memcpy(&arhdro.ar_mode, "100666", 6);
|
memcpy(&arhdro.ar_mode, "100644", 6);
|
||||||
|
|
||||||
// i_obj = first input object file
|
// i_obj = first input object file
|
||||||
while (i_obj < argc)
|
while (i_obj < argc)
|
||||||
@ -176,6 +222,7 @@ ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
|
|||||||
|
|
||||||
shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + ehdr->e_shstrndx * ehdr->e_shentsize);
|
shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + ehdr->e_shstrndx * ehdr->e_shentsize);
|
||||||
shstr = (char *)(buf + shdr->sh_offset);
|
shstr = (char *)(buf + shdr->sh_offset);
|
||||||
|
symtab = strtab = NULL;
|
||||||
for (i = 0; i < ehdr->e_shnum; i++)
|
for (i = 0; i < ehdr->e_shnum; i++)
|
||||||
{
|
{
|
||||||
shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + i * ehdr->e_shentsize);
|
shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + i * ehdr->e_shentsize);
|
||||||
@ -196,7 +243,7 @@ ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (symtab && symtabsize)
|
if (symtab && strtab)
|
||||||
{
|
{
|
||||||
int nsym = symtabsize / sizeof(ElfW(Sym));
|
int nsym = symtabsize / sizeof(ElfW(Sym));
|
||||||
//printf("symtab: info size shndx name\n");
|
//printf("symtab: info size shndx name\n");
|
||||||
@ -207,6 +254,9 @@ ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
|
|||||||
(sym->st_info == 0x10
|
(sym->st_info == 0x10
|
||||||
|| sym->st_info == 0x11
|
|| sym->st_info == 0x11
|
||||||
|| sym->st_info == 0x12
|
|| sym->st_info == 0x12
|
||||||
|
|| sym->st_info == 0x20
|
||||||
|
|| sym->st_info == 0x21
|
||||||
|
|| sym->st_info == 0x22
|
||||||
)) {
|
)) {
|
||||||
//printf("symtab: %2Xh %4Xh %2Xh %s\n", sym->st_info, sym->st_size, sym->st_shndx, strtab + sym->st_name);
|
//printf("symtab: %2Xh %4Xh %2Xh %s\n", sym->st_info, sym->st_size, sym->st_shndx, strtab + sym->st_name);
|
||||||
istrlen = strlen(strtab + sym->st_name)+1;
|
istrlen = strlen(strtab + sym->st_name)+1;
|
||||||
@ -239,14 +289,21 @@ ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
|
|||||||
tcc_free(buf);
|
tcc_free(buf);
|
||||||
i_obj++;
|
i_obj++;
|
||||||
fpos += (fsize + sizeof(arhdro));
|
fpos += (fsize + sizeof(arhdro));
|
||||||
|
if (fpos & 1)
|
||||||
|
fputc(0, fo), ++fpos;
|
||||||
}
|
}
|
||||||
hofs = 8 + sizeof(arhdr) + strpos + (funccnt+1) * sizeof(int);
|
hofs = 8 + sizeof(arhdr) + strpos + (funccnt+1) * sizeof(int);
|
||||||
fpos = 0;
|
fpos = 0;
|
||||||
if ((hofs & 1)) // align
|
if ((hofs & 1)) // align
|
||||||
hofs++, fpos = 1;
|
hofs++, fpos = 1;
|
||||||
// write header
|
// write header
|
||||||
fwrite("!<arch>\n", 8, 1, fh);
|
fwrite(ARMAG, 8, 1, fh);
|
||||||
sprintf(stmp, "%-10d", (int)(strpos + (funccnt+1) * sizeof(int)));
|
// create an empty archive
|
||||||
|
if (!funccnt) {
|
||||||
|
ret = 0;
|
||||||
|
goto the_end;
|
||||||
|
}
|
||||||
|
sprintf(stmp, "%-10d", (int)(strpos + (funccnt+1) * sizeof(int)) + fpos);
|
||||||
memcpy(&arhdr.ar_size, stmp, 10);
|
memcpy(&arhdr.ar_size, stmp, 10);
|
||||||
fwrite(&arhdr, sizeof(arhdr), 1, fh);
|
fwrite(&arhdr, sizeof(arhdr), 1, fh);
|
||||||
afpos[0] = le2belong(funccnt);
|
afpos[0] = le2belong(funccnt);
|
||||||
@ -272,6 +329,8 @@ the_end:
|
|||||||
tcc_free(afpos);
|
tcc_free(afpos);
|
||||||
if (fh)
|
if (fh)
|
||||||
fclose(fh);
|
fclose(fh);
|
||||||
|
if (created_file && ret != 0)
|
||||||
|
remove(created_file);
|
||||||
if (fo)
|
if (fo)
|
||||||
fclose(fo), remove(tfile);
|
fclose(fo), remove(tfile);
|
||||||
return ret;
|
return ret;
|
||||||
@ -301,7 +360,7 @@ the_end:
|
|||||||
|
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
|
|
||||||
ST_FUNC int tcc_tool_impdef(TCCState *s1, int argc, char **argv)
|
ST_FUNC int tcc_tool_impdef(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int ret, v, i;
|
int ret, v, i;
|
||||||
char infile[260];
|
char infile[260];
|
||||||
@ -392,10 +451,8 @@ usage:
|
|||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
the_end:
|
the_end:
|
||||||
/* cannot free memory received from tcc_get_dllexports
|
if (p)
|
||||||
if it came from a dll */
|
tcc_free(p);
|
||||||
/* if (p)
|
|
||||||
tcc_free(p); */
|
|
||||||
if (fp)
|
if (fp)
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
if (op)
|
if (op)
|
||||||
@ -430,37 +487,48 @@ the_end:
|
|||||||
|
|
||||||
#if !defined TCC_TARGET_I386 && !defined TCC_TARGET_X86_64
|
#if !defined TCC_TARGET_I386 && !defined TCC_TARGET_X86_64
|
||||||
|
|
||||||
ST_FUNC void tcc_tool_cross(TCCState *s, char **argv, int option)
|
ST_FUNC int tcc_tool_cross(char **argv, int option)
|
||||||
{
|
{
|
||||||
tcc_error("-m%d not implemented.", option);
|
fprintf(stderr, "tcc -m%d not implemented\n", option);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <process.h>
|
#include <process.h>
|
||||||
|
|
||||||
static char *str_replace(const char *str, const char *p, const char *r)
|
/* - Empty argument or with space/tab (not newline) requires quoting.
|
||||||
|
* - Double-quotes at the value require '\'-escape, regardless of quoting.
|
||||||
|
* - Consecutive (or 1) backslashes at the value all need '\'-escape only if
|
||||||
|
* followed by [escaped] double quote, else taken literally, e.g. <x\\y\>
|
||||||
|
* remains literal without quoting or esc, but <x\\"y\> becomes <x\\\\\"y\>.
|
||||||
|
* - This "before double quote" rule applies also before delimiting quoting,
|
||||||
|
* e.g. <x\y \"z\> becomes <"x\y \\\"z\\"> (quoting required because space).
|
||||||
|
*
|
||||||
|
* https://learn.microsoft.com/en-us/cpp/c-language/parsing-c-command-line-arguments
|
||||||
|
*/
|
||||||
|
static char *quote_win32(const char *s)
|
||||||
{
|
{
|
||||||
const char *s, *s0;
|
char *o, *r = tcc_malloc(2 * strlen(s) + 3); /* max-esc, quotes, \0 */
|
||||||
char *d, *d0;
|
int cbs = 0, quoted = !*s; /* consecutive backslashes before current */
|
||||||
int sl, pl, rl;
|
|
||||||
|
|
||||||
sl = strlen(str);
|
for (o = r; *s; *o++ = *s++) {
|
||||||
pl = strlen(p);
|
quoted |= *s == ' ' || *s == '\t';
|
||||||
rl = strlen(r);
|
if (*s == '\\' || *s == '"')
|
||||||
for (d0 = NULL;; d0 = tcc_malloc(sl + 1)) {
|
*o++ = '\\';
|
||||||
for (d = d0, s = str; s0 = s, s = strstr(s, p), s; s += pl) {
|
else
|
||||||
if (d) {
|
o -= cbs; /* undo cbs escapes, if any (not followed by DQ) */
|
||||||
memcpy(d, s0, sl = s - s0), d += sl;
|
cbs = *s == '\\' ? cbs + 1 : 0;
|
||||||
memcpy(d, r, rl), d += rl;
|
|
||||||
} else
|
|
||||||
sl += rl - pl;
|
|
||||||
}
|
|
||||||
if (d) {
|
|
||||||
strcpy(d, s0);
|
|
||||||
return d0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (quoted) {
|
||||||
|
memmove(r + 1, r, o++ - r);
|
||||||
|
*r = *o++ = '"';
|
||||||
|
} else {
|
||||||
|
o -= cbs;
|
||||||
|
}
|
||||||
|
|
||||||
|
*o = 0;
|
||||||
|
return r; /* don't bother with realloc(r, o-r+1) */
|
||||||
}
|
}
|
||||||
|
|
||||||
static int execvp_win32(const char *prog, char **argv)
|
static int execvp_win32(const char *prog, char **argv)
|
||||||
@ -468,8 +536,7 @@ static int execvp_win32(const char *prog, char **argv)
|
|||||||
int ret; char **p;
|
int ret; char **p;
|
||||||
/* replace all " by \" */
|
/* replace all " by \" */
|
||||||
for (p = argv; *p; ++p)
|
for (p = argv; *p; ++p)
|
||||||
if (strchr(*p, '"'))
|
*p = quote_win32(*p);
|
||||||
*p = str_replace(*p, "\"", "\\\"");
|
|
||||||
ret = _spawnvp(P_NOWAIT, prog, (const char *const*)argv);
|
ret = _spawnvp(P_NOWAIT, prog, (const char *const*)argv);
|
||||||
if (-1 == ret)
|
if (-1 == ret)
|
||||||
return ret;
|
return ret;
|
||||||
@ -479,7 +546,7 @@ static int execvp_win32(const char *prog, char **argv)
|
|||||||
#define execvp execvp_win32
|
#define execvp execvp_win32
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
ST_FUNC void tcc_tool_cross(TCCState *s, char **argv, int target)
|
ST_FUNC int tcc_tool_cross(char **argv, int target)
|
||||||
{
|
{
|
||||||
char program[4096];
|
char program[4096];
|
||||||
char *a0 = argv[0];
|
char *a0 = argv[0];
|
||||||
@ -498,7 +565,8 @@ ST_FUNC void tcc_tool_cross(TCCState *s, char **argv, int target)
|
|||||||
|
|
||||||
if (strcmp(a0, program))
|
if (strcmp(a0, program))
|
||||||
execvp(argv[0] = program, argv);
|
execvp(argv[0] = program, argv);
|
||||||
tcc_error("could not run '%s'", program);
|
fprintf(stderr, "tcc: could not run '%s'\n", program);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* TCC_TARGET_I386 && TCC_TARGET_X86_64 */
|
#endif /* TCC_TARGET_I386 && TCC_TARGET_X86_64 */
|
||||||
@ -506,20 +574,34 @@ ST_FUNC void tcc_tool_cross(TCCState *s, char **argv, int target)
|
|||||||
/* enable commandline wildcard expansion (tcc -o x.exe *.c) */
|
/* enable commandline wildcard expansion (tcc -o x.exe *.c) */
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
int _CRT_glob = 1;
|
const int _CRT_glob = 1;
|
||||||
#ifndef _CRT_glob
|
#ifndef _CRT_glob
|
||||||
int _dowildcard = 1;
|
const int _dowildcard = 1;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* -------------------------------------------------------------- */
|
/* -------------------------------------------------------------- */
|
||||||
/* generate xxx.d file */
|
/* generate xxx.d file */
|
||||||
|
|
||||||
ST_FUNC void gen_makedeps(TCCState *s, const char *target, const char *filename)
|
static char *escape_target_dep(const char *s) {
|
||||||
|
char *res = tcc_malloc(strlen(s) * 2 + 1);
|
||||||
|
int j;
|
||||||
|
for (j = 0; *s; s++, j++) {
|
||||||
|
if (is_space(*s)) {
|
||||||
|
res[j++] = '\\';
|
||||||
|
}
|
||||||
|
res[j] = *s;
|
||||||
|
}
|
||||||
|
res[j] = '\0';
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
ST_FUNC int gen_makedeps(TCCState *s1, const char *target, const char *filename)
|
||||||
{
|
{
|
||||||
FILE *depout;
|
FILE *depout;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
int i;
|
char **escaped_targets;
|
||||||
|
int i, k, num_targets;
|
||||||
|
|
||||||
if (!filename) {
|
if (!filename) {
|
||||||
/* compute filename automatically: dir/file.o -> dir/file.d */
|
/* compute filename automatically: dir/file.o -> dir/file.d */
|
||||||
@ -528,19 +610,42 @@ ST_FUNC void gen_makedeps(TCCState *s, const char *target, const char *filename)
|
|||||||
filename = buf;
|
filename = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->verbose)
|
if(!strcmp(filename, "-"))
|
||||||
|
depout = fdopen(1, "w");
|
||||||
|
else
|
||||||
|
/* XXX return err codes instead of error() ? */
|
||||||
|
depout = fopen(filename, "w");
|
||||||
|
if (!depout)
|
||||||
|
return tcc_error_noabort("could not open '%s'", filename);
|
||||||
|
if (s1->verbose)
|
||||||
printf("<- %s\n", filename);
|
printf("<- %s\n", filename);
|
||||||
|
|
||||||
/* XXX return err codes instead of error() ? */
|
escaped_targets = tcc_malloc(s1->nb_target_deps * sizeof(*escaped_targets));
|
||||||
depout = fopen(filename, "w");
|
num_targets = 0;
|
||||||
if (!depout)
|
for (i = 0; i<s1->nb_target_deps; ++i) {
|
||||||
tcc_error("could not open '%s'", filename);
|
for (k = 0; k < i; ++k)
|
||||||
|
if (0 == strcmp(s1->target_deps[i], s1->target_deps[k]))
|
||||||
|
goto next;
|
||||||
|
escaped_targets[num_targets++] = escape_target_dep(s1->target_deps[i]);
|
||||||
|
next:;
|
||||||
|
}
|
||||||
|
|
||||||
fprintf(depout, "%s: \\\n", target);
|
fprintf(depout, "%s:", target);
|
||||||
for (i=0; i<s->nb_target_deps; ++i)
|
for (i = 0; i < num_targets; ++i)
|
||||||
fprintf(depout, " %s \\\n", s->target_deps[i]);
|
fprintf(depout, " \\\n %s", escaped_targets[i]);
|
||||||
fprintf(depout, "\n");
|
fprintf(depout, "\n");
|
||||||
|
if (s1->gen_phony_deps) {
|
||||||
|
/* Skip first file, which is the c file.
|
||||||
|
* Only works for single file give on command-line,
|
||||||
|
* but other compilers have the same limitation */
|
||||||
|
for (i = 1; i < num_targets; ++i)
|
||||||
|
fprintf(depout, "%s:\n", escaped_targets[i]);
|
||||||
|
}
|
||||||
|
for (i = 0; i < num_targets; ++i)
|
||||||
|
tcc_free(escaped_targets[i]);
|
||||||
|
tcc_free(escaped_targets);
|
||||||
fclose(depout);
|
fclose(depout);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------------------------- */
|
/* -------------------------------------------------------------- */
|
||||||
|
|||||||
268
tests/Makefile
268
tests/Makefile
@ -4,62 +4,87 @@
|
|||||||
|
|
||||||
TOP = ..
|
TOP = ..
|
||||||
include $(TOP)/Makefile
|
include $(TOP)/Makefile
|
||||||
VPATH = $(TOPSRC)/tests $(TOPSRC) $(TOP)
|
VPATH = $(TOPSRC)/tests $(TOPSRC)
|
||||||
CFLAGS := $(filter-out -W% -g% -O%,$(CFLAGS)) -I$(TOPSRC) $(LDFLAGS)
|
CFLAGS := $(filter-out -g% -O%,$(CFLAGS)) -I$(TOPSRC) -I$(TOP) $(LDFLAGS)
|
||||||
|
|
||||||
# what tests to run
|
# what tests to run
|
||||||
TESTS = \
|
TESTS = \
|
||||||
hello-exe \
|
hello-exe \
|
||||||
hello-run \
|
hello-run \
|
||||||
libtest \
|
libtest \
|
||||||
|
libtest_mt \
|
||||||
test3 \
|
test3 \
|
||||||
memtest \
|
|
||||||
dlltest \
|
|
||||||
abitest \
|
abitest \
|
||||||
asm-c-connect-test \
|
asm-c-connect-test \
|
||||||
vla_test-run \
|
vla_test-run \
|
||||||
cross-test \
|
|
||||||
tests2-dir \
|
tests2-dir \
|
||||||
pp-dir
|
pp-dir \
|
||||||
|
memtest \
|
||||||
|
dlltest \
|
||||||
|
cross-test
|
||||||
|
|
||||||
BTESTS = test1b test3b btest
|
# test4_static -- Not all relocation types are implemented yet.
|
||||||
|
|
||||||
# test4 -- problem with -static
|
|
||||||
# asmtest / asmtest2 -- minor differences with gcc
|
# asmtest / asmtest2 -- minor differences with gcc
|
||||||
# btest -- works on i386 (including win32)
|
|
||||||
|
|
||||||
# bounds-checking is supported only on i386
|
ifeq ($(CONFIG_backtrace),no)
|
||||||
ifneq ($(ARCH),i386)
|
TESTS := $(filter-out libtest_mt, $(TESTS))
|
||||||
TESTS := $(filter-out $(BTESTS),$(TESTS))
|
else ifneq ($(CONFIG_bcheck),no)
|
||||||
|
TESTS += btest test1b tccb
|
||||||
endif
|
endif
|
||||||
ifdef CONFIG_WIN32
|
ifeq ($(CONFIG_dll),no)
|
||||||
TESTS := $(filter-out $(BTESTS),$(TESTS))
|
TESTS := $(filter-out dlltest, $(TESTS))
|
||||||
endif
|
endif
|
||||||
ifdef CONFIG_OSX # -run only
|
ifeq (-$(CONFIG_arm_eabi)-$(CONFIG_arm_vfp)-,-yes--)
|
||||||
TESTS := hello-run libtest tests2-dir pp-dir
|
TESTS := $(filter-out test3 test1b,$(TESTS))
|
||||||
endif
|
|
||||||
ifeq (,$(filter arm64 i386 x86_64,$(ARCH)))
|
|
||||||
TESTS := $(filter-out vla_test-run,$(TESTS))
|
|
||||||
endif
|
|
||||||
ifeq ($(CONFIG_arm_eabi),yes)
|
|
||||||
TESTS := $(filter-out test3,$(TESTS))
|
|
||||||
endif
|
endif
|
||||||
ifeq (,$(filter i386 x86_64,$(ARCH)))
|
ifeq (,$(filter i386 x86_64,$(ARCH)))
|
||||||
TESTS := $(filter-out dlltest asm-c-connect-test,$(TESTS))
|
TESTS := $(filter-out asm-c-connect-test,$(TESTS))
|
||||||
endif
|
endif
|
||||||
ifndef CONFIG_cross
|
|
||||||
TESTS := $(filter-out cross-%,$(TESTS))
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(OS),Windows_NT) # for libtcc_test to find libtcc.dll
|
ifeq ($(OS),Windows_NT) # for libtcc_test to find libtcc.dll
|
||||||
PATH := $(CURDIR)/$(TOP)$(if $(findstring :\,$(PATH)),;,:)$(PATH)
|
PATH := $(CURDIR)/$(TOP)$(if $(findstring ;,$(PATH)),;,:)$(PATH)
|
||||||
|
endif
|
||||||
|
ifdef CONFIG_OSX
|
||||||
|
LIBS += $(LINK_LIBTCC)
|
||||||
|
endif
|
||||||
|
ifeq ($(ARCH),arm)
|
||||||
|
# tcctest refers to the alignment of functions, and with thumb mode
|
||||||
|
# the low bit of code addresses selects the mode, so the "alignment"
|
||||||
|
# of functions via bit masking comes out as 1. Just disable thumb.
|
||||||
|
test.ref: CFLAGS+=-marm
|
||||||
|
endif
|
||||||
|
ifeq ($(ARCH)$(CONFIG_WIN32),i386)
|
||||||
|
# tcctest.c:get_asm_string uses a construct that is checked too strictly
|
||||||
|
# by GCC in 32bit mode when PIC is enabled.
|
||||||
|
test.ref: CFLAGS+=-fno-PIC -fno-PIE -Wl,-z,notext
|
||||||
|
endif
|
||||||
|
ifeq ($(CC_NAME),msvc)
|
||||||
|
test.ref abitest : CC = gcc
|
||||||
|
endif
|
||||||
|
ifeq ($(TARGETOS),OpenBSD)
|
||||||
|
dlltest: CFLAGS+=-fno-stack-protector
|
||||||
|
endif
|
||||||
|
ifneq (,$(filter FreeBSD NetBSD,$(TARGETOS)))
|
||||||
|
# test3 has dlsym problems
|
||||||
|
TESTS := $(filter-out test3,$(TESTS))
|
||||||
|
TESTS += test1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
RUN_TCC = $(NATIVE_DEFINES) -run $(TOPSRC)/tcc.c $(TCCFLAGS)
|
RUN_TCC = -run $(TOPSRC)/tcc.c $(TCCFLAGS)
|
||||||
DISAS = objdump -d
|
DISAS = objdump -d
|
||||||
DUMPTCC = (set -x; $(TOP)/tcc -vv; ldd $(TOP)/tcc; exit 1)
|
ifdef CONFIG_OSX
|
||||||
|
DUMPTCC = (set -x; $(TCC_LOCAL) -vv; otool -L $(TCC_LOCAL); exit 1)
|
||||||
|
else
|
||||||
|
DUMPTCC = (set -x; $(TCC_LOCAL) -vv; ldd $(TCC_LOCAL); exit 1)
|
||||||
|
endif
|
||||||
|
|
||||||
all test : clean-s $(TESTS)
|
all test :
|
||||||
|
@echo ------------ version ------------
|
||||||
|
@$(TCC_LOCAL) -v
|
||||||
|
@$(MAKE) --no-print-directory -s clean
|
||||||
|
@$(MAKE) --no-print-directory -s -r _all
|
||||||
|
@echo ------- ALL TESTS PASSED --------
|
||||||
|
|
||||||
|
_all : $(TESTS)
|
||||||
|
|
||||||
hello-exe: ../examples/ex1.c
|
hello-exe: ../examples/ex1.c
|
||||||
@echo ------------ $@ ------------
|
@echo ------------ $@ ------------
|
||||||
@ -69,12 +94,15 @@ hello-run: ../examples/ex1.c
|
|||||||
@echo ------------ $@ ------------
|
@echo ------------ $@ ------------
|
||||||
$(TCC) -run $< || $(DUMPTCC)
|
$(TCC) -run $< || $(DUMPTCC)
|
||||||
|
|
||||||
libtest: libtcc_test$(EXESUF)
|
libtes%: libtcc_tes%$(EXESUF)
|
||||||
@echo ------------ $@ ------------
|
@echo ------------ $@ ------------
|
||||||
./libtcc_test$(EXESUF) $(TCCFLAGS)
|
./libtcc_tes$*$(EXESUF) $(TOPSRC)/tcc.c $(TCCFLAGS)
|
||||||
|
|
||||||
libtcc_test$(EXESUF): libtcc_test.c $(LIBTCC)
|
libtcc_test$(EXESUF): libtcc_test.c
|
||||||
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
|
$(CC) -o $@ $< $(CFLAGS) $(-LTCC) $(LIBS)
|
||||||
|
|
||||||
|
libtcc_test_mt$(EXESUF): libtcc_test_mt.c
|
||||||
|
$(CC) -o $@ $< $(CFLAGS) $(-LTCC) $(LIBS)
|
||||||
|
|
||||||
%-dir:
|
%-dir:
|
||||||
@echo ------------ $@ ------------
|
@echo ------------ $@ ------------
|
||||||
@ -82,28 +110,30 @@ libtcc_test$(EXESUF): libtcc_test.c $(LIBTCC)
|
|||||||
|
|
||||||
# test.ref - generate using cc
|
# test.ref - generate using cc
|
||||||
test.ref: tcctest.c
|
test.ref: tcctest.c
|
||||||
$(CC) -o tcctest.gcc $< $(NATIVE_DEFINES) $(CFLAGS) -w -O0 -std=gnu99 -fno-omit-frame-pointer
|
$(CC) -o tcctest.gcc$(EXESUF) $< $(CFLAGS) -w -O0 -std=gnu99 -fno-omit-frame-pointer
|
||||||
./tcctest.gcc > $@
|
./tcctest.gcc$(EXESUF) > $@
|
||||||
|
|
||||||
# auto test
|
# auto test
|
||||||
test1 test1b: tcctest.c test.ref
|
test1 test1b: tcctest.c test.ref
|
||||||
@echo ------------ $@ ------------
|
@echo ------------ $@ ------------
|
||||||
$(TCC) -run $< > test.out1
|
$(TCC) $(RUN_TCC) -w -run $< > test.out1
|
||||||
@diff -u test.ref test.out1 && echo "Auto Test OK"
|
@diff -u test.ref test.out1 && echo "$(AUTO_TEST) OK"
|
||||||
|
|
||||||
# iterated test2 (compile tcc then compile tcctest.c !)
|
# iterated test2 (compile tcc then compile tcctest.c !)
|
||||||
test2 test2b: tcctest.c test.ref
|
test2 test2b: tcctest.c test.ref
|
||||||
@echo ------------ $@ ------------
|
@echo ------------ $@ ------------
|
||||||
$(TCC) $(RUN_TCC) $(RUN_TCC) -run $< > test.out2
|
$(TCC) $(RUN_TCC) $(RUN_TCC) -w -run $< > test.out2
|
||||||
@diff -u test.ref test.out2 && echo "Auto Test2 OK"
|
@diff -u test.ref test.out2 && echo "$(AUTO_TEST)2 OK"
|
||||||
|
|
||||||
# iterated test3 (compile tcc then compile tcc then compile tcctest.c !)
|
# iterated test3 (compile tcc then compile tcc then compile tcctest.c !)
|
||||||
test3 test3b: tcctest.c test.ref
|
test3 test3b: tcctest.c test.ref
|
||||||
@echo ------------ $@ ------------
|
@echo ------------ $@ ------------
|
||||||
$(TCC) $(RUN_TCC) $(RUN_TCC) $(RUN_TCC) -run $< > test.out3
|
$(TCC) $(RUN_TCC) $(RUN_TCC) $(RUN_TCC) -w -run $< > test.out3
|
||||||
@diff -u test.ref test.out3 && echo "Auto Test3 OK"
|
@diff -u test.ref test.out3 && echo "$(AUTO_TEST)3 OK"
|
||||||
|
|
||||||
test%b : TCCFLAGS += -b
|
AUTO_TEST = Auto Test
|
||||||
|
test%b : TCCFLAGS += -b -bt1
|
||||||
|
test%b : AUTO_TEST = Auto Bound-Test
|
||||||
|
|
||||||
# binary output test
|
# binary output test
|
||||||
test4: tcctest.c test.ref
|
test4: tcctest.c test.ref
|
||||||
@ -112,65 +142,74 @@ test4: tcctest.c test.ref
|
|||||||
$(TCC) -c -o tcctest3.o $<
|
$(TCC) -c -o tcctest3.o $<
|
||||||
$(TCC) -o tcctest3 tcctest3.o
|
$(TCC) -o tcctest3 tcctest3.o
|
||||||
./tcctest3 > test3.out
|
./tcctest3 > test3.out
|
||||||
@if diff -u test.ref test3.out ; then echo "Object Auto Test OK"; fi
|
@if diff -u test.ref test3.out ; then echo "Object $(AUTO_TEST) OK"; fi
|
||||||
# dynamic output
|
# dynamic output
|
||||||
$(TCC) -o tcctest1 $<
|
$(TCC) -o tcctest1 $<
|
||||||
./tcctest1 > test1.out
|
./tcctest1 > test1.out
|
||||||
@if diff -u test.ref test1.out ; then echo "Dynamic Auto Test OK"; fi
|
@if diff -u test.ref test1.out ; then echo "Dynamic $(AUTO_TEST) OK"; fi
|
||||||
# dynamic output + bound check
|
# dynamic output + bound check
|
||||||
$(TCC) -b -o tcctest4 $<
|
$(TCC) -b -o tcctest4 $<
|
||||||
./tcctest4 > test4.out
|
./tcctest4 > test4.out
|
||||||
@if diff -u test.ref test4.out ; then echo "BCheck Auto Test OK"; fi
|
@if diff -u test.ref test4.out ; then echo "BCheck $(AUTO_TEST) OK"; fi
|
||||||
# static output
|
|
||||||
|
test4_static: tcctest.c test.ref
|
||||||
|
@echo ------------ $@ ------------
|
||||||
|
# static output.
|
||||||
$(TCC) -static -o tcctest2 $<
|
$(TCC) -static -o tcctest2 $<
|
||||||
./tcctest2 > test2.out
|
./tcctest2 > test2.out
|
||||||
@if diff -u test.ref test2.out ; then echo "Static Auto Test OK"; fi
|
@if diff -u test.ref test2.out ; then echo "Static $(AUTO_TEST) OK"; fi
|
||||||
|
|
||||||
# use tcc to create libtcc.so/.dll and the tcc(.exe) frontend and run them
|
# use tcc to create libtcc.so/.dll and the tcc(.exe) frontend and run them
|
||||||
dlltest:
|
dlltest:
|
||||||
@echo ------------ $@ ------------
|
@echo ------------ $@ ------------
|
||||||
$(TCC) $(NATIVE_DEFINES) -DLIBTCC_AS_DLL $(TOPSRC)/libtcc.c $(LIBS) -shared -o libtcc2$(DLLSUF)
|
$(TCC) -DLIBTCC_AS_DLL $(TOPSRC)/libtcc.c $(LIBS) -shared -o libtcc2$(DLLSUF)
|
||||||
$(TCC) $(NATIVE_DEFINES) -DONE_SOURCE=0 $(TOPSRC)/tcc.c libtcc2$(DLLSUF) $(LIBS) -Wl,-rpath=. -o tcc2$(EXESUF)
|
$(TCC) -DONE_SOURCE=0 $(TOPSRC)/tcc.c libtcc2$(DLLSUF) $(LIBS) -Wl,-rpath=. -o tcc2$(EXESUF)
|
||||||
./tcc2$(EXESUF) $(TCCFLAGS) $(RUN_TCC) -run $(TOPSRC)/examples/ex1.c
|
./tcc2$(EXESUF) $(TCCFLAGS) $(RUN_TCC) -run $(TOPSRC)/examples/ex1.c
|
||||||
ifndef CONFIG_WIN32
|
ifeq (,$(filter Darwin WIN32,$(TARGETOS)))
|
||||||
@echo ------------ $@ with PIC ------------
|
@echo ------------ $@ with PIC ------------
|
||||||
$(CC) $(CFLAGS) -fPIC $(NATIVE_DEFINES) -DLIBTCC_AS_DLL -c $(TOPSRC)/libtcc.c
|
$(CC) $(CFLAGS) -fPIC -DLIBTCC_AS_DLL -c $(TOPSRC)/libtcc.c
|
||||||
$(TCC) libtcc.o $(LIBS) -shared -o libtcc2$(DLLSUF)
|
$(TCC) libtcc.o $(LIBS) -shared -o libtcc2$(DLLSUF)
|
||||||
$(TCC) $(NATIVE_DEFINES) -DONE_SOURCE=0 $(TOPSRC)/tcc.c libtcc2$(DLLSUF) $(LIBS) -Wl,-rpath=. -o tcc2$(EXESUF)
|
$(TCC) -DONE_SOURCE=0 $(TOPSRC)/tcc.c libtcc2$(DLLSUF) $(LIBS) -Wl,-rpath=. -o tcc2$(EXESUF)
|
||||||
./tcc2$(EXESUF) $(TCCFLAGS) $(RUN_TCC) -run $(TOPSRC)/examples/ex1.c
|
./tcc2$(EXESUF) $(TCCFLAGS) $(RUN_TCC) -run $(TOPSRC)/examples/ex1.c
|
||||||
endif
|
endif
|
||||||
@rm tcc2$(EXESUF) libtcc2$(DLLSUF)
|
@rm tcc2$(EXESUF) libtcc2$(DLLSUF)
|
||||||
|
|
||||||
memtest:
|
memtest:
|
||||||
@echo ------------ $@ ------------
|
@echo ------------ $@ ------------
|
||||||
$(CC) $(CFLAGS) $(NATIVE_DEFINES) -DMEM_DEBUG=2 $(TOPSRC)/tcc.c $(LIBS) -o memtest-tcc$(EXESUF)
|
$(CC) $(CFLAGS) -DMEM_DEBUG=2 $(TOPSRC)/tcc.c $(LIBS) -o memtest-tcc$(EXESUF)
|
||||||
./memtest-tcc$(EXESUF) $(TCCFLAGS) $(NATIVE_DEFINES) $(TOPSRC)/tcc.c $(LIBS)
|
./memtest-tcc$(EXESUF) $(TCCFLAGS) $(TOPSRC)/tcc.c $(LIBS)
|
||||||
./memtest-tcc$(EXESUF) $(TCCFLAGS) $(NATIVE_DEFINES) -run $(TOPSRC)/tcc.c $(TCCFLAGS) $(TOPSRC)/tests/tcctest.c
|
./memtest-tcc$(EXESUF) $(TCCFLAGS) -run $(TOPSRC)/tcc.c $(TCCFLAGS) -w $(TOPSRC)/tests/tcctest.c
|
||||||
|
@echo OK
|
||||||
|
|
||||||
# memory and bound check auto test
|
# memory and bound check auto test
|
||||||
BOUNDS_OK = 1 4 8 10 14
|
BOUNDS_OK = 1 4 8 10 14 16
|
||||||
BOUNDS_FAIL= 2 5 7 9 11 12 13 15
|
BOUNDS_FAIL= 2 5 6 7 9 11 12 13 15 17 18
|
||||||
|
|
||||||
btest: boundtest.c
|
btest: boundtest.c
|
||||||
@echo ------------ $@ ------------
|
@echo ------------ $@ ------------
|
||||||
@for i in $(BOUNDS_OK); do \
|
@for i in $(BOUNDS_OK); do \
|
||||||
echo ; echo --- boundtest $$i ---; \
|
if $(TCC) -b -run $< $$i >/dev/null 2>&1 ; then \
|
||||||
if $(TCC) -b -run $< $$i ; then \
|
echo "Test $$i succeeded as expected" ; \
|
||||||
echo succeeded as expected; \
|
|
||||||
else\
|
else\
|
||||||
echo Failed positive test $$i ; exit 1 ; \
|
echo "Failed positive test $$i" ; exit 1 ; \
|
||||||
fi ;\
|
fi ;\
|
||||||
done ;\
|
done ;\
|
||||||
for i in $(BOUNDS_FAIL); do \
|
for i in $(BOUNDS_FAIL); do \
|
||||||
echo ; echo --- boundtest $$i ---; \
|
if $(TCC) -b -bt1 -run $< $$i >/dev/null 2>&1 ; then \
|
||||||
if $(TCC) -b -run $< $$i ; then \
|
echo "Failed negative test $$i" ; exit 1 ;\
|
||||||
echo Failed negative test $$i ; exit 1 ;\
|
|
||||||
else\
|
else\
|
||||||
echo failed as expected; \
|
echo "Test $$i failed as expected" ; \
|
||||||
fi ;\
|
fi ;\
|
||||||
done ;\
|
done ;\
|
||||||
echo; echo Bound test OK
|
echo Bound-Test OK
|
||||||
|
|
||||||
|
tccb:
|
||||||
|
@echo ------------ $@ ------------
|
||||||
|
$(TCC) -b $(TOPSRC)/tcc.c $(TCCFLAGS) $(LIBS) -o tccb1.exe
|
||||||
|
mv tccb1.exe tccb2.exe
|
||||||
|
./tccb2.exe -b $(TOPSRC)/tcc.c $(TCCFLAGS) $(LIBS) -o tccb1.exe
|
||||||
|
cmp -s tccb1.exe tccb2.exe && echo "Exe Bound-Test OK"
|
||||||
|
|
||||||
|
|
||||||
# speed test
|
# speed test
|
||||||
speedtest: ex2 ex3
|
speedtest: ex2 ex3
|
||||||
@ -181,8 +220,9 @@ speedtest: ex2 ex3
|
|||||||
time $(TCC) -run $(TOPSRC)/examples/ex3.c 35
|
time $(TCC) -run $(TOPSRC)/examples/ex3.c 35
|
||||||
|
|
||||||
weaktest: tcctest.c test.ref
|
weaktest: tcctest.c test.ref
|
||||||
|
@echo ------------ $@ ------------
|
||||||
$(TCC) -c $< -o weaktest.tcc.o
|
$(TCC) -c $< -o weaktest.tcc.o
|
||||||
$(CC) -c $< -o weaktest.gcc.o $(NATIVE_DEFINES) $(CFLAGS) -w -O0 -std=gnu99 -fno-omit-frame-pointer
|
$(CC) -c $< -o weaktest.gcc.o $(CFLAGS) -w -O0 -std=gnu99 -fno-omit-frame-pointer
|
||||||
objdump -t weaktest.tcc.o | grep ' w ' | sed -e 's/.* \([a-zA-Z0-9_]*\)$$/\1/' | LC_ALL=C sort > weaktest.tcc.o.txt
|
objdump -t weaktest.tcc.o | grep ' w ' | sed -e 's/.* \([a-zA-Z0-9_]*\)$$/\1/' | LC_ALL=C sort > weaktest.tcc.o.txt
|
||||||
objdump -t weaktest.gcc.o | grep ' w ' | sed -e 's/.* \([a-zA-Z0-9_]*\)$$/\1/' | LC_ALL=C sort > weaktest.gcc.o.txt
|
objdump -t weaktest.gcc.o | grep ' w ' | sed -e 's/.* \([a-zA-Z0-9_]*\)$$/\1/' | LC_ALL=C sort > weaktest.gcc.o.txt
|
||||||
diff weaktest.gcc.o.txt weaktest.tcc.o.txt && echo "Weak Auto Test OK"
|
diff weaktest.gcc.o.txt weaktest.tcc.o.txt && echo "Weak Auto Test OK"
|
||||||
@ -192,36 +232,38 @@ ex%: $(TOPSRC)/examples/ex%.c
|
|||||||
|
|
||||||
# tiny assembler testing
|
# tiny assembler testing
|
||||||
asmtest.ref: asmtest.S
|
asmtest.ref: asmtest.S
|
||||||
$(CC) -Wa,-W -o asmtest.ref.o -c asmtest.S
|
$(CC) -Wa,-W -Wa,-mx86-used-note=no -o asmtest.ref.o -c asmtest.S
|
||||||
objdump -D asmtest.ref.o > asmtest.ref
|
objdump -D asmtest.ref.o > asmtest.ref
|
||||||
|
|
||||||
|
ifeq ($(ARCH),arm)
|
||||||
|
asmtest asmtest2:
|
||||||
|
TCC="${TCC}" ./arm-asm-testsuite.sh
|
||||||
|
else
|
||||||
asmtest asmtest2: asmtest.ref
|
asmtest asmtest2: asmtest.ref
|
||||||
@echo ------------ $@ ------------
|
@echo ------------ $@ ------------
|
||||||
$(TCC) $(MAYBE_RUN_TCC) -c asmtest.S
|
$(TCC) $(MAYBE_RUN_TCC) -c asmtest.S
|
||||||
objdump -D asmtest.o > asmtest.out
|
objdump -D asmtest.o > asmtest.out
|
||||||
@if diff -u --ignore-matching-lines="file format" asmtest.ref asmtest.out ; then echo "ASM Auto Test OK"; fi
|
@if diff -u --ignore-matching-lines="file format" asmtest.ref asmtest.out ; then echo "ASM Auto Test OK"; fi
|
||||||
|
endif
|
||||||
|
|
||||||
# test assembler with tcc compiled by itself
|
# test assembler with tcc compiled by itself
|
||||||
asmtest2: MAYBE_RUN_TCC = $(RUN_TCC)
|
asmtest2: MAYBE_RUN_TCC = $(RUN_TCC)
|
||||||
|
|
||||||
# Check that code generated by libtcc is binary compatible with
|
# Check that code generated by libtcc is binary compatible with
|
||||||
# that generated by CC
|
# that generated by CC
|
||||||
abitest-cc$(EXESUF): abitest.c $(LIBTCC)
|
abitest-cc.exe: abitest.c
|
||||||
$(CC) -o $@ $^ $(CFLAGS) $(LIBS) -w
|
$(CC) -o $@ $^ $(CFLAGS) $(-LTCC) $(LIBS) -w
|
||||||
|
|
||||||
abitest-tcc$(EXESUF): abitest.c libtcc.c
|
abitest-tcc.exe: abitest.c libtcc.c
|
||||||
$(TCC) -o $@ $^ $(NATIVE_DEFINES) $(LIBS)
|
$(TCC) -o $@ $^ $(LIBS)
|
||||||
|
|
||||||
ABITESTS := abitest-cc$(EXESUF)
|
abitest-% : abitest-%.exe
|
||||||
ifneq ($(CONFIG_arm_eabi),yes) # not ARM soft-float
|
|
||||||
ABITESTS += abitest-tcc$(EXESUF)
|
|
||||||
endif
|
|
||||||
|
|
||||||
abitest: $(ABITESTS)
|
|
||||||
@echo ------------ $@ ------------
|
@echo ------------ $@ ------------
|
||||||
./abitest-cc$(EXESUF) $(TCCFLAGS)
|
./$< $(TCCFLAGS)
|
||||||
ifneq ($(CONFIG_arm_eabi),yes) # not ARM soft-float
|
|
||||||
./abitest-tcc$(EXESUF) $(TCCFLAGS)
|
abitest: abitest-cc
|
||||||
|
ifneq (-$(CONFIG_arm_eabi)-$(CONFIG_arm_vfp)-,-yes--)
|
||||||
|
abitest: abitest-tcc
|
||||||
endif
|
endif
|
||||||
|
|
||||||
vla_test$(EXESUF): vla_test.c
|
vla_test$(EXESUF): vla_test.c
|
||||||
@ -231,6 +273,8 @@ vla_test-run: vla_test$(EXESUF)
|
|||||||
@echo ------------ $@ ------------
|
@echo ------------ $@ ------------
|
||||||
./vla_test$(EXESUF)
|
./vla_test$(EXESUF)
|
||||||
|
|
||||||
|
.PHONY: abitest vla_test tccb
|
||||||
|
|
||||||
asm-c-connect$(EXESUF): asm-c-connect-1.c asm-c-connect-2.c
|
asm-c-connect$(EXESUF): asm-c-connect-1.c asm-c-connect-2.c
|
||||||
$(TCC) -o $@ $^
|
$(TCC) -o $@ $^
|
||||||
|
|
||||||
@ -244,21 +288,42 @@ asm-c-connect-test: asm-c-connect$(EXESUF) asm-c-connect-sep$(EXESUF)
|
|||||||
@echo ------------ $@ ------------
|
@echo ------------ $@ ------------
|
||||||
./asm-c-connect$(EXESUF) > asm-c-connect.out1 && cat asm-c-connect.out1
|
./asm-c-connect$(EXESUF) > asm-c-connect.out1 && cat asm-c-connect.out1
|
||||||
./asm-c-connect-sep$(EXESUF) > asm-c-connect.out2 && cat asm-c-connect.out2
|
./asm-c-connect-sep$(EXESUF) > asm-c-connect.out2 && cat asm-c-connect.out2
|
||||||
@diff -u asm-c-connect.out1 asm-c-connect.out2 && echo "ok"
|
@diff -u asm-c-connect.out1 asm-c-connect.out2 || (echo "error"; exit 1)
|
||||||
|
|
||||||
cross-test :
|
# quick sanity check for cross-compilers
|
||||||
|
cross-test : tcctest.c examples/ex3.c
|
||||||
@echo ------------ $@ ------------
|
@echo ------------ $@ ------------
|
||||||
$(TOP)/i386-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok"
|
$(foreach T,$(CROSS-TGTS),$(call CROSS-COMPILE,$T))
|
||||||
$(TOP)/i386-win32-tcc$(EXESUF) $(TCCFLAGS-win) $(TOPSRC)/examples/ex3.c && echo "ok"
|
|
||||||
$(TOP)/x86_64-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok"
|
CROSS-TGTS = \
|
||||||
$(TOP)/x86_64-win32-tcc$(EXESUF) $(TCCFLAGS-win) $(TOPSRC)/examples/ex3.c && echo "ok"
|
i386 \
|
||||||
$(TOP)/arm-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok"
|
i386-win32 \
|
||||||
$(TOP)/arm-wince-tcc$(EXESUF) $(TCCFLAGS-win) -c $(TOPSRC)/examples/ex3.c && echo "ok"
|
i386-OpenBSD \
|
||||||
$(TOP)/arm64-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok"
|
x86_64 \
|
||||||
$(TOP)/c67-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok"
|
x86_64-win32 \
|
||||||
$(TOP)/i386-win32-tcc$(EXESUF) $(TCCFLAGS-win) $(TOPSRC)/win32/examples/hello_win.c && echo "ok"
|
x86_64-osx \
|
||||||
$(TOP)/x86_64-win32-tcc$(EXESUF) $(TCCFLAGS-win) $(TOPSRC)/win32/examples/hello_win.c && echo "ok"
|
x86_64-FreeBSD \
|
||||||
$(TOP)/arm-wince-tcc$(EXESUF) $(TCCFLAGS-win) -c $(TOPSRC)/win32/examples/hello_win.c && echo "ok"
|
x86_64-NetBSD \
|
||||||
|
x86_64-OpenBSD \
|
||||||
|
arm-fpa \
|
||||||
|
arm-eabihf \
|
||||||
|
arm-NetBSD \
|
||||||
|
arm-wince \
|
||||||
|
arm64 \
|
||||||
|
arm64-win32 \
|
||||||
|
arm64-osx \
|
||||||
|
arm64-FreeBSD \
|
||||||
|
arm64-NetBSD \
|
||||||
|
arm64-OpenBSD \
|
||||||
|
riscv64 \
|
||||||
|
c67
|
||||||
|
|
||||||
|
define CROSS-COMPILE
|
||||||
|
@echo " . $(1)"
|
||||||
|
$(TCC) $(DEF-$1) -DTCC_CROSS_TEST -run $(TOPSRC)/tcc.c \
|
||||||
|
-c $(if $(findstring c67,$1),$(filter %/ex3.c,$^),$<) -w $(TCCFLAGS)
|
||||||
|
|
||||||
|
endef
|
||||||
|
|
||||||
# targets for development
|
# targets for development
|
||||||
%.bin: %.c tcc
|
%.bin: %.c tcc
|
||||||
@ -279,11 +344,8 @@ cache: tcc_g
|
|||||||
clean:
|
clean:
|
||||||
rm -f *~ *.o *.a *.bin *.i *.ref *.out *.out? *.out?b *.cc *.gcc
|
rm -f *~ *.o *.a *.bin *.i *.ref *.out *.out? *.out?b *.cc *.gcc
|
||||||
rm -f *-cc *-gcc *-tcc *.exe hello libtcc_test vla_test tcctest[1234]
|
rm -f *-cc *-gcc *-tcc *.exe hello libtcc_test vla_test tcctest[1234]
|
||||||
rm -f asm-c-connect$(EXESUF)
|
rm -f asm-c-connect asm-c-connect-sep
|
||||||
rm -f ex? tcc_g weaktest.*.txt *.def
|
rm -f ex? tcc_g weaktest.*.txt *.def *.pdb *.obj libtcc_test_mt
|
||||||
@$(MAKE) -C tests2 $@
|
@$(MAKE) -C tests2 $@
|
||||||
@$(MAKE) -C pp $@
|
@$(MAKE) -C pp $@
|
||||||
|
|
||||||
# silent clean, used before running tests
|
|
||||||
clean-s:
|
|
||||||
@$(MAKE) -s --no-print-directory clean
|
|
||||||
|
|||||||
@ -52,7 +52,7 @@ static int run_callback(const char *src, callback_type callback) {
|
|||||||
return -1;
|
return -1;
|
||||||
if (tcc_compile_string(s, src) == -1)
|
if (tcc_compile_string(s, src) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
if (tcc_relocate(s, TCC_RELOCATE_AUTO) == -1)
|
if (tcc_relocate(s) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
ptr = tcc_get_symbol(s, "f");
|
ptr = tcc_get_symbol(s, "f");
|
||||||
|
|||||||
243
tests/arm-asm-testsuite.sh
Executable file
243
tests/arm-asm-testsuite.sh
Executable file
@ -0,0 +1,243 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Note: "{r3}" is definitely different--but would complicate the assembler.
|
||||||
|
|
||||||
|
state="`mktemp -d`"
|
||||||
|
cat ../arm-tok.h | \
|
||||||
|
grep DEF_ASM | \
|
||||||
|
grep -v 'not useful' | \
|
||||||
|
grep -v '#define' | \
|
||||||
|
grep -v '/[*]' | \
|
||||||
|
grep -v 'DEF_ASM_CONDED_WITH_SUFFIX(x' | \
|
||||||
|
sed -e 's;^[ ]*DEF_ASM_CONDED_VFP_F32_F64[^(]*(\(.*\)).*$; DEF_ASM_CONDED(\1.f32)\
|
||||||
|
DEF_ASM_CONDED(\1.f64);g' | \
|
||||||
|
sed -e 's;^[ ]*DEF_ASM[^(]*(\(.*\)).*$;\1;g' -e 's;, ;.;g' | \
|
||||||
|
egrep -v '^((r|c|p|s|d)[0-9]+|fp|ip|sp|lr|pc|asl|apsr_nzcv|fpsid|fpscr|fpexc)$' | while read s
|
||||||
|
do
|
||||||
|
as_opts=""
|
||||||
|
if [ "${s#v}" != "${s}" ]
|
||||||
|
then
|
||||||
|
if grep -q "CONFIG_arm_vfp=yes" ../config.mak
|
||||||
|
then
|
||||||
|
as_opts="${as_opts} -mfpu=vfp"
|
||||||
|
else
|
||||||
|
echo "note: skipping VFP instruction: $s (because VFP is disabled)">&2
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
ok=0
|
||||||
|
for args in "r3, r4, r5, r6" \
|
||||||
|
"r3, r4, r5" \
|
||||||
|
"r3, r4, r5, asl #7" \
|
||||||
|
"r3, r4, r5, lsl #7" \
|
||||||
|
"r3, r4, r5, asr #7" \
|
||||||
|
"r3, r4, r5, lsr #7" \
|
||||||
|
"r3, r4, r5, ror #7" \
|
||||||
|
"r3, r4, r5, rrx" \
|
||||||
|
"r3, r4, r5, asl r6" \
|
||||||
|
"r3, r4, r5, lsl r6" \
|
||||||
|
"r3, r4, r5, asr r6" \
|
||||||
|
"r3, r4, r5, lsr r6" \
|
||||||
|
"r3, r4, r5, ror r6" \
|
||||||
|
"r3, r4, #5, asl #7" \
|
||||||
|
"r3, r4, #5, lsl #7" \
|
||||||
|
"r3, r4, #5, asr #7" \
|
||||||
|
"r3, r4, #5, lsr #7" \
|
||||||
|
"r3, r4, #5, ror #7" \
|
||||||
|
"r3, r4, #5, rrx" \
|
||||||
|
"r3, #5, r4" \
|
||||||
|
"r3, #4, #8" \
|
||||||
|
"r3, r4, asl #5" \
|
||||||
|
"r3, r4, lsl #5" \
|
||||||
|
"r3, r4, asr #5" \
|
||||||
|
"r3, r4, lsr #5" \
|
||||||
|
"r3, r4, ror #5" \
|
||||||
|
"r3, r4, ror #8" \
|
||||||
|
"r3, r4, asl r5" \
|
||||||
|
"r3, r4, lsl r5" \
|
||||||
|
"r3, r4, asr r5" \
|
||||||
|
"r3, r4, lsr r5" \
|
||||||
|
"r3, r4, ror r5" \
|
||||||
|
"r3, r4, ror #8" \
|
||||||
|
"r3, r4, ror #16" \
|
||||||
|
"r3, r4, ror #24" \
|
||||||
|
"r3, r4, rrx" \
|
||||||
|
"r3, #4, asl #5" \
|
||||||
|
"r3, #4, lsl #5" \
|
||||||
|
"r3, #4, asr #5" \
|
||||||
|
"r3, #4, lsr #5" \
|
||||||
|
"r3, #4, ror #5" \
|
||||||
|
"r3, r4, rrx" \
|
||||||
|
"r3, r4" \
|
||||||
|
"r3" \
|
||||||
|
"{r3,r4,r5}" \
|
||||||
|
"{r3,r5,r4}" \
|
||||||
|
"r2!, {r3,r4,r5}" \
|
||||||
|
"r2!, {r3,r5,r4}" \
|
||||||
|
"r2, {r3,r4,r5}" \
|
||||||
|
"r2, {r3,r5,r4}" \
|
||||||
|
"r2, [r3, r4]" \
|
||||||
|
"r2, [r3, r4]!" \
|
||||||
|
"r2, [r3, -r4]" \
|
||||||
|
"r2, [r3, -r4]!" \
|
||||||
|
"r2, [r3], r4" \
|
||||||
|
"r2, [r3], -r4" \
|
||||||
|
"r2, [r3]" \
|
||||||
|
"r2, r3, [r4, lsl# 2]" \
|
||||||
|
"r2, [r3, r4, lsr# 1]" \
|
||||||
|
"r2, [r3, r4, lsr# 2]!" \
|
||||||
|
"r2, [r3, -r4, ror# 3]" \
|
||||||
|
"r2, [r3, -r4, lsl# 1]!" \
|
||||||
|
"r2, [r3], r4, lsl# 3" \
|
||||||
|
"r2, [r3], -r4, asr# 31" \
|
||||||
|
"r2, [r3], -r4, asl# 1" \
|
||||||
|
"r2, [r3], -r4, rrx" \
|
||||||
|
"r2, [r3]" \
|
||||||
|
"r2, r3, [r4]" \
|
||||||
|
"r2, [r3, #4]" \
|
||||||
|
"r2, [r3, #-4]" \
|
||||||
|
"r2, [r3, #0x45]" \
|
||||||
|
"r2, [r3, #-0x45]" \
|
||||||
|
"r2, r3, #4" \
|
||||||
|
"r2, r3, #-4" \
|
||||||
|
"p10, #7, c2, c0, c1, #4" \
|
||||||
|
"p10, #7, r2, c0, c1, #4" \
|
||||||
|
"p10, #0, c2, c0, c1, #4" \
|
||||||
|
"p10, #0, r2, c0, c1, #4" \
|
||||||
|
"r2, #4" \
|
||||||
|
"r2, #-4" \
|
||||||
|
"r2, #0xEFFF" \
|
||||||
|
"r3, #0x0000" \
|
||||||
|
"r4, #0x0201" \
|
||||||
|
"r4, #0xFFFFFF00" \
|
||||||
|
"r2, #-4" \
|
||||||
|
"p10, #7, c2, c0, c1, #4" \
|
||||||
|
"p10, #7, r2, c0, c1, #4" \
|
||||||
|
"#4" \
|
||||||
|
"#-4" \
|
||||||
|
"p5, c2, [r3]" \
|
||||||
|
"p5, c3, [r4]" \
|
||||||
|
"p5, c2, [r3, #4]" \
|
||||||
|
"p5, c2, [r3, #-4]" \
|
||||||
|
"p5, c2, [r3, #0x45]" \
|
||||||
|
"p5, c2, [r3, #-0x45]" \
|
||||||
|
"s2, [r3]" \
|
||||||
|
"s3, [r4]" \
|
||||||
|
"s2, [r3, #4]" \
|
||||||
|
"s2, [r3, #-4]" \
|
||||||
|
"s2, [r3, #0x45]" \
|
||||||
|
"s2, [r3, #-0x45]" \
|
||||||
|
"r1, {d3-d4}" \
|
||||||
|
"r1!, {d3-d4}" \
|
||||||
|
"r2, {d4-d15}" \
|
||||||
|
"r3!, {d4-d15}" \
|
||||||
|
"r3!, {d4}" \
|
||||||
|
"r2, {s4-s31}" \
|
||||||
|
"r3!, {s4}" \
|
||||||
|
"{d3-d4}" \
|
||||||
|
"{d4-d15}" \
|
||||||
|
"{d4}" \
|
||||||
|
"{s4-s31}" \
|
||||||
|
"{s4}" \
|
||||||
|
"s2, s3, s4" \
|
||||||
|
"s2, s3" \
|
||||||
|
"d2, d3, d4" \
|
||||||
|
"d2, d3" \
|
||||||
|
"s2, #0" \
|
||||||
|
"d2, #0" \
|
||||||
|
"s3, #0.0" \
|
||||||
|
"d3, #0.0" \
|
||||||
|
"s4, #-0.1796875" \
|
||||||
|
"d4, #0.1796875" \
|
||||||
|
"r2, r3, d1" \
|
||||||
|
"d1, r2, r3" \
|
||||||
|
"s1, r2" \
|
||||||
|
"r2, s1" \
|
||||||
|
"r2, fpexc" \
|
||||||
|
"r2, fpscr" \
|
||||||
|
"r2, fpsid" \
|
||||||
|
"apsr_nzcv, fpscr" \
|
||||||
|
"fpexc, r2" \
|
||||||
|
"fpscr, r2" \
|
||||||
|
"fpsid, r2" \
|
||||||
|
"s3, d4" \
|
||||||
|
"d4, s3" \
|
||||||
|
""
|
||||||
|
do
|
||||||
|
#echo ".syntax unified" > a.s
|
||||||
|
err="`mktemp --suffix=-stderr.log`"
|
||||||
|
as_object="${state}/as-$s $args.o"
|
||||||
|
tcc_object="${state}/tcc-$s $args.o"
|
||||||
|
expected="${state}/expected-$s $args"
|
||||||
|
got="${state}/got-$s $args"
|
||||||
|
if echo "$s $args" | "${CROSS_COMPILE}as" -mlittle-endian ${as_opts} -o "${as_object}" - 2>"${err}"
|
||||||
|
then
|
||||||
|
cat "${err}"
|
||||||
|
rm -f "${err}"
|
||||||
|
total_count=`expr $total_count + 1`
|
||||||
|
"${CROSS_COMPILE}objdump" -S "${as_object}" |grep "^[ ]*0:" >"${expected}"
|
||||||
|
|
||||||
|
#echo '__asm__("'"$s ${args}"'");' > "${csource}"
|
||||||
|
if echo '__asm__("'"$s ${args}"'");'| ${TCC} -o "${tcc_object}" -c -
|
||||||
|
then
|
||||||
|
"${CROSS_COMPILE}objdump" -S "${tcc_object}" |grep "^[ ]*0:" >"${got}"
|
||||||
|
if diff -u "${got}" "${expected}"
|
||||||
|
then
|
||||||
|
touch "${state}/ok-$s $args"
|
||||||
|
else
|
||||||
|
echo "warning: '$s $args' did not work in tcc (see above)">&2
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
rm -f "${tcc_object}"
|
||||||
|
echo "warning: '$s $args' did not work in tcc">&2
|
||||||
|
fi
|
||||||
|
ok=1
|
||||||
|
else # GNU as can't do it either--so we don't care
|
||||||
|
rm -f "${as_object}"
|
||||||
|
fi
|
||||||
|
rm -f "${err}"
|
||||||
|
done
|
||||||
|
if [ "${ok}" -eq "0" ]
|
||||||
|
then
|
||||||
|
echo "warning: $s could not be used.">&2
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
successful_count="$(ls -1 "${state}/ok-"* |wc -l)"
|
||||||
|
total_count="$(ls -1 "${state}/as-"*.o |wc -l)"
|
||||||
|
echo "${successful_count} of ${total_count} tests succeeded.">&2
|
||||||
|
if [ "${successful_count}" -eq "${total_count}" ]
|
||||||
|
then
|
||||||
|
rm -rf "${state}"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
status=0
|
||||||
|
for s in "${state}/as-"*.o
|
||||||
|
do
|
||||||
|
test="$(basename "$s")"
|
||||||
|
test="${test%.o}"
|
||||||
|
test="${test#as-}"
|
||||||
|
t="${state}/ok-${test}"
|
||||||
|
if [ ! -f "$t" ]
|
||||||
|
then
|
||||||
|
case "${test}" in
|
||||||
|
"bl r3"|"b r3"|"mov r2, #0xEFFF"|"mov r4, #0x0201")
|
||||||
|
known_failure=" (known failure)"
|
||||||
|
;;
|
||||||
|
"vmov.f32 r2, r3, d1"|"vmov.f32 d1, r2, r3") # GNU as bug
|
||||||
|
known_failure=" (known failure)"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
known_failure=""
|
||||||
|
status=1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
echo "Failed test: ${test}${known_failure}">&2
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
rm -rf "${state}"
|
||||||
|
exit "${status}"
|
||||||
|
fi
|
||||||
@ -1,18 +1,30 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#if defined _WIN32 && !defined __TINYC__
|
#if (defined _WIN32 || defined __APPLE__) && (!defined __TINYC__ || defined __leading_underscore)
|
||||||
# define _ "_"
|
# define _ "_"
|
||||||
#else
|
#else
|
||||||
# define _
|
# define _
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int x1_c(void)
|
#ifdef __clang__
|
||||||
|
/* clang needs some help tp not throw functions away even at -O0 */
|
||||||
|
#define __USED __attribute__((__used__))
|
||||||
|
#else
|
||||||
|
#define __USED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int __USED x1_c (void)
|
||||||
{
|
{
|
||||||
printf(" x1");
|
printf(" x1");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if __i386__
|
||||||
asm(".text;"_"x1: call "_"x1_c; ret");
|
asm(".text;"_"x1: call "_"x1_c; ret");
|
||||||
|
#else
|
||||||
|
/* Keep stack aligned */
|
||||||
|
asm(".text;"_"x1: sub $8,%rsp; call "_"x1_c; add $8,%rsp; ret");
|
||||||
|
#endif
|
||||||
|
|
||||||
void callx4(void);
|
void callx4(void);
|
||||||
void callx5_again(void);
|
void callx5_again(void);
|
||||||
@ -37,7 +49,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
int x2(void)
|
int __USED x2(void)
|
||||||
{
|
{
|
||||||
printf(" x2");
|
printf(" x2");
|
||||||
return 2;
|
return 2;
|
||||||
|
|||||||
@ -1,11 +1,18 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#if defined _WIN32 && !defined __TINYC__
|
#if (defined _WIN32 || defined __APPLE__) && (!defined __TINYC__ || defined __leading_underscore)
|
||||||
# define _ "_"
|
# define _ "_"
|
||||||
#else
|
#else
|
||||||
# define _
|
# define _
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
/* clang needs some help tp not throw functions away even at -O0 */
|
||||||
|
#define __USED __attribute__((__used__))
|
||||||
|
#else
|
||||||
|
#define __USED
|
||||||
|
#endif
|
||||||
|
|
||||||
int x3(void)
|
int x3(void)
|
||||||
{
|
{
|
||||||
printf(" x3");
|
printf(" x3");
|
||||||
@ -15,7 +22,12 @@ int x3(void)
|
|||||||
/* That callx4 is defined globally (as if ".globl callx4")
|
/* That callx4 is defined globally (as if ".globl callx4")
|
||||||
is a TCC extension. GCC doesn't behave like this. */
|
is a TCC extension. GCC doesn't behave like this. */
|
||||||
void callx4(void);
|
void callx4(void);
|
||||||
|
#if __i386__
|
||||||
__asm__(_"callx4: call "_"x4; ret;"
|
__asm__(_"callx4: call "_"x4; ret;"
|
||||||
|
#else
|
||||||
|
/* Keep stack aligned */
|
||||||
|
__asm__(_"callx4: sub $8,%rsp; call "_"x4; add $8,%rsp; ret;"
|
||||||
|
#endif
|
||||||
#ifndef __TINYC__
|
#ifndef __TINYC__
|
||||||
" .global "_"callx4"
|
" .global "_"callx4"
|
||||||
#endif
|
#endif
|
||||||
@ -30,7 +42,7 @@ void callx5_again(void)
|
|||||||
asm("call "_"x6");
|
asm("call "_"x6");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void x6()
|
static void __USED x6()
|
||||||
{
|
{
|
||||||
printf(" x6-2");
|
printf(" x6-2");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -425,7 +425,7 @@ L3:
|
|||||||
|
|
||||||
fsubp %st(5)
|
fsubp %st(5)
|
||||||
fsubp
|
fsubp
|
||||||
fsubp %st(1), %st
|
//fsubp %st(1), %st # not accepted by new GAS anymore
|
||||||
|
|
||||||
fsubs 0x1000
|
fsubs 0x1000
|
||||||
fisubs 0x1002
|
fisubs 0x1002
|
||||||
@ -438,7 +438,7 @@ L3:
|
|||||||
|
|
||||||
fsubrp %st(5)
|
fsubrp %st(5)
|
||||||
fsubrp
|
fsubrp
|
||||||
fsubrp %st(1), %st
|
//fsubrp %st(1), %st # not accepted by new GAS anymore
|
||||||
|
|
||||||
fsubrs 0x1000
|
fsubrs 0x1000
|
||||||
fisubrs 0x1002
|
fisubrs 0x1002
|
||||||
@ -451,7 +451,7 @@ L3:
|
|||||||
|
|
||||||
fdivp %st(5)
|
fdivp %st(5)
|
||||||
fdivp
|
fdivp
|
||||||
fdivp %st(1), %st
|
//fdivp %st(1), %st # not accepted by new GAS anymore
|
||||||
|
|
||||||
fdivs 0x1000
|
fdivs 0x1000
|
||||||
fidivs 0x1002
|
fidivs 0x1002
|
||||||
@ -632,10 +632,19 @@ int $0x10
|
|||||||
leave
|
leave
|
||||||
int3
|
int3
|
||||||
iret
|
iret
|
||||||
|
iretw
|
||||||
|
iretl
|
||||||
|
#ifdef __x86_64__
|
||||||
|
iretq
|
||||||
|
#endif
|
||||||
rsm
|
rsm
|
||||||
hlt
|
hlt
|
||||||
wait
|
wait
|
||||||
nop
|
nop
|
||||||
|
vmcall
|
||||||
|
vmlaunch
|
||||||
|
vmresume
|
||||||
|
vmxoff
|
||||||
|
|
||||||
/* XXX: handle prefixes */
|
/* XXX: handle prefixes */
|
||||||
#if 0
|
#if 0
|
||||||
@ -692,6 +701,10 @@ int $0x10
|
|||||||
fxsaveq (%r11)
|
fxsaveq (%r11)
|
||||||
fxrstorq (%rcx)
|
fxrstorq (%rcx)
|
||||||
fxrstorq (%r10)
|
fxrstorq (%r10)
|
||||||
|
movnti %ebx, (%rdi)
|
||||||
|
movntil %ecx, (%rdi)
|
||||||
|
movnti %rax, (%rdi)
|
||||||
|
movntiq %r8, (%rdi)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -745,8 +758,37 @@ int $0x10
|
|||||||
bts %edx, 0x1000
|
bts %edx, 0x1000
|
||||||
btsl $2, 0x1000
|
btsl $2, 0x1000
|
||||||
|
|
||||||
|
popcnt %ax, %si
|
||||||
|
popcntw %ax, %si
|
||||||
|
popcnt 0x1000, %edx
|
||||||
|
popcntl 0x1000, %edx
|
||||||
|
#ifdef __x86_64__
|
||||||
|
popcnt %rbx, %rdi
|
||||||
|
popcntq %rcx, %r8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
lzcnt %cx, %ax
|
||||||
|
lzcntw %cx, %ax
|
||||||
|
lzcnt %edx, %ebx
|
||||||
|
lzcntl 8(%edi), %ecx
|
||||||
|
#ifdef __x86_64__
|
||||||
|
lzcnt %rdi, %rdx
|
||||||
|
lzcntq %r12, %r15
|
||||||
|
lzcnt 0x40(%rcx), %r11
|
||||||
|
lzcntq (%r8), %rsi
|
||||||
|
#endif
|
||||||
|
|
||||||
|
tzcnt %cx, %ax
|
||||||
|
tzcntw %cx, %ax
|
||||||
|
tzcnt %edx, %ebx
|
||||||
|
tzcntl -24(%edi), %ecx
|
||||||
|
#ifdef __x86_64__
|
||||||
|
tzcnt %rbp, %rdx
|
||||||
|
tzcntq %rax, %r15
|
||||||
|
tzcnt -8(%rbp), %rcx
|
||||||
|
tzcntq (%r8), %r12
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __i386__
|
#ifdef __i386__
|
||||||
boundl %edx, 0x10000
|
boundl %edx, 0x10000
|
||||||
boundw %bx, 0x1000
|
boundw %bx, 0x1000
|
||||||
@ -768,8 +810,13 @@ int $0x10
|
|||||||
|
|
||||||
swapgs
|
swapgs
|
||||||
|
|
||||||
str %rdx
|
/* Newer gas assemble 'str %rdx' as 'str %edx', based on the observation
|
||||||
str %r9
|
that the 16bit value of the task register is zero-extended into the
|
||||||
|
destination anyway, and hence storing into %edx is the same as storing
|
||||||
|
into %rdx. TCC doesn't do that micro-optimization, hence just store
|
||||||
|
into the 32bit reg as well. */
|
||||||
|
str %edx
|
||||||
|
str %r9d
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
lmsw 0x1000
|
lmsw 0x1000
|
||||||
|
|||||||
@ -50,15 +50,12 @@ int test4(void)
|
|||||||
int i, sum = 0;
|
int i, sum = 0;
|
||||||
int *tab4;
|
int *tab4;
|
||||||
|
|
||||||
fprintf(stderr, "%s start\n", __FUNCTION__);
|
|
||||||
|
|
||||||
tab4 = malloc(20 * sizeof(int));
|
tab4 = malloc(20 * sizeof(int));
|
||||||
for(i=0;i<20;i++) {
|
for(i=0;i<20;i++) {
|
||||||
sum += tab4[i];
|
sum += tab4[i];
|
||||||
}
|
}
|
||||||
free(tab4);
|
free(tab4);
|
||||||
|
|
||||||
fprintf(stderr, "%s end\n", __FUNCTION__);
|
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,20 +65,16 @@ int test5(void)
|
|||||||
int i, sum = 0;
|
int i, sum = 0;
|
||||||
int *tab4;
|
int *tab4;
|
||||||
|
|
||||||
fprintf(stderr, "%s start\n", __FUNCTION__);
|
|
||||||
|
|
||||||
tab4 = malloc(20 * sizeof(int));
|
tab4 = malloc(20 * sizeof(int));
|
||||||
for(i=0;i<21;i++) {
|
for(i=0;i<21;i++) {
|
||||||
sum += tab4[i];
|
sum += tab4[i];
|
||||||
}
|
}
|
||||||
free(tab4);
|
free(tab4);
|
||||||
|
|
||||||
fprintf(stderr, "%s end\n", __FUNCTION__);
|
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* error */
|
/* error */
|
||||||
/* XXX: currently: bug */
|
|
||||||
int test6(void)
|
int test6(void)
|
||||||
{
|
{
|
||||||
int i, sum = 0;
|
int i, sum = 0;
|
||||||
@ -179,54 +172,62 @@ int test13(void)
|
|||||||
int test14(void)
|
int test14(void)
|
||||||
{
|
{
|
||||||
char *p = alloca(TAB_SIZE);
|
char *p = alloca(TAB_SIZE);
|
||||||
|
size_t ret;
|
||||||
memset(p, 'a', TAB_SIZE);
|
memset(p, 'a', TAB_SIZE);
|
||||||
p[TAB_SIZE-1] = 0;
|
p[TAB_SIZE-1] = 0;
|
||||||
return strlen(p);
|
ret = strlen(p);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* error */
|
/* error */
|
||||||
int test15(void)
|
int test15(void)
|
||||||
{
|
{
|
||||||
char *p = alloca(TAB_SIZE-1);
|
char *p = alloca(TAB_SIZE-1);
|
||||||
|
size_t ret;
|
||||||
memset(p, 'a', TAB_SIZE);
|
memset(p, 'a', TAB_SIZE);
|
||||||
p[TAB_SIZE-1] = 0;
|
p[TAB_SIZE-1] = 0;
|
||||||
return strlen(p);
|
ret = strlen(p);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ok */
|
/* ok */
|
||||||
int test16()
|
int test16()
|
||||||
{
|
{
|
||||||
char *demo = "This is only a test.";
|
char *demo = "This is only a test.";
|
||||||
char *p;
|
char *p, *q;
|
||||||
|
|
||||||
fprintf(stderr, "%s start\n", __FUNCTION__);
|
|
||||||
|
|
||||||
p = alloca(16);
|
p = alloca(16);
|
||||||
strcpy(p,"12345678901234");
|
strcpy(p,"12345678901234");
|
||||||
printf("alloca: p is %s\n", p);
|
|
||||||
|
|
||||||
/* Test alloca embedded in a larger expression */
|
/* Test alloca embedded in a larger expression */
|
||||||
printf("alloca: %s\n", strcpy(alloca(strlen(demo)+1),demo) );
|
printf("alloca : %s : %s\n", p, strcpy(q=alloca(strlen(demo)+1),demo) );
|
||||||
|
|
||||||
fprintf(stderr, "%s end\n", __FUNCTION__);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* error */
|
/* error */
|
||||||
int test17()
|
int test17()
|
||||||
{
|
{
|
||||||
char *demo = "This is only a test.";
|
char *demo = "This is only a test.";
|
||||||
char *p;
|
char *p, *q;
|
||||||
|
|
||||||
fprintf(stderr, "%s start\n", __FUNCTION__);
|
|
||||||
|
|
||||||
p = alloca(16);
|
p = alloca(16);
|
||||||
strcpy(p,"12345678901234");
|
strcpy(p,"12345678901234");
|
||||||
printf("alloca: p is %s\n", p);
|
|
||||||
|
|
||||||
/* Test alloca embedded in a larger expression */
|
/* Test alloca embedded in a larger expression */
|
||||||
printf("alloca: %s\n", strcpy(alloca(strlen(demo)),demo) );
|
printf("alloca : %s : %s\n", p, strcpy(q=alloca(strlen(demo)),demo) );
|
||||||
|
|
||||||
fprintf(stderr, "%s end\n", __FUNCTION__);
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test18(void)
|
||||||
|
{
|
||||||
|
int i, sum = 0, n = TAB_SIZE;
|
||||||
|
int tab[n];
|
||||||
|
for(i=0;i<TAB_SIZE+1;i++) {
|
||||||
|
sum += tab[i];
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
int (*table_test[])(void) = {
|
int (*table_test[])(void) = {
|
||||||
@ -247,14 +248,25 @@ int (*table_test[])(void) = {
|
|||||||
test15,
|
test15,
|
||||||
test16,
|
test16,
|
||||||
test17,
|
test17,
|
||||||
|
test18
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
char *cp;
|
||||||
int index;
|
int index;
|
||||||
int (*ftest)(void);
|
int (*ftest)(void);
|
||||||
int index_max = sizeof(table_test)/sizeof(table_test[0]);
|
int index_max = sizeof(table_test)/sizeof(table_test[0]);
|
||||||
|
|
||||||
|
/* check bounds checking main arg */
|
||||||
|
for (i = 0; i < argc; i++) {
|
||||||
|
cp = argv[i];
|
||||||
|
while (*cp) {
|
||||||
|
cp++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
printf(
|
printf(
|
||||||
"test TCC bound checking system\n"
|
"test TCC bound checking system\n"
|
||||||
|
|||||||
35
tests/bug.c
Normal file
35
tests/bug.c
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
int compile_errors(void)
|
||||||
|
{
|
||||||
|
#if TEST == 1
|
||||||
|
{
|
||||||
|
/* Not constant */
|
||||||
|
static int i = (&"Foobar"[1] - &"Foobar"[0]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if TEST == 2
|
||||||
|
{
|
||||||
|
/* Not constant */
|
||||||
|
struct{int c;}v;
|
||||||
|
static long i=((char*)&(v.c)-(char*)&v);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if TEST == 3
|
||||||
|
{
|
||||||
|
/* Not constant */
|
||||||
|
static const short ar[] = { &&l1 - &&l1, &&l2 - &&l1 };
|
||||||
|
void *p = &&l1 + ar[0];
|
||||||
|
goto *p;
|
||||||
|
l1: return 1;
|
||||||
|
l2: return 2;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
163
tests/gcctestsuite.sh
Normal file → Executable file
163
tests/gcctestsuite.sh
Normal file → Executable file
@ -1,33 +1,164 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
TESTSUITE_PATH=$HOME/gcc/gcc-3.2/gcc/testsuite/gcc.c-torture
|
if [ -z "$TESTSUITE_PATH" ]
|
||||||
TCC="./tcc -B. -I. -DNO_TRAMPOLINES"
|
then
|
||||||
rm -f tcc.sum tcc.log
|
if [ -d "$HOME/gcc/gcc-3.2/gcc/testsuite/gcc.c-torture" ]
|
||||||
|
then
|
||||||
|
TESTSUITE_PATH="$HOME/gcc/gcc-3.2/gcc/testsuite/gcc.c-torture"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$TESTSUITE_PATH" ]
|
||||||
|
then
|
||||||
|
echo "gcc testsuite not found."
|
||||||
|
echo "define TESTSUITE_PATH to point to the gcc.c-torture directory"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$TCC_SOURCE_PATH" ]
|
||||||
|
then
|
||||||
|
if [ -f "include/tccdefs.h" ]
|
||||||
|
then
|
||||||
|
TCC_SOURCE_PATH="."
|
||||||
|
elif [ -f "../include/tccdefs.h" ]
|
||||||
|
then
|
||||||
|
TCC_SOURCE_PATH=".."
|
||||||
|
elif [ -f "../tinycc/include/tccdefs.h" ]
|
||||||
|
then
|
||||||
|
TCC_SOURCE_PATH="../tinycc"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$RUNTIME_DIR" ]
|
||||||
|
then
|
||||||
|
RUNTIME_DIR=$XDG_RUNTIME_DIR
|
||||||
|
fi
|
||||||
|
if [ -z "$RUNTIME_DIR" ]
|
||||||
|
then
|
||||||
|
RUNTIME_DIR="/tmp"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$CC" ]
|
||||||
|
then
|
||||||
|
if [ -z "$TCC_SOURCE_PATH" ]
|
||||||
|
then
|
||||||
|
echo "tcc not found."
|
||||||
|
echo "define TCC_SOURCE_PATH to point to the tcc source path"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
TCC="./tcc -B. -I$TCC_SOURCE_PATH/ -I$TCC_SOURCE_PATH/include -DNO_TRAMPOLINES"
|
||||||
|
else
|
||||||
|
TCC="$CC -O1 -Wno-implicit-int $CFLAGS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f tcc.sum tcc.fail
|
||||||
|
nb_ok="0"
|
||||||
|
nb_skipped="0"
|
||||||
nb_failed="0"
|
nb_failed="0"
|
||||||
|
nb_exe_failed="0"
|
||||||
|
|
||||||
|
# skip some failed tests not implemented in tcc
|
||||||
|
# builtin: gcc "__builtins_*"
|
||||||
|
# ieee: gcc "__builtins_*" in the ieee directory
|
||||||
|
# complex: C99 "_Complex" and gcc "__complex__"
|
||||||
|
# misc: stdc features, other arch, gcc extensions (example: gnu_inline in c89)
|
||||||
|
#
|
||||||
|
|
||||||
|
old_pwd="`pwd`"
|
||||||
|
cd "$TESTSUITE_PATH"
|
||||||
|
|
||||||
|
skip_builtin="`grep '_builtin_' compile/*.c execute/*.c execute/ieee/*.c | cut -d ':' -f1 | cut -d '/' -f2 | sort -u `"
|
||||||
|
skip_ieee="`grep '_builtin_' execute/ieee/*.c | cut -d ':' -f1 | cut -d '/' -f3 | sort -u `"
|
||||||
|
skip_complex="`grep -i '_Complex' compile/*.c execute/*.c execute/ieee/*.c | cut -d ':' -f1 | cut -d '/' -f2 | sort -u `"
|
||||||
|
skip_int128="`grep -Eiw '__int128_t|__uint128_t' compile/*.c execute/*.c execute/ieee/*.c | cut -d ':' -f1 | cut -d '/' -f2 | sort -u `"
|
||||||
|
skip_vector="`grep -Eiw 'vector|vector_size|__vector_size__' compile/*.c execute/*.c execute/ieee/*.c | cut -d ':' -f1 | cut -d '/' -f2 | sort -u `"
|
||||||
|
skip_misc="20000120-2.c mipscop-1.c mipscop-2.c mipscop-3.c mipscop-4.c
|
||||||
|
fp-cmp-4f.c fp-cmp-4l.c fp-cmp-8f.c fp-cmp-8l.c pr38016.c "
|
||||||
|
|
||||||
|
cd "$old_pwd"
|
||||||
|
|
||||||
for src in $TESTSUITE_PATH/compile/*.c ; do
|
for src in $TESTSUITE_PATH/compile/*.c ; do
|
||||||
echo $TCC -o /tmp/test.o -c $src
|
echo $TCC -o $RUNTIME_DIR/tst.o -c $src
|
||||||
$TCC -o /tmp/test.o -c $src >> tcc.log 2>&1
|
if $TCC -o $RUNTIME_DIR/tst.o -c $src 2>&1 | grep 'cannot use local functions' >/dev/null 2>&1
|
||||||
if [ "$?" = "0" ] ; then
|
then
|
||||||
result="PASS"
|
result="SKIP"
|
||||||
|
nb_skipped=$(( $nb_skipped + 1 ))
|
||||||
else
|
else
|
||||||
result="FAIL"
|
$TCC -o $RUNTIME_DIR/tst.o -c $src >> tcc.fail 2>&1
|
||||||
nb_failed=$(( $nb_failed + 1 ))
|
if [ "$?" = "0" ] ; then
|
||||||
|
result="PASS"
|
||||||
|
nb_ok=$(( $nb_ok + 1 ))
|
||||||
|
else
|
||||||
|
base=`basename "$src"`
|
||||||
|
skip_me="`echo $skip_builtin $skip_ieee $skip_complex $skip_int128 $skip_misc $skip_vector | grep -w $base`"
|
||||||
|
|
||||||
|
if [ -n "$skip_me" ]
|
||||||
|
then
|
||||||
|
result="SKIP"
|
||||||
|
nb_skipped=$(( $nb_skipped + 1 ))
|
||||||
|
else
|
||||||
|
result="FAIL"
|
||||||
|
nb_failed=$(( $nb_failed + 1 ))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
echo "$result: $src" >> tcc.sum
|
echo "$result: $src" >> tcc.sum
|
||||||
done
|
done
|
||||||
|
|
||||||
for src in $TESTSUITE_PATH/execute/*.c ; do
|
if [ -f "$RUNTIME_DIR/tst.o" ]
|
||||||
echo $TCC $src
|
then
|
||||||
$TCC $src >> tcc.log 2>&1
|
rm -f "$RUNTIME_DIR/tst.o"
|
||||||
if [ "$?" = "0" ] ; then
|
fi
|
||||||
result="PASS"
|
|
||||||
|
for src in $TESTSUITE_PATH/execute/*.c $TESTSUITE_PATH/execute/ieee/*.c ; do
|
||||||
|
echo $TCC $src -o $RUNTIME_DIR/tst -lm
|
||||||
|
if $TCC $src -o $RUNTIME_DIR/tst -lm 2>&1 | grep 'cannot use local functions' >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
result="SKIP"
|
||||||
|
nb_skipped=$(( $nb_skipped + 1 ))
|
||||||
else
|
else
|
||||||
result="FAIL"
|
$TCC $src -o $RUNTIME_DIR/tst -lm >> tcc.fail 2>&1
|
||||||
nb_failed=$(( $nb_failed + 1 ))
|
if [ "$?" = "0" ] ; then
|
||||||
|
if $RUNTIME_DIR/tst >> tcc.fail 2>&1
|
||||||
|
then
|
||||||
|
result="PASS"
|
||||||
|
nb_ok=$(( $nb_ok + 1 ))
|
||||||
|
else
|
||||||
|
result="FAILEXE"
|
||||||
|
nb_exe_failed=$(( $nb_exe_failed + 1 ))
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
base=`basename "$src"`
|
||||||
|
skip_me="`echo $skip_builtin $skip_ieee $skip_complex $skip_int128 $skip_misc $skip_vector | grep -w $base`"
|
||||||
|
|
||||||
|
if [ -n "$skip_me" ]
|
||||||
|
then
|
||||||
|
result="SKIP"
|
||||||
|
nb_skipped=$(( $nb_skipped + 1 ))
|
||||||
|
else
|
||||||
|
result="FAIL"
|
||||||
|
nb_failed=$(( $nb_failed + 1 ))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
echo "$result: $src" >> tcc.sum
|
echo "$result: $src" >> tcc.sum
|
||||||
done
|
done
|
||||||
|
|
||||||
|
if [ -f "$RUNTIME_DIR/tst.o" ]
|
||||||
|
then
|
||||||
|
rm -f "$RUNTIME_DIR/tst.o"
|
||||||
|
fi
|
||||||
|
if [ -f "$RUNTIME_DIR/tst" ]
|
||||||
|
then
|
||||||
|
rm -f "$RUNTIME_DIR/tst"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$nb_ok test(s) ok." >> tcc.sum
|
||||||
|
echo "$nb_ok test(s) ok."
|
||||||
|
echo "$nb_skipped test(s) skipped." >> tcc.sum
|
||||||
|
echo "$nb_skipped test(s) skipped."
|
||||||
echo "$nb_failed test(s) failed." >> tcc.sum
|
echo "$nb_failed test(s) failed." >> tcc.sum
|
||||||
echo "$nb_failed test(s) failed."
|
echo "$nb_failed test(s) failed."
|
||||||
|
echo "$nb_exe_failed test(s) exe failed." >> tcc.sum
|
||||||
|
echo "$nb_exe_failed test(s) exe failed."
|
||||||
|
|||||||
@ -6,9 +6,13 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "libtcc.h"
|
#include "libtcc.h"
|
||||||
|
|
||||||
|
void handle_error(void *opaque, const char *msg)
|
||||||
|
{
|
||||||
|
fprintf(opaque, "%s\n", msg);
|
||||||
|
}
|
||||||
|
|
||||||
/* this function is called by the generated code */
|
/* this function is called by the generated code */
|
||||||
int add(int a, int b)
|
int add(int a, int b)
|
||||||
{
|
{
|
||||||
@ -53,6 +57,9 @@ int main(int argc, char **argv)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* set custom error/warning printer */
|
||||||
|
tcc_set_error_func(s, stderr, handle_error);
|
||||||
|
|
||||||
/* if tcclib.h and libtcc1.a are not installed, where can we find them */
|
/* if tcclib.h and libtcc1.a are not installed, where can we find them */
|
||||||
for (i = 1; i < argc; ++i) {
|
for (i = 1; i < argc; ++i) {
|
||||||
char *a = argv[i];
|
char *a = argv[i];
|
||||||
@ -78,7 +85,7 @@ int main(int argc, char **argv)
|
|||||||
tcc_add_symbol(s, "hello", hello);
|
tcc_add_symbol(s, "hello", hello);
|
||||||
|
|
||||||
/* relocate the code */
|
/* relocate the code */
|
||||||
if (tcc_relocate(s, TCC_RELOCATE_AUTO) < 0)
|
if (tcc_relocate(s) < 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* get entry symbol */
|
/* get entry symbol */
|
||||||
|
|||||||
363
tests/libtcc_test_mt.c
Normal file
363
tests/libtcc_test_mt.c
Normal file
@ -0,0 +1,363 @@
|
|||||||
|
/*
|
||||||
|
* Multi-thread Test for libtcc
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FIB
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <setjmp.h>
|
||||||
|
#include "libtcc.h"
|
||||||
|
|
||||||
|
#define M 20 /* number of states */
|
||||||
|
#define F(n) (n % 20 + 2) /* fib argument */
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#define TF_TYPE(func, param) DWORD WINAPI func(void *param)
|
||||||
|
typedef TF_TYPE(ThreadFunc, x);
|
||||||
|
HANDLE hh[M];
|
||||||
|
void create_thread(ThreadFunc f, int n)
|
||||||
|
{
|
||||||
|
DWORD tid;
|
||||||
|
hh[n] = CreateThread(NULL, 0, f, (void*)(size_t)n, 0, &tid);
|
||||||
|
}
|
||||||
|
void wait_threads(int n)
|
||||||
|
{
|
||||||
|
WaitForMultipleObjects(n, hh, TRUE, INFINITE);
|
||||||
|
while (n)
|
||||||
|
CloseHandle(hh[--n]);
|
||||||
|
}
|
||||||
|
void sleep_ms(unsigned n)
|
||||||
|
{
|
||||||
|
Sleep(n);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#define TF_TYPE(func, param) void* func(void *param)
|
||||||
|
typedef TF_TYPE(ThreadFunc, x);
|
||||||
|
pthread_t hh[M];
|
||||||
|
void create_thread(ThreadFunc f, int n)
|
||||||
|
{
|
||||||
|
pthread_create(&hh[n], NULL, f, (void*)(size_t)n);
|
||||||
|
}
|
||||||
|
void wait_threads(int n)
|
||||||
|
{
|
||||||
|
while (n)
|
||||||
|
pthread_join(hh[--n], NULL);
|
||||||
|
|
||||||
|
}
|
||||||
|
void sleep_ms(unsigned n)
|
||||||
|
{
|
||||||
|
usleep(n * 1000);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void handle_error(void *opaque, const char *msg)
|
||||||
|
{
|
||||||
|
fprintf(opaque, "%s\n", msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this function is called by the generated code */
|
||||||
|
int add(int a, int b)
|
||||||
|
{
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _str(s) #s
|
||||||
|
#define str(s) _str(s)
|
||||||
|
/* as a trick, prepend #line directive for better error/warning messages */
|
||||||
|
#define PROG(lbl) \
|
||||||
|
char lbl[] = "#line " str(__LINE__) " " str(__FILE__) "\n\n"
|
||||||
|
|
||||||
|
PROG(my_program)
|
||||||
|
"#include <tcclib.h>\n" /* include the "Simple libc header for TCC" */
|
||||||
|
"int add(int a, int b);\n"
|
||||||
|
"int fib(int n)\n"
|
||||||
|
"{\n"
|
||||||
|
" if (n <= 2)\n"
|
||||||
|
" return 1;\n"
|
||||||
|
" else\n"
|
||||||
|
" return add(fib(n-1),fib(n-2));\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"void bar(void) { *(void**)0 = 0; }\n"
|
||||||
|
"\n"
|
||||||
|
"int foo(int n)\n"
|
||||||
|
"{\n"
|
||||||
|
" printf(\" %d\", fib(n));\n"
|
||||||
|
" if (n >= N_CRASH && n < N_CRASH + 8)\n"
|
||||||
|
" bar();\n"
|
||||||
|
" return 0;\n"
|
||||||
|
"# warning is this the correct file:line...\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
int g_argc; char **g_argv;
|
||||||
|
|
||||||
|
void parse_args(TCCState *s)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
/* if tcclib.h and libtcc1.a are not installed, where can we find them */
|
||||||
|
for (i = 1; i < g_argc; ++i) {
|
||||||
|
char *a = g_argv[i];
|
||||||
|
if (a[0] == '-') {
|
||||||
|
if (a[1] == 'B')
|
||||||
|
tcc_set_lib_path(s, a+2);
|
||||||
|
else if (a[1] == 'I')
|
||||||
|
tcc_add_include_path(s, a+2);
|
||||||
|
else if (a[1] == 'L')
|
||||||
|
tcc_add_library_path(s, a+2);
|
||||||
|
else if (a[1] == 'D')
|
||||||
|
tcc_define_symbol(s, a+2, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int backtrace_func(
|
||||||
|
void *ud,
|
||||||
|
void *pc,
|
||||||
|
const char *file,
|
||||||
|
int line,
|
||||||
|
const char *func,
|
||||||
|
const char *msg)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
printf("\n *** %p %s %s:%d in '%s'",
|
||||||
|
pc,
|
||||||
|
msg ? "at" : "by",
|
||||||
|
file ? file : "?",
|
||||||
|
line,
|
||||||
|
func ? func : "?");
|
||||||
|
return 1; // want more backtrace levels
|
||||||
|
#else
|
||||||
|
//printf(" [%d]", *(int*)ud);
|
||||||
|
printf("!");
|
||||||
|
return 0; // cancel backtrace
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TCCState *new_state(int w)
|
||||||
|
{
|
||||||
|
TCCState *s = tcc_new();
|
||||||
|
if (!s) {
|
||||||
|
fprintf(stderr, __FILE__ ": could not create tcc state\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
tcc_set_error_func(s, stdout, handle_error);
|
||||||
|
parse_args(s);
|
||||||
|
if (0 == (w & 1))
|
||||||
|
tcc_set_options(s, "-w");
|
||||||
|
if (w & 2) {
|
||||||
|
tcc_set_options(s, "-bt");
|
||||||
|
tcc_define_symbol(s, "N_CRASH", str(M/2));
|
||||||
|
} else
|
||||||
|
tcc_define_symbol(s, "N_CRASH", "-1000");
|
||||||
|
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *reloc_state(TCCState *s, const char *entry)
|
||||||
|
{
|
||||||
|
void *func;
|
||||||
|
tcc_add_symbol(s, "add", add);
|
||||||
|
tcc_add_symbol(s, "printf", printf);
|
||||||
|
if (tcc_relocate(s) < 0) {
|
||||||
|
fprintf(stderr, __FILE__ ": could not relocate tcc state.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
func = tcc_get_symbol(s, entry);
|
||||||
|
if (!func)
|
||||||
|
fprintf(stderr, __FILE__ ": could not get entry symbol.\n");
|
||||||
|
return func;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* work with several states at the same time */
|
||||||
|
int state_test(int w)
|
||||||
|
{
|
||||||
|
TCCState *s[M];
|
||||||
|
int (*funcs[M])(int);
|
||||||
|
int n;
|
||||||
|
jmp_buf jb;
|
||||||
|
|
||||||
|
for (n = 0; n < M + 4; ++n) {
|
||||||
|
unsigned a = n, b = n - 1, c = n - 2, d = n - 3, e = n - 4;
|
||||||
|
if (a < M)
|
||||||
|
s[a] = new_state(w);
|
||||||
|
if (b < M)
|
||||||
|
if (tcc_compile_string(s[b], my_program) == -1)
|
||||||
|
break;
|
||||||
|
if (c < M)
|
||||||
|
funcs[c] = reloc_state(s[c], "foo");
|
||||||
|
if (d < M && funcs[d]) {
|
||||||
|
tcc_set_backtrace_func(s[d], &d, backtrace_func);
|
||||||
|
if (0 == tcc_setjmp(s[d], jb, funcs[d]))
|
||||||
|
funcs[d](F(d));
|
||||||
|
}
|
||||||
|
if (e < M)
|
||||||
|
tcc_delete(s[e]);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* simple compilation in threads */
|
||||||
|
TF_TYPE(thread_test_simple, vn)
|
||||||
|
{
|
||||||
|
TCCState *s;
|
||||||
|
int (*func)(int);
|
||||||
|
int ret;
|
||||||
|
int n = (size_t)vn;
|
||||||
|
jmp_buf jb;
|
||||||
|
|
||||||
|
s = new_state(0); /* '2' for exceptions */
|
||||||
|
sleep_ms(1);
|
||||||
|
ret = tcc_compile_string(s, my_program);
|
||||||
|
sleep_ms(1);
|
||||||
|
if (ret >= 0) {
|
||||||
|
func = reloc_state(s, "foo");
|
||||||
|
tcc_set_backtrace_func(s, &n, backtrace_func);
|
||||||
|
if (func) {
|
||||||
|
if (0 == tcc_setjmp(s, jb, func))
|
||||||
|
func(F(n));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tcc_delete(s);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* more complex compilation in threads */
|
||||||
|
TF_TYPE(thread_test_complex, vn)
|
||||||
|
{
|
||||||
|
TCCState *s;
|
||||||
|
int ret;
|
||||||
|
int n = (size_t)vn;
|
||||||
|
char *argv[30], b[10];
|
||||||
|
int argc = 0, i;
|
||||||
|
|
||||||
|
sprintf(b, "%d", F(n));
|
||||||
|
|
||||||
|
for (i = 1; i < g_argc; ++i) argv[argc++] = g_argv[i];
|
||||||
|
#if 0
|
||||||
|
argv[argc++] = "-run";
|
||||||
|
for (i = 1; i < g_argc; ++i) argv[argc++] = g_argv[i];
|
||||||
|
#endif
|
||||||
|
argv[argc++] = "-DFIB";
|
||||||
|
argv[argc++] = "-run";
|
||||||
|
argv[argc++] = __FILE__;
|
||||||
|
argv[argc++] = b;
|
||||||
|
argv[argc] = NULL;
|
||||||
|
|
||||||
|
s = new_state(1);
|
||||||
|
sleep_ms(2);
|
||||||
|
ret = tcc_add_file(s, argv[0]);
|
||||||
|
sleep_ms(3);
|
||||||
|
if (ret == 0)
|
||||||
|
tcc_run(s, argc, argv);
|
||||||
|
tcc_delete(s);
|
||||||
|
fflush(stdout);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void time_tcc(int n, const char *src)
|
||||||
|
{
|
||||||
|
TCCState *s;
|
||||||
|
int ret, i = 0;
|
||||||
|
while (i++ < n) {
|
||||||
|
s = new_state(1);
|
||||||
|
printf(" %d", i), fflush(stdout);
|
||||||
|
ret = tcc_add_file(s, src);
|
||||||
|
tcc_delete(s);
|
||||||
|
if (ret < 0)
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned getclock_ms(void)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
return GetTickCount();
|
||||||
|
#else
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
return tv.tv_sec*1000 + (tv.tv_usec+500)/1000;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
unsigned t;
|
||||||
|
|
||||||
|
g_argc = argc;
|
||||||
|
g_argv = argv;
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
fprintf(stderr, "usage: libtcc_test_mt tcc.c <options>\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
printf("running fib with mixed calls\n "), fflush(stdout);
|
||||||
|
t = getclock_ms();
|
||||||
|
state_test(0);
|
||||||
|
printf("\n (%u ms)\n", getclock_ms() - t);
|
||||||
|
#endif
|
||||||
|
#if 1
|
||||||
|
printf("producing some exceptions (!)\n "), fflush(stdout);
|
||||||
|
t = getclock_ms();
|
||||||
|
state_test(2);
|
||||||
|
printf("\n (%u ms)\n", getclock_ms() - t);
|
||||||
|
#endif
|
||||||
|
#if 1
|
||||||
|
//{ int i; for (i = 0; i < 100; ++i) { printf("(%d) ", i);
|
||||||
|
printf("running fib in threads\n "), fflush(stdout);
|
||||||
|
t = getclock_ms();
|
||||||
|
for (n = 0; n < M; ++n)
|
||||||
|
create_thread(thread_test_simple, n);
|
||||||
|
wait_threads(n);
|
||||||
|
printf("\n (%u ms)\n", getclock_ms() - t);
|
||||||
|
//}}
|
||||||
|
#endif
|
||||||
|
#if 1
|
||||||
|
printf("running tcc.c in threads to run fib\n "), fflush(stdout);
|
||||||
|
t = getclock_ms();
|
||||||
|
for (n = 0; n < M; ++n)
|
||||||
|
create_thread(thread_test_complex, n);
|
||||||
|
wait_threads(n);
|
||||||
|
printf("\n (%u ms)\n", getclock_ms() - t);
|
||||||
|
#endif
|
||||||
|
#if 1
|
||||||
|
printf("compiling tcc.c 10 times\n "), fflush(stdout);
|
||||||
|
t = getclock_ms();
|
||||||
|
time_tcc(10, argv[1]);
|
||||||
|
printf("\n (%u ms)\n", getclock_ms() - t), fflush(stdout);
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
#include <tcclib.h>
|
||||||
|
#ifdef _WIN32
|
||||||
|
# ifndef _WIN64
|
||||||
|
__declspec(stdcall)
|
||||||
|
# endif
|
||||||
|
void Sleep(unsigned);
|
||||||
|
# define sleep_ms Sleep
|
||||||
|
#else
|
||||||
|
int usleep(unsigned long);
|
||||||
|
# define sleep_ms(x) usleep((x)*1000);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int fib(n)
|
||||||
|
{
|
||||||
|
return (n <= 2) ? 1 : fib(n-1) + fib(n-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
sleep_ms(333);
|
||||||
|
printf(" %d", fib(atoi(argv[1])));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
164
tests/msvcrt_start.c
Normal file
164
tests/msvcrt_start.c
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
/* ------------------------------------------------------------- */
|
||||||
|
/* minimal startup with runtime linker to msvcrt */
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
#define REDIR_ALL \
|
||||||
|
REDIR(__set_app_type)\
|
||||||
|
REDIR(__getmainargs)\
|
||||||
|
REDIR(_controlfp)\
|
||||||
|
REDIR(_vsnprintf)\
|
||||||
|
REDIR(exit)\
|
||||||
|
\
|
||||||
|
REDIR(puts)\
|
||||||
|
REDIR(printf)\
|
||||||
|
REDIR(putchar)\
|
||||||
|
REDIR(strtod)\
|
||||||
|
REDIR(memset)\
|
||||||
|
REDIR(strcpy)\
|
||||||
|
REDIR(strlen)\
|
||||||
|
REDIR(malloc)\
|
||||||
|
REDIR(free)\
|
||||||
|
|
||||||
|
#if defined __i386__ && !defined __TINYC__
|
||||||
|
# define __leading_underscore 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __leading_underscore
|
||||||
|
# define _(s) "_"#s
|
||||||
|
#else
|
||||||
|
# define _(s) #s
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define REDIR(s) void *s;
|
||||||
|
static struct { REDIR_ALL } all_ptrs;
|
||||||
|
#undef REDIR
|
||||||
|
|
||||||
|
#define REDIR(s) #s"\0"
|
||||||
|
static const char all_names[] = REDIR_ALL;
|
||||||
|
#undef REDIR
|
||||||
|
|
||||||
|
#if __aarch64__
|
||||||
|
#if defined __TINYC__
|
||||||
|
# define ALIGN ".align 8"
|
||||||
|
#else
|
||||||
|
# define ALIGN ".align 3" /* .align is power of 2 on non-ELF platforms */
|
||||||
|
#endif
|
||||||
|
# define REDIR(s) \
|
||||||
|
__asm__("\n"_(s)":"); \
|
||||||
|
__asm__(".int 0x58000090"); /* ldr x16, [pc, #16] */ \
|
||||||
|
__asm__(".int 0xf9400210"); /* ldr x16, [x16] */ \
|
||||||
|
__asm__(".int 0xd61f0200"); /* br x16 */ \
|
||||||
|
__asm__(".int 0xd503201f"); /* nop for alignment */ \
|
||||||
|
__asm__(".quad all_ptrs + (. - all_jmps - 16) / 24 * 8"); \
|
||||||
|
__asm__(".global "_(s));
|
||||||
|
|
||||||
|
__asm__("\t.text\n\t"ALIGN"\nall_jmps:");
|
||||||
|
REDIR_ALL
|
||||||
|
#else
|
||||||
|
# define REDIR(s) \
|
||||||
|
__asm__("\n"_(s)":");\
|
||||||
|
__asm__("jmp *%0"::"m"(all_ptrs.s));\
|
||||||
|
__asm__(".global "_(s));
|
||||||
|
|
||||||
|
static void all_jmps() { REDIR_ALL }
|
||||||
|
#endif
|
||||||
|
#undef REDIR
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
# include <windows.h>
|
||||||
|
#else
|
||||||
|
# if __i386__
|
||||||
|
# define STDCALL __declspec(stdcall)
|
||||||
|
# else
|
||||||
|
# define STDCALL
|
||||||
|
# endif
|
||||||
|
# define DWORD long unsigned
|
||||||
|
# define HMODULE void*
|
||||||
|
# define HANDLE void*
|
||||||
|
S TDCALL HMODULE LoadLibraryA(const char *);
|
||||||
|
S TDCALL HMODULE GetProcAddress(HMODULE , char*);
|
||||||
|
S TDCALL void ExitProcess(int);
|
||||||
|
S TDCALL int WriteFile(HANDLE, const void*, DWORD, DWORD*, void*);
|
||||||
|
S TDCALL HANDLE GetStdHandle(DWORD);
|
||||||
|
S TDCALL int FlushFileBuffers(HANDLE);
|
||||||
|
# define STD_ERROR_HANDLE -12
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void eput(const char *s)
|
||||||
|
{
|
||||||
|
DWORD n_out;
|
||||||
|
int n = 0;
|
||||||
|
while (s[n])
|
||||||
|
++n;
|
||||||
|
WriteFile(GetStdHandle(STD_ERROR_HANDLE), s, n, &n_out, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rt_reloc()
|
||||||
|
{
|
||||||
|
const char *s = all_names;
|
||||||
|
void **p = (void**)&all_ptrs;
|
||||||
|
void *dll = LoadLibraryA("msvcrt.dll");
|
||||||
|
do {
|
||||||
|
char buf[100], *d = buf;
|
||||||
|
*p = (void*)GetProcAddress(dll, (char*)s);
|
||||||
|
*d++ = '_'; do *d++ = *s; while (*s++);
|
||||||
|
if (0 == *p)
|
||||||
|
*p = (void*)GetProcAddress(dll, buf);
|
||||||
|
if (0 == *p) {
|
||||||
|
eput("MSVCRT_START.C: RUNTIME RELOCATION ERROR: '");
|
||||||
|
eput(buf+1);
|
||||||
|
eput("'\n");
|
||||||
|
ExitProcess(-1);
|
||||||
|
}
|
||||||
|
++p;
|
||||||
|
} while (*s);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
# define rt_reloc()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main(int argc, char **argv, char **env);
|
||||||
|
void exit(int);
|
||||||
|
void __set_app_type(int apptype);
|
||||||
|
|
||||||
|
typedef struct { int newmode; } _startupinfo;
|
||||||
|
int __getmainargs(int *pargc, char ***pargv, char ***penv, int globb, _startupinfo*);
|
||||||
|
|
||||||
|
void _controlfp(unsigned a, unsigned b);
|
||||||
|
#define _MCW_PC 0x00030000 // Precision Control
|
||||||
|
#define _PC_53 0x00010000 // 53 bits
|
||||||
|
|
||||||
|
int __argc;
|
||||||
|
char **__argv;
|
||||||
|
char **environ;
|
||||||
|
_startupinfo start_info = {0};
|
||||||
|
|
||||||
|
void mainCRTStartup(void)
|
||||||
|
{
|
||||||
|
rt_reloc();
|
||||||
|
#if defined __i386__ || defined __x86_64__
|
||||||
|
_controlfp(_PC_53, _MCW_PC);
|
||||||
|
#endif
|
||||||
|
__set_app_type(1);
|
||||||
|
__getmainargs(&__argc, &__argv, &environ, 0, &start_info);
|
||||||
|
exit(main(__argc, __argv, environ));
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#define size_t __SIZE_TYPE__
|
||||||
|
int printf(const char *, ...);
|
||||||
|
int _vsnprintf(char *, size_t, const char *, va_list);
|
||||||
|
|
||||||
|
/* undefined on windows-11-arm64 */
|
||||||
|
int vprintf(const char *format, va_list ap)
|
||||||
|
{
|
||||||
|
char buf[1000];
|
||||||
|
_vsnprintf(buf, sizeof buf, format, ap);
|
||||||
|
return printf("%s", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __main() {} /* for gcc */
|
||||||
|
void _pei386_runtime_relocator(void) {} /* for gcc */
|
||||||
|
void __chkstk(unsigned n) {} /* for clang */
|
||||||
@ -14,7 +14,7 @@ x D4(a, b) y
|
|||||||
x D4(a) y
|
x D4(a) y
|
||||||
x D4() y
|
x D4() y
|
||||||
|
|
||||||
#define GNU_COMMA(X,Y...) X,## Y
|
#define GNU_COMMA(X,Y...) X,##Y
|
||||||
|
|
||||||
x GNU_COMMA(A,B,C) y
|
x GNU_COMMA(A,B,C) y
|
||||||
x GNU_COMMA(A,B) y
|
x GNU_COMMA(A,B) y
|
||||||
@ -29,3 +29,8 @@ __NORETURN
|
|||||||
#define X(...)
|
#define X(...)
|
||||||
#define Y(...) 1 __VA_ARGS__ 2
|
#define Y(...) 1 __VA_ARGS__ 2
|
||||||
Y(X X() ())
|
Y(X X() ())
|
||||||
|
|
||||||
|
#define DDD(A, B) D_ ## B ## _D_ ## A
|
||||||
|
#define CCC(X, ...) DDD(X,## __VA_ARGS__)
|
||||||
|
/* must be D_B_D_A (not D_B _D_A) */
|
||||||
|
CCC(A,B)
|
||||||
|
|||||||
@ -6,10 +6,11 @@ x a b c d y
|
|||||||
x a b c y
|
x a b c y
|
||||||
x a b y
|
x a b y
|
||||||
x a y
|
x a y
|
||||||
x y
|
x y
|
||||||
x A,B,C y
|
x A,B,C y
|
||||||
x A,B y
|
x A,B y
|
||||||
x A y
|
x A y
|
||||||
x y
|
x y
|
||||||
__attribute__((__noreturn__))
|
__attribute__((__noreturn__))
|
||||||
1 2
|
1 2
|
||||||
|
D_B_D_A
|
||||||
|
|||||||
@ -13,3 +13,18 @@
|
|||||||
X181 M_EMPTYI_P_C1()
|
X181 M_EMPTYI_P_C1()
|
||||||
X182 M_EMPTYI_P_C1(x)
|
X182 M_EMPTYI_P_C1(x)
|
||||||
X183 usefnlike()
|
X183 usefnlike()
|
||||||
|
|
||||||
|
#define ABC(x) ABC : x
|
||||||
|
#define A(a,b,c) a ## b ## c
|
||||||
|
#define B(a,b,c) A(a,b,c)
|
||||||
|
#define C(a,b,c) a b c
|
||||||
|
B(
|
||||||
|
C(A,C(,,),),
|
||||||
|
C(B(,,),B,B(,,)),
|
||||||
|
C(B(,,),B(,,),C)
|
||||||
|
)/* */(a b c)
|
||||||
|
|
||||||
|
#define TEST(x) TEST : x
|
||||||
|
#define K(a,b) a ## b
|
||||||
|
#define L(a,b) K( TE a , b ST )
|
||||||
|
L(,)(t e s t)
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
X181 1
|
X181 1
|
||||||
X182 0
|
X182 0
|
||||||
X183 yeah
|
X183 yeah
|
||||||
|
ABC : a b c
|
||||||
|
TEST : t e s t
|
||||||
|
|||||||
@ -34,3 +34,29 @@ OK
|
|||||||
#else
|
#else
|
||||||
NOT OK
|
NOT OK
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
----- 5 ------
|
||||||
|
line __LINE__
|
||||||
|
#define __LINE__ # ## #
|
||||||
|
line __LINE__
|
||||||
|
|
||||||
|
----- 10 ------
|
||||||
|
/* preprocessor numbers are (u)intmax_t */
|
||||||
|
#if -2147483648 < 0
|
||||||
|
1 true
|
||||||
|
#endif
|
||||||
|
#if -0x80000000 < 0
|
||||||
|
2 true
|
||||||
|
#endif
|
||||||
|
#if -9223372036854775808U > 0
|
||||||
|
3 true
|
||||||
|
#endif
|
||||||
|
#if -0x8000000000000000 > 0 // unsigned by overflow
|
||||||
|
4 true
|
||||||
|
#endif
|
||||||
|
#if 1 << 31 > 2 && 1 << 32 > 2 && 1 << 63 < 2 && 1U << 63 > 2
|
||||||
|
5 true
|
||||||
|
#endif
|
||||||
|
#if (1<<29) * 11 >= 1<<32 && defined DDD << 63 < 0
|
||||||
|
6 true
|
||||||
|
#endif
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user