mirror of
https://github.com/ptitSeb/box64.git
synced 2026-11-08 10:10:25 -10:00
Compare commits
621
Commits
save_memory
...
v0.2.6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e42001b2bc | ||
|
|
9818f5b6a3 | ||
|
|
46e40fbb65 | ||
|
|
c141dbbd82 | ||
|
|
9d5d08fa6c | ||
|
|
7b9aa5b91a | ||
|
|
8c75f7659f | ||
|
|
d8c40c1662 | ||
|
|
7c0180c3b9 | ||
|
|
211fee2e4e | ||
|
|
9b7b91651d | ||
|
|
6ecfe5e141 | ||
|
|
e11291538c | ||
|
|
5b90d59877 | ||
|
|
85df885b90 | ||
|
|
4dd5b67bbf | ||
|
|
88575ebc5d | ||
|
|
d8a19e9832 | ||
|
|
99a938ef37 | ||
|
|
b07ea3460e | ||
|
|
f557a86ecc | ||
|
|
a5f8dd0788 | ||
|
|
effbd82d00 | ||
|
|
9d72c9db1b | ||
|
|
486df332dd | ||
|
|
8806c8ba8b | ||
|
|
0df1e38ded | ||
|
|
7344689ba6 | ||
|
|
0ddbb80ee3 | ||
|
|
48667b7dda | ||
|
|
5708bc6b49 | ||
|
|
9481df50b1 | ||
|
|
840c454c1c | ||
|
|
77143dc8cf | ||
|
|
e3e77a8234 | ||
|
|
c3e84e6daa | ||
|
|
c3f71c43e9 | ||
|
|
df2ad6b1ca | ||
|
|
1d462b7558 | ||
|
|
0a8c3ddd71 | ||
|
|
6ab86657ff | ||
|
|
aed66d81b3 | ||
|
|
e355280232 | ||
|
|
92fff0c903 | ||
|
|
06319911d4 | ||
|
|
98959e902b | ||
|
|
1e996410f8 | ||
|
|
548a8ac87b | ||
|
|
44494df9d3 | ||
|
|
60c698d381 | ||
|
|
df3e1ace61 | ||
|
|
6def5118bb | ||
|
|
7d3224e37f | ||
|
|
28a1581bb6 | ||
|
|
66b8e697ea | ||
|
|
c15f1c917a | ||
|
|
5b72444a6d | ||
|
|
94a37bb60a | ||
|
|
935113a53d | ||
|
|
d39ed15517 | ||
|
|
1dce5ef39f | ||
|
|
2c69b57617 | ||
|
|
06961d3db5 | ||
|
|
bdf2922f5d | ||
|
|
f52d13f86a | ||
|
|
1b7b361b30 | ||
|
|
151c40441f | ||
|
|
e26363dc0f | ||
|
|
5dbc8bf383 | ||
|
|
27e6cf0e31 | ||
|
|
24f241a1cd | ||
|
|
a8febc8638 | ||
|
|
c04dfb82bb | ||
|
|
08d189683d | ||
|
|
b67975a820 | ||
|
|
fa175e7d24 | ||
|
|
c2221e5304 | ||
|
|
104b5ec6d6 | ||
|
|
59b4780afa | ||
|
|
899405456b | ||
|
|
40a81173f3 | ||
|
|
19a6608619 | ||
|
|
558a52909d | ||
|
|
76eb623de6 | ||
|
|
9e45c05383 | ||
|
|
c0a1529468 | ||
|
|
f4a7a88167 | ||
|
|
44ecb62ce7 | ||
|
|
37a976831d | ||
|
|
dd1aeb7265 | ||
|
|
777c62c056 | ||
|
|
717cddcc3d | ||
|
|
d6f7f620fc | ||
|
|
1bd928a766 | ||
|
|
e493b0775d | ||
|
|
a966fa34ae | ||
|
|
8cd27fca4d | ||
|
|
3676ca15c8 | ||
|
|
616f7d3def | ||
|
|
ec4c6ec7a1 | ||
|
|
941fa6d520 | ||
|
|
ce5e561cf3 | ||
|
|
8e5a00db76 | ||
|
|
faaeffbd38 | ||
|
|
a070066b71 | ||
|
|
4e92269ae1 | ||
|
|
994971b08f | ||
|
|
019c0fabe1 | ||
|
|
8e5346be21 | ||
|
|
5f9d1f62cf | ||
|
|
d7bdf862bf | ||
|
|
6470442e08 | ||
|
|
6157f53aae | ||
|
|
3f2d4a5274 | ||
|
|
ae83035380 | ||
|
|
4566ff6d24 | ||
|
|
cbceca3b35 | ||
|
|
436de1c4f5 | ||
|
|
737d4a5506 | ||
|
|
e5b16e9ef1 | ||
|
|
ea64f8453f | ||
|
|
507eb1c786 | ||
|
|
04f8ab3871 | ||
|
|
6b390caef5 | ||
|
|
8cee527ad0 | ||
|
|
bdf7d47742 | ||
|
|
6ad9435b4d | ||
|
|
e853892282 | ||
|
|
4969b8c252 | ||
|
|
239ef8951d | ||
|
|
494510e2a8 | ||
|
|
6dd899df22 | ||
|
|
7c4b97961f | ||
|
|
5c0a82913f | ||
|
|
d7e64d3f11 | ||
|
|
ea8d725546 | ||
|
|
cfffbcc5be | ||
|
|
ba80b40e9e | ||
|
|
b0fe7ecf8c | ||
|
|
84a6cfd558 | ||
|
|
efbf692cca | ||
|
|
f81057416b | ||
|
|
168675d380 | ||
|
|
6327477695 | ||
|
|
4c7ac85ae8 | ||
|
|
afe6fbe3b3 | ||
|
|
39568bff2f | ||
|
|
d3b44f1c84 | ||
|
|
8e74746573 | ||
|
|
bb54f234bd | ||
|
|
572a84c19b | ||
|
|
8fe46092c0 | ||
|
|
02bad8bcd1 | ||
|
|
54be0c0dec | ||
|
|
20df2789b5 | ||
|
|
a8f902885d | ||
|
|
c17e37b6e0 | ||
|
|
df25986597 | ||
|
|
dc06ca51a6 | ||
|
|
d76ea27c54 | ||
|
|
90b606584d | ||
|
|
19a24c2171 | ||
|
|
f7d75ca641 | ||
|
|
5baa083386 | ||
|
|
6f7cb088b0 | ||
|
|
8901d1c37d | ||
|
|
ec9dedd75c | ||
|
|
3edf7ee978 | ||
|
|
9e35b66510 | ||
|
|
713458ac81 | ||
|
|
90e2f04c34 | ||
|
|
9896b02bd6 | ||
|
|
d39dd45ae4 | ||
|
|
d50ae52176 | ||
|
|
784be47702 | ||
|
|
4f1fa811d0 | ||
|
|
201cd065a9 | ||
|
|
d832ec8ab2 | ||
|
|
0c6c01d86a | ||
|
|
13612d4024 | ||
|
|
9daf8d6493 | ||
|
|
e071406829 | ||
|
|
ff85b03e3f | ||
|
|
590429d104 | ||
|
|
eb0b5bd3f8 | ||
|
|
b15a902f6d | ||
|
|
4468d63145 | ||
|
|
aba5c428e9 | ||
|
|
62966c2f64 | ||
|
|
dfd2a4ef0e | ||
|
|
7fcc6e010c | ||
|
|
5d2ae4aa1e | ||
|
|
4318172edd | ||
|
|
9201559b1d | ||
|
|
40f90dd8f3 | ||
|
|
308cc81a27 | ||
|
|
7e8f8cf415 | ||
|
|
62634c6e1e | ||
|
|
70e4bd4174 | ||
|
|
7e0e618222 | ||
|
|
cf6f013909 | ||
|
|
2ed8557ea6 | ||
|
|
da3373ae42 | ||
|
|
cd0173dae4 | ||
|
|
02e7400ef0 | ||
|
|
6d6f29b6e1 | ||
|
|
0260b3177e | ||
|
|
b82d9d15d4 | ||
|
|
3bc0495eb2 | ||
|
|
50c0b60c10 | ||
|
|
c2680fd0a7 | ||
|
|
85c74c6bf8 | ||
|
|
93f665eb9c | ||
|
|
113c879d7a | ||
|
|
f13ee05c6a | ||
|
|
90fd2ff6a3 | ||
|
|
3a40b9f3a3 | ||
|
|
d8805b6af7 | ||
|
|
675336dee5 | ||
|
|
3cd4ed8e63 | ||
|
|
9c7208b1fa | ||
|
|
48af038643 | ||
|
|
ca8ad5e554 | ||
|
|
ab146f5d23 | ||
|
|
13fdd31c67 | ||
|
|
28f69afe96 | ||
|
|
2827e9e253 | ||
|
|
46ba6fc561 | ||
|
|
b3997769c0 | ||
|
|
410f58b7c7 | ||
|
|
fbecdad199 | ||
|
|
9e6e3160ff | ||
|
|
ca8abae240 | ||
|
|
6f0d095364 | ||
|
|
cc661c7549 | ||
|
|
6982846f50 | ||
|
|
eb6ec17504 | ||
|
|
8c68e1108b | ||
|
|
9077fd7b51 | ||
|
|
f8b88418ed | ||
|
|
9c12016859 | ||
|
|
e6943c8a9d | ||
|
|
c6483b5cf8 | ||
|
|
60925658bb | ||
|
|
5ef9ea35d6 | ||
|
|
901bb48877 | ||
|
|
9fc37e6418 | ||
|
|
b34cce3f75 | ||
|
|
787646b3cc | ||
|
|
f0d5e9d01e | ||
|
|
be05309e51 | ||
|
|
52811e2ec2 | ||
|
|
107738f0f2 | ||
|
|
936fa20928 | ||
|
|
362a3fde10 | ||
|
|
5c13f8f10a | ||
|
|
20cf990bf7 | ||
|
|
00744bc0e5 | ||
|
|
cb2a623faa | ||
|
|
7e80e7ba86 | ||
|
|
c50c985c85 | ||
|
|
c3ee794d40 | ||
|
|
c8502fa20c | ||
|
|
a31c037165 | ||
|
|
c71035530a | ||
|
|
acaf23fcb8 | ||
|
|
15860f3245 | ||
|
|
8a1e4cdf30 | ||
|
|
e574dca373 | ||
|
|
32fc932813 | ||
|
|
8a471d4d11 | ||
|
|
81ca3cd06e | ||
|
|
f8d65a831e | ||
|
|
a1ac21af75 | ||
|
|
d3d5e4e7bc | ||
|
|
c11cd7f4af | ||
|
|
840f2dced7 | ||
|
|
f81d6cf262 | ||
|
|
fe378c938a | ||
|
|
d9a4fed2f8 | ||
|
|
2a4fe80399 | ||
|
|
8999713301 | ||
|
|
0900cc2f59 | ||
|
|
87bf751b11 | ||
|
|
12c40a5b80 | ||
|
|
e9a2f9ff62 | ||
|
|
1fc382f74f | ||
|
|
65fc95b614 | ||
|
|
4354e8c861 | ||
|
|
f1014bbbb6 | ||
|
|
72f232e776 | ||
|
|
b7ebc35193 | ||
|
|
671328aaf6 | ||
|
|
c7bd174d7c | ||
|
|
54f8d05105 | ||
|
|
892f102e4a | ||
|
|
f9b54dab31 | ||
|
|
b3daf55ec2 | ||
|
|
391cef8549 | ||
|
|
59b51cccfc | ||
|
|
a83091bc3b | ||
|
|
7372540fce | ||
|
|
ceaa4bcac6 | ||
|
|
862f31ef1c | ||
|
|
6643bf8695 | ||
|
|
3c0297fbdf | ||
|
|
479cdb4218 | ||
|
|
6389ccee8d | ||
|
|
d478f98a4c | ||
|
|
dba0058763 | ||
|
|
10b4782efb | ||
|
|
f82d8d647a | ||
|
|
1698c822a5 | ||
|
|
c9177ec259 | ||
|
|
0481589615 | ||
|
|
6ef2b22a3c | ||
|
|
da19b2008a | ||
|
|
5493ab345a | ||
|
|
2589f7db14 | ||
|
|
2e283b9d6d | ||
|
|
3cf27bb46e | ||
|
|
f67d0709b7 | ||
|
|
2e66d603d3 | ||
|
|
d51560211c | ||
|
|
1b620b31d5 | ||
|
|
b82b730bf9 | ||
|
|
9191c993b1 | ||
|
|
1a2245043d | ||
|
|
2df7b9f302 | ||
|
|
202cbc62db | ||
|
|
9209e57bd9 | ||
|
|
1e1ad7694b | ||
|
|
b920d37f4e | ||
|
|
3cb2bc31a8 | ||
|
|
be24eec9d0 | ||
|
|
60fed04cb7 | ||
|
|
6c956013a6 | ||
|
|
59289ae8f9 | ||
|
|
8310e9762b | ||
|
|
99483d2913 | ||
|
|
b77303931e | ||
|
|
5863dc6c7c | ||
|
|
2a3923a173 | ||
|
|
3e882f3fd9 | ||
|
|
0499c38466 | ||
|
|
3e18d5ea57 | ||
|
|
ae75a502f0 | ||
|
|
6ac200f597 | ||
|
|
d7f635586d | ||
|
|
e27156be58 | ||
|
|
cafe638d5a | ||
|
|
4d996f6273 | ||
|
|
86dfd2840f | ||
|
|
dd9c3a53bf | ||
|
|
57959a1e93 | ||
|
|
6cfd7a988b | ||
|
|
ef95ff3342 | ||
|
|
773c17496e | ||
|
|
6118dafd94 | ||
|
|
8befcbfacf | ||
|
|
b9ea4983f9 | ||
|
|
d8765f86dd | ||
|
|
3d9744362f | ||
|
|
b2162ba263 | ||
|
|
aba40a9360 | ||
|
|
1a9e076685 | ||
|
|
2d9a3c643a | ||
|
|
85d2a06f6f | ||
|
|
8a5719afe1 | ||
|
|
2ec01c9b60 | ||
|
|
5fa02ef1e3 | ||
|
|
cfe8f8f6e1 | ||
|
|
9d63f0ce9a | ||
|
|
afd8d305f3 | ||
|
|
83738a606d | ||
|
|
072311b256 | ||
|
|
c904a9af1c | ||
|
|
7c042a566a | ||
|
|
57b762eb29 | ||
|
|
a4eb0cbd74 | ||
|
|
e558912a36 | ||
|
|
00ea757e77 | ||
|
|
2f04934471 | ||
|
|
1e6f492852 | ||
|
|
582c7c762a | ||
|
|
3ad64aa6a4 | ||
|
|
1c680d3aaa | ||
|
|
eed9ea35f9 | ||
|
|
a724725fdf | ||
|
|
84a5929645 | ||
|
|
cb85a8f5cb | ||
|
|
23dd80ffd8 | ||
|
|
16393c499b | ||
|
|
684160f178 | ||
|
|
e3f193b382 | ||
|
|
37d9c4b480 | ||
|
|
b6633aa306 | ||
|
|
c8651fb1f3 | ||
|
|
83a5b0d223 | ||
|
|
d95ef48d22 | ||
|
|
b59ce0b95b | ||
|
|
c00cd1d627 | ||
|
|
ab65641eae | ||
|
|
6c0781c157 | ||
|
|
bf6c6498aa | ||
|
|
4b6cec8452 | ||
|
|
b77da2635b | ||
|
|
033ddf8cc8 | ||
|
|
5b3c67c692 | ||
|
|
86aa8b8b2e | ||
|
|
0329bbc55e | ||
|
|
c9549e8ab6 | ||
|
|
5903f02086 | ||
|
|
28dcd34624 | ||
|
|
13b7398b3a | ||
|
|
50cf9c0e67 | ||
|
|
71ad38d742 | ||
|
|
c086a1ff24 | ||
|
|
75958f1f31 | ||
|
|
be34e0221d | ||
|
|
0913c94e46 | ||
|
|
910a0ef8e1 | ||
|
|
7b0e8b47a2 | ||
|
|
14e799ebe5 | ||
|
|
5e52c735a6 | ||
|
|
9eb5883f77 | ||
|
|
7a783b867b | ||
|
|
83ec0bd751 | ||
|
|
aacff4a9b6 | ||
|
|
7ab8ad8b10 | ||
|
|
cf7ac30215 | ||
|
|
547944ac88 | ||
|
|
99d7b46e48 | ||
|
|
eca872c04d | ||
|
|
8947b735f9 | ||
|
|
e245dee90b | ||
|
|
edba2a2e96 | ||
|
|
81e8ce4952 | ||
|
|
afd5d3a1e3 | ||
|
|
d1e8bcd7a5 | ||
|
|
79c71bf5c1 | ||
|
|
2c7daa388b | ||
|
|
cc351402a1 | ||
|
|
90a7602e5a | ||
|
|
1e0b8e443b | ||
|
|
96025a1977 | ||
|
|
6e1bcc03a6 | ||
|
|
728ec2e769 | ||
|
|
25a064f3a8 | ||
|
|
8a25b91ad2 | ||
|
|
cacd7dd2eb | ||
|
|
acf6825603 | ||
|
|
1b8c48ee1d | ||
|
|
6a6b75b7b4 | ||
|
|
491cbda0d3 | ||
|
|
aadd5e8786 | ||
|
|
e155d43c4b | ||
|
|
683f5d64b9 | ||
|
|
d26469c6a4 | ||
|
|
57d497c801 | ||
|
|
eac105fe9e | ||
|
|
61c2a3ed7a | ||
|
|
46031c008e | ||
|
|
d2aadd66bf | ||
|
|
646770ff68 | ||
|
|
90ad165359 | ||
|
|
30eae8f513 | ||
|
|
2d37575f3d | ||
|
|
eb1e607b93 | ||
|
|
9d16aec99a | ||
|
|
a95099696f | ||
|
|
be4791f826 | ||
|
|
41d5fa16a7 | ||
|
|
d3635126b7 | ||
|
|
7cba83231a | ||
|
|
7f4145d67f | ||
|
|
103c804c8e | ||
|
|
c7db4470e4 | ||
|
|
2e55fc8c32 | ||
|
|
5d921acd7d | ||
|
|
aa051b662e | ||
|
|
5fabd602ae | ||
|
|
0393e15843 | ||
|
|
539fb8e214 | ||
|
|
7b1fa28b85 | ||
|
|
30475f0eda | ||
|
|
19771b307c | ||
|
|
7a992837a1 | ||
|
|
33d8fa7b23 | ||
|
|
62d55296c0 | ||
|
|
cd0aad731a | ||
|
|
8e7afcc5fb | ||
|
|
a62618ee47 | ||
|
|
4e9b7f27a9 | ||
|
|
7d7ea4405c | ||
|
|
45c4117a40 | ||
|
|
4bd00b0f91 | ||
|
|
9e7225be36 | ||
|
|
154acbef72 | ||
|
|
502611702e | ||
|
|
009b9f7f3d | ||
|
|
77161c8e4d | ||
|
|
b4cd6f27ba | ||
|
|
2bb42ae9a9 | ||
|
|
54ce282b8c | ||
|
|
47057f076a | ||
|
|
7f775b7662 | ||
|
|
48317e0788 | ||
|
|
6c77c8f1aa | ||
|
|
ca759d2c8f | ||
|
|
53a59f593e | ||
|
|
d621670735 | ||
|
|
6653cce464 | ||
|
|
acfbed72de | ||
|
|
c4e322a23a | ||
|
|
6b9d617fa6 | ||
|
|
607ac40ab3 | ||
|
|
69c7ca8bdc | ||
|
|
692eb90dcd | ||
|
|
eee1c62325 | ||
|
|
442c3fdb9b | ||
|
|
e2077c46ce | ||
|
|
e8972efca1 | ||
|
|
f86c856e3b | ||
|
|
6bb674420a | ||
|
|
ee0fdc4332 | ||
|
|
4006992f8d | ||
|
|
8d04940c91 | ||
|
|
4f1d3a75c2 | ||
|
|
24c8af0363 | ||
|
|
4474af2a9a | ||
|
|
a3765ec0f8 | ||
|
|
b04712898c | ||
|
|
adaafc2a6d | ||
|
|
3308cc60e9 | ||
|
|
e4b235378b | ||
|
|
4f5f6b25e8 | ||
|
|
4b40179bc3 | ||
|
|
0f7b23148f | ||
|
|
a46923e494 | ||
|
|
1e7b4b8450 | ||
|
|
0edf24ae97 | ||
|
|
82f60fee35 | ||
|
|
1333e37b71 | ||
|
|
7f3e0b8fe0 | ||
|
|
937863f4aa | ||
|
|
ff3a639c92 | ||
|
|
3eae7156dc | ||
|
|
e12589ea8b | ||
|
|
6b5ee5ecb5 | ||
|
|
f3a9224547 | ||
|
|
8ef326fdc5 | ||
|
|
fb0e8ee9c6 | ||
|
|
6a8cc8ace3 | ||
|
|
f5fadea30e | ||
|
|
bedfb82066 | ||
|
|
8a403d9126 | ||
|
|
aca4e6585c | ||
|
|
0928f50bc6 | ||
|
|
da098cc1f7 | ||
|
|
8da631a14d | ||
|
|
dafa5014a4 | ||
|
|
879c2f365e | ||
|
|
50032affcf | ||
|
|
784cc3ba9c | ||
|
|
1d5a88a319 | ||
|
|
392575ba04 | ||
|
|
83c808c42d | ||
|
|
9a61392cf9 | ||
|
|
b2c2f7bbd2 | ||
|
|
da6ad1a43d | ||
|
|
f9e4253cb7 | ||
|
|
1675ce83b6 | ||
|
|
9b585ef706 | ||
|
|
67c9378fb8 | ||
|
|
7ab299b246 | ||
|
|
0733a87279 | ||
|
|
28dc8e6751 | ||
|
|
51cbb7e1fb | ||
|
|
3a82317dd5 | ||
|
|
1f2ef09d87 | ||
|
|
5bf0f0215d | ||
|
|
8f968e4c9c | ||
|
|
a8ce60ed4a | ||
|
|
27d8911dee | ||
|
|
4bf909393c | ||
|
|
8fc0e1d384 | ||
|
|
60ae205bd4 | ||
|
|
65045c4897 | ||
|
|
e46133c850 | ||
|
|
37ef57f78f | ||
|
|
3c50d99aba | ||
|
|
508efcf51c | ||
|
|
36d11a4443 | ||
|
|
8590b0b4f3 | ||
|
|
7817d629f1 | ||
|
|
7607a87617 | ||
|
|
b2d37d4ddb | ||
|
|
0003c72fc7 | ||
|
|
915f7cbd54 | ||
|
|
0b3097cd0b | ||
|
|
c7e0ba82b4 | ||
|
|
6168fa4275 | ||
|
|
b61a788ce7 | ||
|
|
903ecd207d | ||
|
|
d62e9652fc | ||
|
|
41e3b2b1a1 | ||
|
|
3349757d0f | ||
|
|
066d7458ca | ||
|
|
88a59b4460 | ||
|
|
aaab83356d | ||
|
|
7c1637328a | ||
|
|
0224346ed8 | ||
|
|
35366b25a6 | ||
|
|
b4c951b66b | ||
|
|
b1c09acb0c | ||
|
|
a6b231ce56 | ||
|
|
0862e4995c | ||
|
|
94832fd7d7 | ||
|
|
7cd82d16ce | ||
|
|
dabbca767f |
No files matched your search
@@ -0,0 +1,14 @@
|
||||
---
|
||||
BasedOnStyle: WebKit
|
||||
AlignTrailingComments: true
|
||||
AllowShortBlocksOnASingleLine: true
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: true
|
||||
AllowShortIfStatementsOnASingleLine: true
|
||||
ColumnLimit: 0
|
||||
IndentWidth: 4
|
||||
SortIncludes: false
|
||||
MaxEmptyLinesToKeep: 2
|
||||
IndentCaseLabels: true
|
||||
AlignConsecutiveMacros: true
|
||||
---
|
||||
@@ -17,8 +17,12 @@ on:
|
||||
- RK3399
|
||||
- RK3588
|
||||
- RPI4ARM64
|
||||
- RPI5ARM64
|
||||
- SD845
|
||||
- SD888
|
||||
- ADLINK
|
||||
- TEGRAX1
|
||||
- ARM64
|
||||
build_type:
|
||||
description: 'Build type'
|
||||
required: true
|
||||
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [X64, OTHER_ARM, RISCV, RPI4ARM64, RK3326, RK3399, RK3588, PHYTIUM, SD845]
|
||||
platform: [X64, OTHER_ARM, RISCV, RPI4ARM64, RPI5ARM64, RK3326, RK3399, RK3588, PHYTIUM, SD845, SD888, ADLINK, ARM64, ANDROID]
|
||||
type: [Release, Trace]
|
||||
os: [ubuntu-latest]
|
||||
include:
|
||||
@@ -47,9 +47,17 @@ jobs:
|
||||
run: |
|
||||
sudo apt-get update
|
||||
if [[ ${{ matrix.platform }} != 'X64' && ${{ matrix.platform }} != 'OTHER_ARM' && ${{ matrix.platform }} != 'RISCV' ]]; then
|
||||
echo "BOX64_PLATFORM_MARCRO=-D${{ matrix.platform }}=1" >> $GITHUB_ENV
|
||||
echo "BOX64_COMPILER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
|
||||
sudo apt-get -y install git gcc-aarch64-linux-gnu cmake make python3
|
||||
sudo apt-get -y install git cmake make python3
|
||||
if [[ ${{ matrix.platform }} == 'ANDROID' ]]; then
|
||||
wget https://dl.google.com/android/repository/android-ndk-r23b-linux.zip
|
||||
unzip android-ndk-r23b-linux.zip
|
||||
echo "BOX64_COMPILER=$PWD/android-ndk-r23b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android31-clang" >> $GITHUB_ENV
|
||||
echo "BOX64_PLATFORM_MARCRO=-DANDROID=1 -DARM_DYNAREC=1 -DNOLOADADDR=1" >> $GITHUB_ENV
|
||||
else
|
||||
sudo apt-get -y install git gcc-aarch64-linux-gnu
|
||||
echo "BOX64_PLATFORM_MARCRO=-D${{ matrix.platform }}=1" >> $GITHUB_ENV
|
||||
echo "BOX64_COMPILER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
|
||||
fi
|
||||
else
|
||||
if [[ ${{ matrix.platform }} == 'X64' ]]; then
|
||||
echo "BOX64_PLATFORM_MARCRO=-DLD80BITS=1 -DNOALIGN=1" >> $GITHUB_ENV
|
||||
@@ -88,22 +96,32 @@ jobs:
|
||||
${{ env.BOX64_PLATFORM_MARCRO }}\
|
||||
-DCMAKE_BUILD_TYPE=${{ env.BOX64_BUILD_TYPE }}\
|
||||
-DHAVE_TRACE=${{ env.BOX64_HAVE_TRACE }}\
|
||||
-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON
|
||||
-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON\
|
||||
-DCI=${{ matrix.platform != 'ANDROID' }}
|
||||
make -j$(nproc) VERBOSE=1
|
||||
|
||||
- name: "Test Box64"
|
||||
if: ${{ matrix.platform != 'TEGRAX1' }}
|
||||
run: |
|
||||
if [[ ${{ matrix.platform }} != 'X64' ]]; then
|
||||
sudo apt-get -y install qemu-user
|
||||
if [[ ${{ matrix.platform }} != 'X64' && ${{ matrix.platform }} != 'ANDROID' ]]; then
|
||||
mkdir qemu8.1.0
|
||||
wget -O- -q https://archive.archlinux.org/packages/q/qemu-user-static/qemu-user-static-8.1.0-2-x86_64.pkg.tar.zst | tar -I zstd -C qemu8.1.0 -xf -
|
||||
sudo cp qemu8.1.0/usr/bin/* /usr/bin/
|
||||
fi
|
||||
|
||||
cd build
|
||||
if [[ ${{ matrix.platform }} == 'RISCV' ]]; then
|
||||
QEMU_LD_PREFIX=/usr/riscv64-linux-gnu/ ctest -j$(nproc) --rerun-failed --output-on-failure
|
||||
elif [[ ${{ matrix.platform }} != 'X64' ]]; then
|
||||
QEMU_LD_PREFIX=/usr/aarch64-linux-gnu/ ctest -j$(nproc) --rerun-failed --output-on-failure
|
||||
INTERPRETER=qemu-riscv64-static QEMU_LD_PREFIX=/usr/riscv64-linux-gnu/ ctest -j$(nproc) --rerun-failed --output-on-failure
|
||||
INTERPRETER=qemu-riscv64-static QEMU_LD_PREFIX=/usr/riscv64-linux-gnu/ BOX64_DYNAREC=0 ctest -j$(nproc) --rerun-failed --output-on-failure
|
||||
INTERPRETER=qemu-riscv64-static QEMU_LD_PREFIX=/usr/riscv64-linux-gnu/ QEMU_CPU=rv64,zba=true,zbb=true,zbc=true,zbs=true ctest -j$(nproc) --rerun-failed --output-on-failure
|
||||
INTERPRETER=qemu-riscv64-static QEMU_LD_PREFIX=/usr/riscv64-linux-gnu/ QEMU_CPU=rv64,xtheadba=true,xtheadba=true,xtheadbb=true,xtheadbs=true,xtheadcondmov=true,xtheadmemidx=true,xtheadmempair=true,xtheadfmemidx=true,xtheadmac=true,xtheadfmv=true ctest -j$(nproc) --rerun-failed --output-on-failure
|
||||
elif [[ ${{ matrix.platform }} != 'X64' && ${{ matrix.platform }} != 'ANDROID' ]]; then # AArch64
|
||||
INTERPRETER=qemu-aarch64-static QEMU_LD_PREFIX=/usr/aarch64-linux-gnu/ BOX64_DYNAREC=0 ctest -j$(nproc) --rerun-failed --output-on-failure
|
||||
INTERPRETER=qemu-aarch64-static QEMU_LD_PREFIX=/usr/aarch64-linux-gnu/ ctest -j$(nproc) --rerun-failed --output-on-failure
|
||||
elif [[ ${{ matrix.platform }} == 'ANDROID' ]]; then
|
||||
true
|
||||
else
|
||||
BOX64_DYNAREC=0 ctest -j$(nproc) --rerun-failed --output-on-failure
|
||||
ctest -j$(nproc) --rerun-failed --output-on-failure
|
||||
fi
|
||||
|
||||
|
||||
Executable → Regular
File mode changed.
Executable → Regular
+233
-42
@@ -7,6 +7,8 @@ SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
|
||||
|
||||
option(RPI3ARM64 "Set to ON if targeting an RaspberryPI3 device with multiarch arm64 and armhf" ${RPI3ARM64})
|
||||
option(RPI4ARM64 "Set to ON if targeting an RaspberryPI4 device with multiarch arm64 and armhf" ${RPI4ARM64})
|
||||
option(RPI5ARM64 "Set to ON if targeting an RaspberryPi5 device with multiarch arm64 and armhf" ${RPI5ARM64})
|
||||
option(RPI5ARM64PS16K "Set to ON if targeting an RaspberryPi5 device with multiarch arm64, armhf, and 16k pages" ${RPI5ARM64PS16K})
|
||||
option(RK3326 "Set to ON if targeting an Rockchip RK3326 based device" ${RK3326})
|
||||
option(RK3399 "Set to ON if targeting an Rockchip RK3399 based device" ${RK3399})
|
||||
option(RK3588 "Set to ON if targeting an Rockchip RK3588(S) based device" ${RK3588})
|
||||
@@ -14,18 +16,31 @@ option(ODROIDN2 "Set to ON if targeting an Odroid-N2 device" ${ODROIDN2})
|
||||
option(TEGRAX1 "Set to ON if targeting an Tegra X1 based device" ${TEGRAX1})
|
||||
option(PHYTIUM "Set to ON if targeting an Phytium (D2000 or FT2000/4) based device" ${PHYTIUM})
|
||||
option(SD845 "Set to ON if targeting a Snapragon 845 based device" ${SD845})
|
||||
option(SD888 "Set to ON if targeting a Snapragon 888 based device" ${SD888})
|
||||
option(SD8G2 "Set to ON if targeting a Snapragon 8 Gen 2 based device" ${SD8G2})
|
||||
option(ADLINK "Set to ON if targeting an ADLink AmpereAltra based device" ${ADLINK})
|
||||
option(M1 "Set to ON if targeting a AppleM1 running on Asahi computer" ${M1})
|
||||
option(LARCH64 "Set to ON if targeting an Loongarch64 based device" ${LARCH64})
|
||||
option(RV64 "Set to ON if targeting an RISC-V RV64GC based device" ${RV64})
|
||||
option(PPC64LE "Set to ON if targeting an PowerPC 64 LE based device" ${PPC64LE})
|
||||
option(LX2160A "Set to ON if targeting an LX2160A based device" ${LX2160A})
|
||||
option(ARM64 "Set to ON if targeting a generic ARM64 based device" ${ARM64})
|
||||
option(ANDROID "Set to ON if targeting an Android device" ${ANDROID})
|
||||
option(TERMUX "Set to ON if targeting an Android device with Termux" ${TERMUX})
|
||||
option(USE_CCACHE "Set to ON to use ccache if present in the system" ${USE_CCACHE})
|
||||
option(HAVE_TRACE "Set to ON to have Trace ability (needs ZydisInfo library)" ${HAVE_TRACE})
|
||||
option(SAVE_MEM "Set to ON to build dynarec with some slower memory saving optimisations" ${SAVE_MEM})
|
||||
option(NOLOADADDR "Set to ON to avoid fixing the load address of Box64" OFF)
|
||||
option(NOGIT "Set to ON if not building from a git clone repo (like when building from a zip download from github)" ${NOGIT})
|
||||
option(BAD_SIGNAL "Set to ON to activate the workaround for incoherent si_info on SIGSEGV" ${BAD_SIGNAL})
|
||||
option(SW64 "Set ON if targeting an SW64 based device" ${SW64})
|
||||
option(CI "Set to ON if running in CI" ${CI})
|
||||
option(WITH_MOLD "Set to ON to use with mold" ${WITH_MOLD})
|
||||
|
||||
if(TERMUX)
|
||||
set(TERMUX_PATH "/data/data/com.termux/files")
|
||||
set(ANDROID ON CACHE BOOL "")
|
||||
endif()
|
||||
if(LARCH64)
|
||||
set(LD80BITS OFF CACHE BOOL "")
|
||||
set(NOALIGN OFF CACHE BOOL "")
|
||||
@@ -46,19 +61,25 @@ if(PPC64LE)
|
||||
set(RV64_DYNAREC OFF CACHE BOOL "")
|
||||
set(PAGE16K OFF CACHE BOOL "")
|
||||
endif()
|
||||
if(RK3399 OR RK3588 OR ODROIDN2 OR RPI3ARM64 OR RPI4ARM64 OR RK3326 OR TEGRAX1 OR PHYTIUM OR SD845 OR LX2160A OR M1)
|
||||
if(RPI5ARM64PS16K)
|
||||
set(RPI5ARM64 ON CACHE BOOL "")
|
||||
endif()
|
||||
if(RK3399 OR RK3588 OR ODROIDN2 OR RPI3ARM64 OR RPI4ARM64 OR RPI5ARM64 OR RK3326 OR TEGRAX1 OR PHYTIUM OR SD845 OR SD888 OR SD8G2 OR LX2160A OR M1 OR ARM64 OR ADLINK)
|
||||
set(LD80BITS OFF CACHE BOOL "")
|
||||
set(NOALIGN OFF CACHE BOOL "")
|
||||
set(ARM_DYNAREC ON CACHE BOOL "")
|
||||
set(RV64_DYNAREC OFF CACHE BOOL "")
|
||||
endif()
|
||||
if(RK3399 OR RK3588 OR ODROIDN2 OR RPI3ARM64 OR RPI4ARM64 OR RK3326 OR TEGRAX1 OR PHYTIUM OR SD845 OR LX2160A)
|
||||
if(RK3399 OR RK3588 OR ODROIDN2 OR RPI3ARM64 OR RPI4ARM64 OR RK3326 OR TEGRAX1 OR PHYTIUM OR SD845 OR SD888 OR SD8G2 OR LX2160A OR ADLINK)
|
||||
set(PAGE16K OFF CACHE BOOL "")
|
||||
endif()
|
||||
if(RK3399 OR ODROIDN2 OR RPI3ARM64 OR RPI4ARM64 OR RPI5ARM64)
|
||||
set(SAVE_MEM ON CACHE BOOL "")
|
||||
endif()
|
||||
if(RK3588)
|
||||
set(BAD_SIGNAL ON CACHE BOOL "")
|
||||
endif()
|
||||
if(M1 OR LARCH64)
|
||||
if(M1 OR LARCH64 OR RPI5ARM64PS16K)
|
||||
set(PAGE16K ON CACHE BOOL "")
|
||||
endif()
|
||||
if(SW64)
|
||||
@@ -66,6 +87,10 @@ if(SW64)
|
||||
set(NOALIGN OFF CACHE BOOL "")
|
||||
set(PAGE8K ON CACHE BOOL "")
|
||||
endif()
|
||||
if(ANDROID)
|
||||
set(NOLOADADDR ON CACHE BOOL "")
|
||||
set(BAD_SIGNAL ON CACHE BOOL "")
|
||||
endif()
|
||||
|
||||
option(LD80BITS "Set to ON if host device have 80bits long double (i.e. i386)" ${LD80BITS})
|
||||
option(NOALIGN "Set to ON if host device doesn't need re-align (i.e. i386)" ${NOALIGN})
|
||||
@@ -115,6 +140,11 @@ elseif(RPI4ARM64)
|
||||
add_definitions(-DRPI4ARM64)
|
||||
add_definitions(-pipe -march=armv8-a+crc -mtune=cortex-a72)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc -mtune=cortex-a72")
|
||||
elseif(RPI5ARM64)
|
||||
add_definitions(-DRPI)
|
||||
add_definitions(-DRPI5ARM64)
|
||||
add_definitions(-pipe -march=armv8.2-a+crc+crypto+fp16+rcpc+dotprod -mtune=cortex-a76)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.2-a+crc+crypto+fp16+rcpc+dotprod -mtune=cortex-a76")
|
||||
elseif(RK3326)
|
||||
add_definitions(-DRK3326)
|
||||
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a35+crypto)
|
||||
@@ -137,13 +167,25 @@ elseif(TEGRAX1)
|
||||
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a57+crypto)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a57+crypto")
|
||||
elseif(PHYTIUM)
|
||||
add_definitions(-DPHYSIUM)
|
||||
add_definitions(-DPHYTIUM)
|
||||
add_definitions(-pipe -march=armv8.1-a+crc+simd+crypto)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.1-a+crc+simd+crypto+aes")
|
||||
elseif(SD845)
|
||||
add_definitions(-DSD845)
|
||||
add_definitions(-pipe -march=armv8.2-a+simd+crypto -mtune=cortex-a75.cortex-a55)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.2-a+simd+crypto -mtune=cortex-a75.cortex-a55")
|
||||
elseif(SD888)
|
||||
add_definitions(-DSD888)
|
||||
add_definitions(-pipe -march=armv8.4-a+simd+crypto)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.4-a+simd+crypto")
|
||||
elseif(SD8G2)
|
||||
add_definitions(-DSD8G2)
|
||||
add_definitions(-pipe -march=armv9-a+i8mm+sm4+sha3+rcpc+crypto+nosve+nosve2)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv9-a+i8mm+sm4+sha3+rcpc+crypto+nosve+nosve2")
|
||||
elseif(ADLINK)
|
||||
add_definitions(-DADLINK)
|
||||
add_definitions(-pipe -mcpu=neoverse-n1 -fuse-ld=gold -fuse-linker-plugin)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -mcpu=neoverse-n1")
|
||||
elseif(M1)
|
||||
add_definitions(-DM1)
|
||||
add_definitions(-pipe -march=armv8.5-a+simd+crypto)
|
||||
@@ -164,14 +206,26 @@ elseif(LX2160A)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crypto+crc -mcpu=cortex-a72+crypto")
|
||||
elseif(SW64)
|
||||
add_definitions(-DSW64)
|
||||
elseif(ARM64)
|
||||
#add_definitions(-pipe -march=native)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+simd")
|
||||
elseif(ARM_DYNAREC)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto")
|
||||
if(NOT ANDROID)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto")
|
||||
endif()
|
||||
endif()
|
||||
if(ANDROID)
|
||||
add_definitions(-DANDROID)
|
||||
endif()
|
||||
if(TERMUX)
|
||||
add_definitions(-DTERMUX)
|
||||
endif()
|
||||
|
||||
if(BAD_SIGNAL)
|
||||
add_definitions(-DBAD_SIGNAL)
|
||||
endif()
|
||||
|
||||
if(SAVE_MEM)
|
||||
add_definitions(-DSAVE_MEM)
|
||||
endif()
|
||||
if(PAGE8K)
|
||||
add_definitions(-DPAGE8K)
|
||||
endif()
|
||||
@@ -259,15 +313,16 @@ set(ELFLOADER_SRC
|
||||
"${BOX64_ROOT}/src/mallochook.c"
|
||||
"${BOX64_ROOT}/src/steam.c"
|
||||
"${BOX64_ROOT}/src/dynarec/dynarec.c"
|
||||
"${BOX64_ROOT}/src/elfs/elfdwarf_private.c"
|
||||
"${BOX64_ROOT}/src/elfs/elfloader.c"
|
||||
"${BOX64_ROOT}/src/elfs/elfparser.c"
|
||||
"${BOX64_ROOT}/src/elfs/elfload_dump.c"
|
||||
"${BOX64_ROOT}/src/emu/x64compstrings.c"
|
||||
"${BOX64_ROOT}/src/emu/x64emu.c"
|
||||
"${BOX64_ROOT}/src/emu/x64int3.c"
|
||||
"${BOX64_ROOT}/src/emu/x87emu_private.c"
|
||||
"${BOX64_ROOT}/src/emu/x64primop.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run_private.c"
|
||||
"${BOX64_ROOT}/src/emu/x64shaext.c"
|
||||
"${BOX64_ROOT}/src/emu/x64syscall.c"
|
||||
"${BOX64_ROOT}/src/emu/x86syscall.c"
|
||||
"${BOX64_ROOT}/src/emu/x64tls.c"
|
||||
@@ -278,7 +333,6 @@ set(ELFLOADER_SRC
|
||||
"${BOX64_ROOT}/src/librarian/globalsymbols.c"
|
||||
"${BOX64_ROOT}/src/librarian/symbols.c"
|
||||
"${BOX64_ROOT}/src/libtools/auxval.c"
|
||||
"${BOX64_ROOT}/src/libtools/obstack.c"
|
||||
"${BOX64_ROOT}/src/libtools/myalign.c"
|
||||
"${BOX64_ROOT}/src/libtools/sdl1rwops.c"
|
||||
"${BOX64_ROOT}/src/libtools/sdl2rwops.c"
|
||||
@@ -296,6 +350,12 @@ set(ELFLOADER_SRC
|
||||
"${BOX64_ROOT}/src/tools/wine_tools.c"
|
||||
"${BOX64_ROOT}/src/wrapped/generated/wrapper.c"
|
||||
)
|
||||
if(NOT ANDROID)
|
||||
list(APPEND ELFLOADER_SRC
|
||||
"${BOX64_ROOT}/src/libtools/obstack.c"
|
||||
"${BOX64_ROOT}/src/elfs/elfdwarf_private.c"
|
||||
)
|
||||
endif()
|
||||
|
||||
set(INTERPRETER
|
||||
"${BOX64_ROOT}/src/emu/x64run.c"
|
||||
@@ -303,12 +363,15 @@ set(INTERPRETER
|
||||
"${BOX64_ROOT}/src/emu/x64run64.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run66.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run660f.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run66f20f.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run66f30f.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run6664.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run66d9.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run66dd.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run66f0.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run67.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run67_32.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run6764_32.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run670f.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run6766.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run67660f.c"
|
||||
@@ -332,7 +395,9 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedatkbridge.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedatomic.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedatspi.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedayatanaappindicator3.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedbz2.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedcap.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedcairo.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedcairogobject.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedcrashhandler.c"
|
||||
@@ -341,6 +406,8 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedcurl.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappeddbus.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappeddbusglib1.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappeddbusmenuglib.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedevent21.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedexpat.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedfaudio.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedflac.c"
|
||||
@@ -359,21 +426,34 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgmp.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgnutls.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgobject2.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgomp.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgssapi.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgssapikrb5.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgstallocators.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgstapp.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgstaudio.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgstbase.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgstcheck.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgstcontroller.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgstfft.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgstgl.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgstnet.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgstpbutils.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgstreamer.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgstriff.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgstrtp.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgstrtsp.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgstsdp.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgsttag.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgstvideo.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgthread2.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgtk3.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgtkx112.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedkrb5.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlcms2.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedldlinux.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibasound.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibbsd.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibc.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibcmusl.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibcrypt.c"
|
||||
@@ -383,6 +463,7 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibegl.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibform.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibformw.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibformw6.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibfuse.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibgl.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibglu.c"
|
||||
@@ -465,6 +546,7 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappednss3.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappednssutil3.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedopenal.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedopencl.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedpango.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedpangocairo.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedpangoft2.c"
|
||||
@@ -513,11 +595,25 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedvulkan.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedxshmfence.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedd3dadapter9.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedicuuc66.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedicui18n66.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedicuuc67.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedicui18n67.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedicuuc72.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedicui18n72.c"
|
||||
)
|
||||
if(ANDROID)
|
||||
list(APPEND WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedandroidshmem.c"
|
||||
)
|
||||
endif()
|
||||
if(TERMUX)
|
||||
list(APPEND WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappediconv.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedtermuxexec.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedandroidsupport.c"
|
||||
)
|
||||
endif()
|
||||
|
||||
# If BOX64_ROOT contains a ".c", the build breaks...
|
||||
string(REPLACE ".c" "_private.h" MODROOT ${BOX64_ROOT})
|
||||
@@ -532,16 +628,18 @@ endforeach()
|
||||
|
||||
set(WRAPPER "${BOX64_ROOT}/src/wrapped/generated/wrapper.c" "${BOX64_ROOT}/src/wrapped/generated/wrapper.h")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${BOX64_ROOT}/src/wrapped/generated/functions_list.txt"
|
||||
COMMAND "${PYTHON_EXECUTABLE}" "${BOX64_ROOT}/rebuild_wrappers.py"
|
||||
"${BOX64_ROOT}"
|
||||
"PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "--"
|
||||
${WRAPPEDS_HEAD}
|
||||
MAIN_DEPENDENCY "${BOX64_ROOT}/rebuild_wrappers.py"
|
||||
DEPENDS ${WRAPPEDS} ${WRAPPEDS_HEAD}
|
||||
BYPRODUCTS ${WRAPPER}
|
||||
)
|
||||
if(NOT CI)
|
||||
add_custom_command(
|
||||
OUTPUT "${BOX64_ROOT}/src/wrapped/generated/functions_list.txt"
|
||||
COMMAND "${PYTHON_EXECUTABLE}" "${BOX64_ROOT}/rebuild_wrappers.py"
|
||||
"${BOX64_ROOT}"
|
||||
"PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "ANDROID" "TERMUX" "--"
|
||||
${WRAPPEDS_HEAD}
|
||||
MAIN_DEPENDENCY "${BOX64_ROOT}/rebuild_wrappers.py"
|
||||
DEPENDS ${WRAPPEDS} ${WRAPPEDS_HEAD}
|
||||
BYPRODUCTS ${WRAPPER}
|
||||
)
|
||||
endif ()
|
||||
|
||||
#add_custom_command(
|
||||
# OUTPUT "${BOX64_ROOT}/src/dynarec/last_run.txt"
|
||||
@@ -589,9 +687,11 @@ if(ARM_DYNAREC)
|
||||
#"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_65.c"
|
||||
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_66.c"
|
||||
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_67.c"
|
||||
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_67_32.c"
|
||||
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_6764_32.c"
|
||||
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_d8.c"
|
||||
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_d9.c"
|
||||
#"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_da.c"
|
||||
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_da.c"
|
||||
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_db.c"
|
||||
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_dc.c"
|
||||
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_dd.c"
|
||||
@@ -599,6 +699,8 @@ if(ARM_DYNAREC)
|
||||
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_df.c"
|
||||
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_f0.c"
|
||||
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_660f.c"
|
||||
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_66f20f.c"
|
||||
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_66f30f.c"
|
||||
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_6664.c"
|
||||
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_66f0.c"
|
||||
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_f20f.c"
|
||||
@@ -637,9 +739,10 @@ if(RV64_DYNAREC)
|
||||
#"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_65.c"
|
||||
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_66.c"
|
||||
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_67.c"
|
||||
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_67_32.c"
|
||||
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_d8.c"
|
||||
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_d9.c"
|
||||
#"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_da.c"
|
||||
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_da.c"
|
||||
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_db.c"
|
||||
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_dc.c"
|
||||
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_dd.c"
|
||||
@@ -647,6 +750,8 @@ if(RV64_DYNAREC)
|
||||
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_df.c"
|
||||
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_f0.c"
|
||||
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_660f.c"
|
||||
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_66f20f.c"
|
||||
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_66f30f.c"
|
||||
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_6664.c"
|
||||
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_66f0.c"
|
||||
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_f20f.c"
|
||||
@@ -713,7 +818,15 @@ add_dependencies(${BOX64} WRAPPERS)
|
||||
if(STATICBUILD)
|
||||
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-static -Wl,--no-as-needed -Wl,--whole-archive -Wl,--allow-multiple-definition -lm -ldl -lrt -lpthread -lresolv -lc -Wl,-defsym,_DYNAMIC=0 -pthread")
|
||||
else()
|
||||
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-Wl,--no-as-needed -lc -lm -ldl -lrt -lpthread -lresolv -Wl,--as-needed -pthread")
|
||||
if(ANDROID)
|
||||
if(TERMUX)
|
||||
target_link_libraries(${BOX64} c m dl android-sysv-semaphore)
|
||||
else()
|
||||
target_link_libraries(${BOX64} c m dl)
|
||||
endif()
|
||||
else()
|
||||
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-Wl,--no-as-needed -lc -lm -ldl -lrt -lpthread -lresolv -Wl,--as-needed -pthread")
|
||||
endif()
|
||||
endif()
|
||||
if(DYNAREC)
|
||||
target_link_libraries(${BOX64} dynarec)
|
||||
@@ -722,7 +835,7 @@ target_link_libraries(${BOX64} interpreter)
|
||||
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.13")
|
||||
if(NOT NOLOADADDR)
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "Clang" OR WITH_MOLD)
|
||||
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-Wl,--image-base=${BOX64_ELF_ADDRESS}")
|
||||
else()
|
||||
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-Wl,-Ttext-segment,${BOX64_ELF_ADDRESS}")
|
||||
@@ -731,7 +844,7 @@ if(${CMAKE_VERSION} VERSION_LESS "3.13")
|
||||
else()
|
||||
# If symbols are missing, try this: target_link_options(${BOX64} PUBLIC -rdynamic)
|
||||
if(NOT NOLOADADDR)
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "Clang" OR WITH_MOLD)
|
||||
target_link_options(${BOX64} PUBLIC LINKER:--image-base=${BOX64_ELF_ADDRESS})
|
||||
else()
|
||||
target_link_options(${BOX64} PUBLIC LINKER:-Ttext-segment,${BOX64_ELF_ADDRESS})
|
||||
@@ -739,28 +852,52 @@ else()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "i686" _x86)
|
||||
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "x86_64" _x86_64)
|
||||
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "aarch64" _aarch64)
|
||||
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "riscv64" _riscv64)
|
||||
string(COMPARE EQUAL "${CMAKE_SYSTEM_PROCESSOR}" "i686" _x86)
|
||||
string(COMPARE EQUAL "${CMAKE_SYSTEM_PROCESSOR}" "x86_64" _x86_64)
|
||||
string(COMPARE EQUAL "${CMAKE_SYSTEM_PROCESSOR}" "aarch64" _aarch64)
|
||||
string(COMPARE EQUAL "${CMAKE_SYSTEM_PROCESSOR}" "riscv64" _riscv64)
|
||||
|
||||
if(_x86_64 OR _aarch64)
|
||||
add_definitions(-DCONFIG_64BIT)
|
||||
endif()
|
||||
|
||||
if(NOT _x86 AND NOT _x86_64)
|
||||
install(TARGETS ${BOX64}
|
||||
if(NOT TERMUX)
|
||||
install(TARGETS ${BOX64}
|
||||
RUNTIME DESTINATION bin)
|
||||
else()
|
||||
install(TARGETS ${BOX64}
|
||||
RUNTIME DESTINATION ${TERMUX_PATH}/usr/bin)
|
||||
endif()
|
||||
if(NOT NO_CONF_INSTALL)
|
||||
configure_file(system/box64.conf.cmake system/box64.conf)
|
||||
install(FILES ${CMAKE_BINARY_DIR}/system/box64.conf DESTINATION /etc/binfmt.d/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/system/box64.box64rc DESTINATION /etc/)
|
||||
if(NOT TERMUX)
|
||||
install(FILES ${CMAKE_BINARY_DIR}/system/box64.conf DESTINATION /etc/binfmt.d/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/system/box64.box64rc DESTINATION /etc/)
|
||||
else()
|
||||
#install(FILES ${CMAKE_BINARY_DIR}/system/box64.conf DESTINATION ${TERMUX_PATH}/usr/etc/binfmt.d/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/system/box64.box64rc DESTINATION ${TERMUX_PATH}/usr/etc/)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
if(NOT NO_LIB_INSTALL)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.5 DESTINATION /usr/lib/x86_64-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.6 DESTINATION /usr/lib/x86_64-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libgcc_s.so.1 DESTINATION /usr/lib/x86_64-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libpng12.so.0 DESTINATION /usr/lib/x86_64-linux-gnu/)
|
||||
if(NOT TERMUX)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.5 DESTINATION /usr/lib/x86_64-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.6 DESTINATION /usr/lib/x86_64-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libgcc_s.so.1 DESTINATION /usr/lib/x86_64-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libpng12.so.0 DESTINATION /usr/lib/x86_64-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libcrypto.so.1.1 DESTINATION /usr/lib/x86_64-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libssl.so.1.1 DESTINATION /usr/lib/x86_64-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libunwind.so.8 DESTINATION /usr/lib/x86_64-linux-gnu/)
|
||||
else()
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.5 DESTINATION ${TERMUX_PATH}/usr/lib/x86_64-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.6 DESTINATION ${TERMUX_PATH}/usr/lib/x86_64-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libgcc_s.so.1 DESTINATION ${TERMUX_PATH}/usr/lib/x86_64-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libpng12.so.0 DESTINATION ${TERMUX_PATH}/usr/lib/x86_64-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libcrypto.so.1.1 DESTINATION ${TERMUX_PATH}/usr/lib/x86_64-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libssl.so.1.1 DESTINATION ${TERMUX_PATH}/usr/lib/x86_64-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libunwind.so.8 DESTINATION ${TERMUX_PATH}/usr/lib/x86_64-linux-gnu/)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -778,7 +915,11 @@ set(CPACK_GENERATOR "DEB")
|
||||
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "ptitSeb")
|
||||
set(CPACK_PACKAGE_CONTACT "[email protected]")
|
||||
set(CPACK_PACKAGE_DESCRIPTION "Box64 - Linux Userspace x86_64 Emulator with a twist")
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6")
|
||||
if(NOT TERMUX)
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6")
|
||||
else()
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libandroid-sysv-semaphore")
|
||||
endif()
|
||||
set(CPACK_PACKAGE_HOMEPAGE_URL, "https://box86.org")
|
||||
file(STRINGS "${BOX64_ROOT}/src/box64version.h" TEMP_STRING REGEX "BOX64_MAJOR\\s*")
|
||||
string(REGEX REPLACE "BOX64_MAJOR" "" TEMP_STRING ${TEMP_STRING})
|
||||
@@ -792,9 +933,15 @@ string(REGEX MATCH "[0-9]" BOX64_REVISION ${TEMP_STRING})
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR ${BOX64_MAJOR})
|
||||
set(CPACK_PACKAGE_VERSION_MINOR ${BOX64_MINOR})
|
||||
set(CPACK_PACKAGE_VERSION_PATCH ${BOX64_REVISION})
|
||||
if(NOT TERMUX)
|
||||
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/postinst")
|
||||
endif()
|
||||
if(_aarch64)
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "arm64")
|
||||
if(TERMUX)
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "aarch64")
|
||||
else()
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "arm64")
|
||||
endif()
|
||||
elseif(__riscv64)
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "riscv64")
|
||||
elseif(_x86_64)
|
||||
@@ -803,7 +950,14 @@ else()
|
||||
#probably wrong...
|
||||
execute_process(COMMAND "dpkg --print-architecture" OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE)
|
||||
endif()
|
||||
set(CPACK_DEBIAN_FILE_NAME "${BOX64}-${BOX64_MAJOR}.${BOX64_MINOR}.${BOX64_REVISION}_Linux-${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
|
||||
if(TERMUX)
|
||||
set(CPACK_PACKAGING_INSTALL_PREFIX "${TERMUX_PATH}/usr")
|
||||
endif()
|
||||
if(NOT TERMUX)
|
||||
set(CPACK_DEBIAN_FILE_NAME "${BOX64}-${BOX64_MAJOR}.${BOX64_MINOR}.${BOX64_REVISION}_${CMAKE_SYSTEM_NAME}-${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
|
||||
else()
|
||||
set(CPACK_DEBIAN_FILE_NAME "${BOX64}-${BOX64_MAJOR}.${BOX64_MINOR}.${BOX64_REVISION}_Termux-${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
|
||||
endif()
|
||||
INCLUDE(CPack)
|
||||
|
||||
add_test(bootSyscall ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
|
||||
@@ -910,19 +1064,56 @@ add_test(irelative_reloc ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref20.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
add_test(longjumpInSignals ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
|
||||
add_test(longjumpInSignals ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test21 -D TEST_OUTPUT=tmpfile21.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref21.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
add_test(x87 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
|
||||
add_test(x87 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test22 -D TEST_OUTPUT=tmpfile22.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref22.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
set_tests_properties(x87 PROPERTIES ENVIRONMENT "BOX64_DYNAREC_FASTROUND=0")
|
||||
set_tests_properties(x87 PROPERTIES ENVIRONMENT "BOX64_DYNAREC_FASTROUND=0")
|
||||
|
||||
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
|
||||
add_test(pshufb ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test23 -D TEST_OUTPUT=tmpfile23.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref23.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
add_test(bswap ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test24 -D TEST_OUTPUT=tmpfile24.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref24.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
add_test(x87cache ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test25 -D TEST_OUTPUT=tmpfile25.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref25.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
add_test(feround ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test26 -D TEST_OUTPUT=tmpfile26.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref26.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
set_tests_properties(feround PROPERTIES ENVIRONMENT "BOX64_SYNC_ROUNDING=1")
|
||||
|
||||
add_test(sse4_2 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test27 -D TEST_OUTPUT=tmpfile27.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref27.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
add_test(shaext ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test28 -D TEST_OUTPUT=tmpfile28.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref28.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
add_test(lock ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test29 -D TEST_OUTPUT=tmpfile29.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref29.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
|
||||
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
|
||||
foreach(file ${extension_tests})
|
||||
get_filename_component(testname "${file}" NAME_WE)
|
||||
add_test(NAME "${testname}" COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Linux Userspace x86_64 Emulator with a twist
|
||||
|
||||
[View changelog](https://github.com/ptitSeb/box64/blob/main/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box64/blob/main/README_CN.md) | [Report an error](https://github.com/ptitSeb/box64/issues/new)
|
||||
[View changelog](https://github.com/ptitSeb/box64/blob/main/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box64/blob/main/README_CN.md) | [Українська](https://github.com/ptitSeb/box64/blob/main/README_UK.md) | [Report an error](https://github.com/ptitSeb/box64/issues/new)
|
||||
|
||||
     
|
||||
|
||||
@@ -37,8 +37,8 @@ Note: Box64's Dynarec uses a mechanism with Memory Protection and a SegFault sig
|
||||
|
||||
Compiling/Installation
|
||||
----
|
||||
> Compilation instructions can be found [here](docs/COMPILE.md)\
|
||||
> Instructions for installing Wine for Box64 can be found [here](docs/X64WINE.md)
|
||||
> Compilation instructions can be found [here](https://github.com/ptitSeb/box64/blob/main/docs/COMPILE.md) \
|
||||
> Instructions for installing Wine for Box64 can be found [here](https://github.com/ptitSeb/box64/blob/main/docs/X64WINE.md)
|
||||
|
||||
----
|
||||
|
||||
@@ -54,7 +54,7 @@ Notes about 32-bit platforms
|
||||
|
||||
Because Box64 works by directly translating function calls from x86_64 to host system, the host system (the one Box64 is running on) needs to have 64-bit libraries. Box64 doesn't include any 64-bit <-> 32-bit translation.
|
||||
|
||||
So understand that box64 will only runs 64-bit linux binaries. For 32-bit binaries, you need box86 (with all the multiarch or proot trickery it imply on 64-bit OS).
|
||||
So understand that box64 will only run 64-bit linux binaries. For 32-bit binaries, you need box86 (with all the multiarch or proot trickery it implies on a 64-bit OS).
|
||||
Note that many installer (mojo setup based) will fall back to "x86" when detecting ARM64 OS, and so will try to use box86 for the setup, even if an x86_64 version exist. You can hack your way around with a fake "uname" that return "x86_64" when the argument is "-m"
|
||||
|
||||
----
|
||||
@@ -62,16 +62,16 @@ Note that many installer (mojo setup based) will fall back to "x86" when detecti
|
||||
Notes about Box64 configuration
|
||||
----
|
||||
|
||||
Box64 now have configurations files. There are 2 files loaded. `/etc/box4.box64rc` and `~/.box64rc`. Both files have the same syntax, and is basicaly an ini files. Section in square brakets define the process name, and the rest is the env. var. to set. Looke at [Usage](USAGE.md) for detail on what parameters can be put. Box64 comes with a default file that should be installed for better stability. The file in in `system/box64.box64rc` and should be installed to `/etc/box64.box64rc` If, for some reasons, you don't want to install that file here, at least copy it to `~/.box64rc` or some game may not function correctly.
|
||||
Note that the priority is: `~/.bashrc` > `/etc/box64.box64rc` > command line
|
||||
So, your settings in `~/.bashrc` may override the setting from your command line...
|
||||
Box64 now have configurations files. There are 2 files loaded. `/etc/box4.box64rc` and `~/.box64rc`. Both files have the same syntax, and is basicaly an ini files. Section in square brakets define the process name, and the rest is the env. var. to set. Looke at [Usage](USAGE.md) for detail on what parameters can be put. Box64 comes with a default file that should be installed for better stability. The file in in `system/box64.box64rc` and should be installed to `/etc/box64.box64rc` If, for some reason, you don't want to install that file here, at least copy it to `~/.box64rc` or some game may not function correctly.
|
||||
Note that the priority is: `~/.box64rc` > `/etc/box64.box64rc` > command line
|
||||
So, your settings in `~/.box64rc` may override the setting from your command line...
|
||||
|
||||
----
|
||||
|
||||
Notes about Unity game emulation
|
||||
----
|
||||
|
||||
Running Unity games should just works, but you should also note that many Unity3D games require OpenGL 3+ which can be tricky to provide on ARM SBC (single-board computers). Also many newer Unity3D (like KSP) games use the BC7 compressed textures, wich is not supported on many ARM integrated GPU.
|
||||
Running Unity games should just work, but you should also note that many Unity3D games require OpenGL 3+ which can be tricky to provide on ARM SBC (single-board computers). Also many newer Unity3D (like KSP) games use the BC7 compressed textures, which is not supported on many ARM integrated GPU.
|
||||
Hint: on Pi4, use `MESA_GL_VERSION_OVERRIDE=3.2` and with Panfrost use `PAN_MESA_DEBUG=gl3` to use higher profile if the game starts then quits before showing anything.
|
||||
|
||||
----
|
||||
@@ -86,23 +86,22 @@ GTK libraries are now wrapped on box64, both gtk2 and gtk3.
|
||||
Notes about Steam
|
||||
----
|
||||
|
||||
Note that Steam is a hybrid 32-bit / 64-bit. You NEED box86 to run Steam, as the client app is a 32-bit binary. It also uses a 64-bit local server binaries, but like most stuff using libcef/chromium, it's not working correctly on box64 for now.
|
||||
So, no Steam for now on box64.
|
||||
Note that Steam is a hybrid 32-bit / 64-bit. You NEED box86 to run Steam, as the client app is a 32-bit binary. It also uses a 64-bit local server binaries, and that steamwebhelper process is now mandatory, even on the "small mode". And that process will eat lots of memory. So machine with less the 6Gb of RAM will need a swapfile to use Steam.
|
||||
|
||||
----
|
||||
|
||||
Notes about Wine
|
||||
----
|
||||
|
||||
Wine64 is supported on box64. Proton should also work. Be aware that 64-bit Wine also includes 32-bit components, to be able to run 32-bit Windows programs. The 32-bit apps will need box86 and will not run without it. On a system where both box64 and box86 are present and working, a wine 64-bit setup can run both 32-bit and 64-bit Windows programs (just use `wine` and `wine64` respectively).
|
||||
Note that the new 32bits PE in 64bits process that the Wine time in currently implementing in Wine 7.+ is not yet supported. I tested Wine 7.5 64bits and it worked, but more recent version will probably just not work yet.
|
||||
Wine64 is supported on box64. Proton too. Be aware that 64-bit Wine also includes 32-bit components, to be able to run 32-bit Windows programs. The 32-bit apps will need box86 and will not run without it. On a system where both box64 and box86 are present and working, a wine 64-bit setup can run both 32-bit and 64-bit Windows programs (just use `wine` and `wine64` respectively).
|
||||
Note that the new 32-bit PE in 64-bit processes that the Wine team is currently implementing in Wine 7.+ is now supported, but the support is quite young so there might be some residual issues.
|
||||
|
||||
----
|
||||
|
||||
Notes about Vulkan
|
||||
----
|
||||
|
||||
Box64 wraps Vulkan libraries, but note that it as only been tested with a RX550 card, so some extensions may be missing depending on your graphics card.
|
||||
Box64 wraps Vulkan libraries, but note that it as mostly been tested with an AMD RX550 card and on the Freedreno driver, so some extensions may be missing depending on your graphics card.
|
||||
|
||||
----
|
||||
|
||||
@@ -113,11 +112,11 @@ I want to thank everyone who has contributed to box64 development.
|
||||
There are many ways to contribute: code contribution, financial, hardware and advertisement!
|
||||
So, in no particular order, I want to thank:
|
||||
* For their major code contribution: rajdakin, mogery
|
||||
* For their major financial contribution: FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
|
||||
* For their major financial contribution: FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/), [CubeCoders Limited](http://cubecoders.com/)
|
||||
* For hardware contribution and LoongArch migration: [xiaoji](https://www.linuxgame.cn/), Deepin Beijing Develop Team
|
||||
* For their major code contribution on the RV64 Dynarec: ksco, xctan
|
||||
* For their hardware contribution: [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [StarFive](https://rvspace.org/)
|
||||
* For their continous advertisement of box64 project: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS](https://twisteros.com/) team, [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg), ekianjo ([Boilingsteam](https://boilingsteam.com/))
|
||||
* For their hardware contribution: [ADLINK](https://www.adlinktech.com/Products/Computer_on_Modules/COM-HPC-Server-Carrier-and-Starter-Kit/Ampere_Altra_Developer_Platform?lang=en) with [Ampere](https://amperecomputing.com/home/edge), [Radxa](https://rockpi.org/), [StarFive](https://rvspace.org/), [Pine64](https://www.pine64.org/), [AYN](https://www.ayntec.com/)
|
||||
* For their continuous advertisements for the box64 project: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS](https://twisteros.com/) team, [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg), ekianjo ([Boilingsteam](https://boilingsteam.com/))
|
||||
|
||||
And I also thank the many other people who participated even once in this project.
|
||||
|
||||
|
||||
+5
-5
@@ -6,7 +6,7 @@ Linux 上用户空间的 x86_64 应用模拟器(支持运行原生库)
|
||||
----
|
||||

|
||||
|
||||
[English](docs/README.md)
|
||||
[English](docs/README.md) | [Українська](https://github.com/ptitSeb/box64/blob/main/README_UK.md)
|
||||
|
||||
Box64 可以在非 x86_64 Linux 系统(比如 ARM64)上运行 x86_64 Linux 程序(比如游戏),注意主机系统需要是 64 位小端。
|
||||
|
||||
@@ -14,7 +14,7 @@ Box64 可以在非 x86_64 Linux 系统(比如 ARM64)上运行 x86_64 Linux
|
||||
|
||||
由于 Box64 使用一些“系统”库的原生版本,如 libc、libm、SDL 和 OpenGL 等,因此很容易与大多数应用程序集成和使用,并且在许多情况下性能会相当不错。可以在[这里](https://box86.org/index.php/2021/06/game-performances/)查看一些性能测试的样例。
|
||||
|
||||
Box64 集成了适用于 ARM64 平台的 DynaRec(动态重编译器),速度可以比纯解释模式快 5 到 10 倍。可以在[这里](https://box86.org/2021/07/inner-workings-a-high%E2%80%91level-view-of-box86-and-a-low%E2%80%91level-view-of-the-dynarec/)找到有关 DynaRec 工作原理的一些信息。
|
||||
Box64 集成了适用于 ARM64 和 RV64 平台的 DynaRec(动态重编译器),速度可以比纯解释模式快 5 到 10 倍。可以在[这里](https://box86.org/2021/07/inner-workings-a-high%E2%80%91level-view-of-box86-and-a-low%E2%80%91level-view-of-the-dynarec/)找到有关 DynaRec 工作原理的一些信息。
|
||||
|
||||
一些 x64 内部操作码使用 “Realmode X86 Emulator Library” 的部分内容,有关版权详细信息,请参见 [x64primop.c](../src/emu/x64primop.c)。
|
||||
|
||||
@@ -54,7 +54,7 @@ LOGO 由 @grayduck 制作,感谢!
|
||||
|
||||
因为 Box64 的工作原理是直接将函数调用从 x86_64 转换为主机系统,所以主机系统(运行 Box64 的系统)需要有 64 位库。Box64 不包含任何 64 位 <-> 32 位的转换。
|
||||
|
||||
所以 box64 只能运行 64 位的 Linux 二进制。对于 32 位二进制则需要使用 box86 来运行(它在 64 位操作系统上使用了 multiarch 和 proot 等技巧来实现运行)。请注意,许多(基于 mojo 的)安装程序在检测到 ARM64 操作系统时将回退到 “x86”,因此即使存在 x86_64 版本,也会尝试使用 box86。这时你可以使用一个假的 `uname`,当它的参数为 `-m` 时返回 `x86_64`。
|
||||
所以 box64 只能运行 64 位的 Linux 二进制。对于 32 位二进制则需要使用 box86 来运行(它在 64 位操作系统上使用了 multiarch 和 proot 等技巧来实现运行)。请注意,许多(基于 mojo 的)安装程序在检测到 ARM64 操作系统时将回退到 “x86”,因此即使存在 x86_64 版本,也会尝试使用 box86。这时你可以使用一个假的 `uname` ,并使它在运行参数为 `-m` 时返回 `x86_64`。
|
||||
|
||||
----
|
||||
|
||||
@@ -77,7 +77,7 @@ box64 封装了 GTK,包括 gtk2 和 gtk3。
|
||||
关于 Steam 的注意事项
|
||||
----
|
||||
|
||||
请注意,Steam 是 32/64 位的混合体,所以还需要 box86 才能运行,因为客户端应用程序是 32 位的。它还使用 64 位本地服务器,但与大多数使用 libcef/chromium 的东西一样,它目前无法在 box64 上正常工作。所以,现在 box64 上暂时不能运行 Steam。
|
||||
请注意,Steam 是 32/64 位混合的应用,所以你需要 box86 才能运行,因为客户端应用程序是 32 位的。它还使用 64 位本地服务器,它的 steamwebhelper 无法被关闭(即使是在最小模式)而且会吃掉大量的内存。对于内存小于 6 GB 的机型,你将会需要创建 swapfile 来运行 Steam。
|
||||
|
||||
----
|
||||
|
||||
@@ -105,7 +105,7 @@ Box64 封装了 Vulkan 库,但请注意,它仅在 RX550 显卡上进行过
|
||||
* 代码贡献:rajdakin, mogery
|
||||
* 财务帮助:FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
|
||||
* 硬件捐赠和 LoongArch 迁移:[xiaoji](https://www.linuxgame.cn/), Deepin Beijing Develop Team
|
||||
* 硬件捐赠:[Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [StarFive](https://rvspace.org/)
|
||||
* 硬件捐赠:[ADLink](https://www.adlinktech.com/Products/Computer_on_Modules/COM-HPC-Server-Carrier-and-Starter-Kit/Ampere_Altra_Developer_Platform?lang=en), [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [StarFive](https://rvspace.org/)
|
||||
* 为本项目持续的宣传:salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS](https://twisteros.com/) team, [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg), ekianjo ([Boilingsteam](https://boilingsteam.com/))
|
||||
|
||||
我还要感谢很多人,即使他们只参与了一次本项目。
|
||||
|
||||
+119
@@ -0,0 +1,119 @@
|
||||

|
||||
|
||||
Емулятор простіра користувача x86_64 із родзинкою
|
||||
|
||||
[Дивитись журнал змін](https://github.com/ptitSeb/box64/blob/main/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box64/blob/main/README_CN.md) | [Українська](https://github.com/ptitSeb/box64/blob/main/README_UK.md) | [Повідомити про помилку](https://github.com/ptitSeb/box64/issues/new)
|
||||
|
||||
     
|
||||
|
||||
----
|
||||
|
||||
Box64 дозволяє запускати x86_64 Linux програми (наприклад, ігри) на системах Linux відмінних від x86_64, наприклад ARM (хост-система має мати 64-розрядний порядок редагування).
|
||||
|
||||
Ви можете знайти багато відео про Box64 в YouTube каналах [MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ), [Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g) або [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA)
|
||||
|
||||
Оскільки Box64 використовує рідні версії деяких «системних» бібліотек, таких як libc, libm, SDL і OpenGL, його легко інтегрувати та використовувати з більшістю програм, а продуктивність у багатьох випадках може бути напрочуд високою. Подивіться на цей стендовий аналіз для прикладу [тут](https://box86.org/index.php/2021/06/game-performances/).
|
||||
|
||||
Box64 інтегрується з DynaRec (динамічний рекомпілятор) для платформ ARM64 і RV64 забезпечуючи підвищення швидкості в 5-10 разів, ніж використання лише інтерпретатора. Деякі високорівневі відомості про те, як працює DynaRec, можна знайти [тут](https://box86.org/2021/07/inner-workings-a-high%e2%80%91level-view-of-box86-and-a-low%e2%80%91level-view-of-the-dynarec/).
|
||||
|
||||
Деякі внутрішні коди операцій x64 використовують частини «Бібліотеки емулятора Realmode X86», дивіться [x64primop.c](src/emu/x64primop.c) для детальної інформації про авторські права.
|
||||
|
||||
<img src="docs/img/Box64Icon.png" width="96" height="96">
|
||||
|
||||
Логотип і піктограма зроблені @grayduck, дякую!
|
||||
|
||||
----
|
||||
|
||||
Використання
|
||||
----
|
||||
|
||||
Є кілька змінних середовища для керування поведінкою Box64.
|
||||
|
||||
Дивіться [тут](docs/USAGE.md) для перегляду всіх змінних середовища та того, що вони роблять.
|
||||
|
||||
Примітка: Dynarec від Box64 використовує механізм із захистом пам’яті та обробником сигналу помилки сегментів для обробки JIT коду. Простіше кажучи, якщо ви хочете використовувати GDB для налагодження запущеної програми, яка використовує JIT-код (наприклад, mono/Unity3D), ви все одно матимете багато «звичайних» помилок сегментів. Пропонується використовувати щось на зразок `handle SIGSEGV nostop` в GDB, щоб не зупинятися на кожній помилці сегмента, і, можливо, поставити точку зупину всередині `my_memprotectionhandler` в `signals.c`, якщо ви хочете перехопити помилки сегментів.
|
||||
|
||||
----
|
||||
Компіляція/Встановлення
|
||||
----
|
||||
> Інструкцію зі складання Box64 можна знайти [тут](docs/COMPILE.md).\
|
||||
> Інструкцію з встановлення Wine для Box64 можна знайти [тут](docs/X64WINE.md).
|
||||
|
||||
----
|
||||
|
||||
Історія версій/Журнал змін
|
||||
----
|
||||
|
||||
Історія версій доступна [тут](docs/CHANGELOG.md).
|
||||
|
||||
----
|
||||
|
||||
Примітки щодо 32 бітних платформ
|
||||
----
|
||||
Оскільки Box64 працює шляхом прямого перекладу викликів функцій з x86_64 на хост-систему, хост-система (та, на якій працює Box64) повинна мати 64-розрядні бібліотеки. Box64 не містить 64-біт <-> 32-біт перекладу.
|
||||
|
||||
Також розумійте що Box64 запускатиме лише 64-розрядні двійкові Linux файли. Для 32-розрядних двійкових файлів вам потрібен Box86 (з усіма хитрощами з мультиархітектурною системою або корінними правами). Зауважте, що багато інсталяторів (на основі mojo) повертаються до "x86" при виявленні ОС ARM64, і тому намагатимуться використовувати Box86 для налаштування, навіть якщо існує версія x86_64. Ви можете зламати свій шлях за допомогою фальшивого "uname", який повертає "x86_64", коли аргумент "-m"
|
||||
|
||||
----
|
||||
|
||||
Примітки щодо конфігурації Box64
|
||||
----
|
||||
|
||||
Обидва файли мають однаковий синтаксис і в основному є файлами ini. Розділ у квадратних дужках визначає назву процесу, а решта — встановлють змінну середовища. Подивіться [використання](USAGE.md), щоб дізнатися, які параметри можна завдати. Box64 поставляється з файлом за замовчуванням, який слід встановити для кращої стабільності. Файл знаходиться в `system/box64.box64rc` і має бути встановлен в `/etc/box64.box64rc`. Якщо з певних причин ви не хочете встановлювати цей файл у `/etc`, принаймні скопіюйте його в `~/.box64rc` або гра може не працювати належним чином. Зауважте, що пріоритетом є: `~/.bashrc` > `/etc/box64.box64rc` > командний рядок
|
||||
Таким чином, ваші налаштування в `~/.bashrc` можуть замінити налаштування з вашого командного рядка...
|
||||
|
||||
----
|
||||
|
||||
Примітки щодо емуляції ігор Unity
|
||||
----
|
||||
|
||||
Запуск ігор Unity має працювати, але ви також повинні зауважити, що для багатьох ігор Unity3D потрібен OpenGL 3+, який може бути складно забезпечити на ARM SBC (одноплатних комп’ютерах). Крім того, багато нових ігор Unity3D (наприклад, KSP) використовують стиснуті текстури BC7, які не підтримуються багатьма інтегрованими GPU ARM.
|
||||
Підказка: в Pi4 використовуйте `MESA_GL_VERSION_OVERRIDE=3.2`, а в Panfrost — `PAN_MESA_DEBUG=gl3`, щоб використовувати вищий профіль, якщо гра запускається, а потім завершується, перш ніж щось показує.
|
||||
|
||||
----
|
||||
|
||||
Примітки щодо програм GTK
|
||||
----
|
||||
|
||||
Бібліотеки GTK2 і GTK3 тепер використовуються в Box64.
|
||||
|
||||
----
|
||||
|
||||
Примітки щодо Steam
|
||||
----
|
||||
|
||||
Зауважте, що Steam є гібридом 32-біт / 64-біт. Вам ПОТРІБЕН box86, щоб запустити Steam, оскільки клієнта є 32-розрядною двійковою програмою. Він також використовує 64-розрядні двійкові файли локального сервера, і цей процес steamwebhelper тепер є обов’язковим навіть у «малому режимі». І цей процес з’їсть багато оперативної пам’яті, таким чином машині з 6 Гб оперативної пам’яті знадобиться файл підкачки для використання Steam.
|
||||
|
||||
----
|
||||
|
||||
Примітки щодо Wine
|
||||
----
|
||||
|
||||
Wine64 підтримується Box64, Proton теж. Майте на увазі, що 64-розрядний Wine також містить 32-розрядні компоненти щоб мати можливість запускати 32-розрядні програми Windows. Для 32-розрядних програм потрібен Box86, і вони не працюватимуть без нього. У системі, де присутні і працюють Box64, і Box86, 64-розрядне встановлення Wine може запускати як 32-розрядні, так і 64-розрядні програми Windows (просто використовуйте `wine` і `wine64` відповідно).
|
||||
Зауважте, що новий 32-бітний PE в 64-бітному процесі, який Wine зараз реалізує у Wine 7+ тепер підтримується, але підтримка є досить молодою тому можуть виникнути деякі проблеми.
|
||||
|
||||
----
|
||||
|
||||
Примітки щодо Vulkan
|
||||
----
|
||||
|
||||
Box64 використовує бібліотеки Vulkan, але зауважте що він тестувався з картою AMD Radeon RX550 і драйвером Freedreno, тому деякі розширення можуть бути відсутні залежно від вашої відеокарти.
|
||||
|
||||
----
|
||||
|
||||
Останнє слово
|
||||
----
|
||||
|
||||
Я хочу подякувати всім, хто зробив внесок у розвиток box64.
|
||||
Є багато способів зробити внесок: внесок коду, фінансовий внесок, апаратне забезпечення та реклама!
|
||||
Отже, без особливого порядку, я хочу подякувати:
|
||||
* За основний внесок у код: rajdakin, mogery
|
||||
* За великий фінансовий внесок: FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
|
||||
* За апаратне забезпечення та міграцію LoongArch: [xiaoji](https://www.linuxgame.cn/), команда розробників Deepin Beijing
|
||||
* За основний внесок у код RV64 Dynarec: ksco, xctan
|
||||
* За внесок у апаратне забезпечення: [ADLink](https://www.adlinktech.com/Products/Computer_on_Modules/COM-HPC-Server-Carrier-and-Starter-Kit/Ampere_Altra_Developer_Platform?lang=en), [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [StarFive](https://rvspace.org/)
|
||||
* За безперервну рекламу Box64: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/Команда [TwisterOS](https://twisteros.com/), [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg), ekianjo ([Boilingsteam](https://boilingsteam.com/))
|
||||
|
||||
І я також дякую багатьом іншим людям, які хоч раз брали участь у цьому проекті.
|
||||
|
||||
(Якщо ви використовуєте Box64 у своєму проекті, будь ласка, не забудьте згадати про це!)
|
||||
Vendored
+57
@@ -1,3 +1,60 @@
|
||||
box64 (0.2.6) unstable; urgency=low
|
||||
|
||||
* X64Libs: Updated libstdc++ & libgcc_s
|
||||
* X64Libs: Use x86_64 vrsion of libunwind (it's needed by wine)
|
||||
* Dynarec: More opcodes on ARM64 & RV64
|
||||
* Dynarec: Fixed some flags propagation issues inside blocks
|
||||
* Dynarec: Improved Strong Memory Model emulation, introducing a 3rd level
|
||||
* Dynarec: ARM64: reworked shift and bit opcodes flags handling
|
||||
* Dynarec: RV64: Many fixes, making Wow64 apps running
|
||||
* Dynarec: ARM64: Added support for SSE4.2 (with CRC32 if supported by CPU)
|
||||
* Dynarec: ARM64: Added support for SHA (with hardware support if CPU allows it)
|
||||
* Dynarec: ARM64: The CALLRET optimisation has been improved and is now default
|
||||
* CPU: Remoworked how INT, priviliged opcodes and teh Trace flags works
|
||||
* CPU: Added full support for SSE4.2
|
||||
* CPU: Added full support for SHA extension
|
||||
* ElfLoader: rework how elf memory is handled
|
||||
* Emulation: Added some more syscalls
|
||||
* Emulation: Better handling of Signal (also handling SIGMAX correctly)
|
||||
* Emulation: Better support for POKEUSER/PEEKUSER (helps Windows Unity games)
|
||||
* Wrapping: More libs and some fixes in function wrapping (gtk3, vulkan...)
|
||||
* Wrapping: Removed faked libunwind wrapping
|
||||
* Hardware: Added more profile, with support ADLink Ampere Altra, Qualcomm 8Gen3, and Pi5 machines
|
||||
* OS: Added profile to build for Android and Termux.
|
||||
* OS: New option to use mold for a high speed link
|
||||
* => More hadware support, more functions wrapped for an improve compatibity
|
||||
* => More CPU extension, with ARM64 hardware support when possible, and improved CALLRET optimisation for an improved speed of emulation
|
||||
* => Some work also to reduce the memory footprint
|
||||
|
||||
-- Sebastien Chevalier <[email protected]> Thu, 15 Dec 2023 17:30:33 -0100
|
||||
|
||||
box64 (0.2.4) unstable; urgency=low
|
||||
|
||||
* Added Dynarec for RISC-V
|
||||
* Added partial 32 bits support (WoW64 works)
|
||||
* Changed cpuid to display box64
|
||||
* Fixed steam, again
|
||||
* Improved hacked version for overridden malloc/free functions
|
||||
* More wrapped libs
|
||||
* More wrapped functions and syscalls
|
||||
* Reduced memory footprint
|
||||
* Added support for the BIND_NOW flags in ELF files
|
||||
* Added RTLD_NOLOAD support
|
||||
* Fixed some typos and general cleanup, again
|
||||
* Added a cosimulation mode (to compare the behaviour of the dynarec with the interpreter)
|
||||
* Added FASTNAN/FASTROUND handling for more opcodes
|
||||
* Better float/double/long double handling
|
||||
* Better dlopen/dlclose handling
|
||||
* More games in the rc file
|
||||
* Added BOX64_DYNAREC_MISSING to show only missing opcode, independantly of the log level
|
||||
* Added BOX64_RESERVE_HIGH to reserve addresses above 47bits
|
||||
* Improved multitreading support
|
||||
* Ukrainian translation of the README
|
||||
* => Dynarec now support RISC-V, large speedup on RISC-V 64, were games are now playable (like Stardew Valley on a Vision Five 2)
|
||||
* => Improved compatibility with more fixes in elf handling, more wrapped libs and functiond, more fixed opcodes and refined profile
|
||||
|
||||
-- Sebastien Chevalier <[email protected]> Thu, 10 Mar 2023 10:20:33 -0500
|
||||
|
||||
box64 (0.2.2) unstable; urgency=low
|
||||
|
||||
* Added a hacked version for overridden malloc/free functions, enabling libcef (and derivative) to work.
|
||||
|
||||
@@ -1,3 +1,56 @@
|
||||
v0.2.6
|
||||
======
|
||||
* X64Libs: Updated libstdc++ & libgcc_s
|
||||
* X64Libs: Use x86_64 vrsion of libunwind (it's needed by wine)
|
||||
* Dynarec: More opcodes on ARM64 & RV64
|
||||
* Dynarec: Fixed some flags propagation issues inside blocks
|
||||
* Dynarec: Improved Strong Memory Model emulation, introducing a 3rd level
|
||||
* Dynarec: ARM64: reworked shift and bit opcodes flags handling
|
||||
* Dynarec: RV64: Many fixes, making Wow64 apps running
|
||||
* Dynarec: ARM64: Added support for SSE4.2 (with CRC32 if supported by CPU)
|
||||
* Dynarec: ARM64: Added support for SHA (with hardware support if CPU allows it)
|
||||
* Dynarec: ARM64: The CALLRET optimisation has been improved and is now default
|
||||
* CPU: Remoworked how INT, priviliged opcodes and teh Trace flags works
|
||||
* CPU: Added full support for SSE4.2
|
||||
* CPU: Added full support for SHA extension
|
||||
* ElfLoader: rework how elf memory is handled
|
||||
* Emulation: Added some more syscalls
|
||||
* Emulation: Better handling of Signal (also handling SIGMAX correctly)
|
||||
* Emulation: Better support for POKEUSER/PEEKUSER (helps Windows Unity games)
|
||||
* Wrapping: More libs and some fixes in function wrapping (gtk3, vulkan...)
|
||||
* Wrapping: Removed faked libunwind wrapping
|
||||
* Hardware: Added more profile, with support ADLink Ampere Altra, Qualcomm 8Gen3, and Pi5 machines
|
||||
* OS: Added profile to build for Android and Termux.
|
||||
* OS: New option to use mold for a high speed link
|
||||
=> More hadware support, more functions wrapped for an improve compatibity
|
||||
=> More CPU extension, with ARM64 hardware support when possible, and improved CALLRET optimisation for an improved speed of emulation
|
||||
=> Some work also to reduce the memory footprint
|
||||
|
||||
v0.2.4
|
||||
======
|
||||
* Added Dynarec for RISC-V
|
||||
* Added partial 32 bits support (WoW64 works)
|
||||
* Changed cpuid to display box64
|
||||
* Fixed steam, again
|
||||
* Improved hacked version for overridden malloc/free functions
|
||||
* More wrapped libs
|
||||
* More wrapped functions and syscalls
|
||||
* Reduced memory footprint
|
||||
* Added support for the BIND_NOW flags in ELF files
|
||||
* Added RTLD_NOLOAD support
|
||||
* Fixed some typos and general cleanup, again
|
||||
* Added a cosimulation mode (to compare the behaviour of the dynarec with the interpreter)
|
||||
* Added FASTNAN/FASTROUND handling for more opcodes
|
||||
* Better float/double/long double handling
|
||||
* Better dlopen/dlclose handling
|
||||
* More games in the rc file
|
||||
* Added BOX64_DYNAREC_MISSING to show only missing opcode, independantly of the log level
|
||||
* Added BOX64_RESERVE_HIGH to reserve addresses above 47bits
|
||||
* Improved multitreading support
|
||||
* Ukrainian translation of the README
|
||||
=> Dynarec now support RISC-V, large speedup on RISC-V 64, were games are now playable (like Stardew Valley on a Vision Five 2)
|
||||
=> Improved compatibility with more fixes in elf handling, more wrapped libs and functiond, more fixed opcodes and refined profile
|
||||
|
||||
v0.2.2
|
||||
======
|
||||
* Added a hacked version for overridden malloc/free functions, enabling libcef (and derivative) to work.
|
||||
|
||||
Executable → Regular
+55
-7
@@ -7,7 +7,7 @@ You can use [@ryanfortner](https://github.com/ryanfortner)'s apt repository to i
|
||||
```
|
||||
sudo wget https://ryanfortner.github.io/box64-debs/box64.list -O /etc/apt/sources.list.d/box64.list
|
||||
wget -qO- https://ryanfortner.github.io/box64-debs/KEY.gpg | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/box64-debs-archive-keyring.gpg
|
||||
sudo apt update && sudo apt install box64-generic-arm -y
|
||||
sudo apt update && sudo apt install box64-arm64 -y
|
||||
```
|
||||
|
||||
Alternatively, you can generate your own package using the [instructions below](https://github.com/ptitSeb/box64/blob/main/docs/COMPILE.md#debian-packaging).
|
||||
@@ -27,9 +27,9 @@ If it's the first install, you also need:
|
||||
sudo systemctl restart systemd-binfmt
|
||||
```
|
||||
- You can use `make -j1`, `make -j2` to prevent running out of memory
|
||||
- You can also add `-DBAD_SIGNAL=ON` to the cmake command if you are on Linux Kernel mixed with Android, like on RK3588 or maybe Termux
|
||||
- You can also add `-DBAD_SIGNAL=ON` to the cmake command if you are on Linux Kernel mixed with Android, like on RK3588.
|
||||
|
||||
#### For instance, if you want to build box64 for Generic ARM64 Linux platforms, it would look like this:
|
||||
#### For Instance, if you want to build box64 for Generic ARM64 Linux platforms, it would look like this:
|
||||
```
|
||||
git clone https://github.com/ptitSeb/box64
|
||||
cd box64
|
||||
@@ -68,7 +68,6 @@ Still, this can be faster if your build is attended.
|
||||
|
||||
```
|
||||
-D RPI3ARM64=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
make
|
||||
```
|
||||
|
||||
#### for Raspberry Pi 4
|
||||
@@ -79,6 +78,13 @@ Warning, you need a 64bit OS:
|
||||
-D RPI4ARM64=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
```
|
||||
|
||||
#### for Raspberry Pi 5
|
||||
|
||||
If your Raspberry Pi OS use 16K pages use `RPI5ARM64PS16K` instead of `RPI5ARM64`:
|
||||
```
|
||||
-D RPI5ARM64=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
```
|
||||
|
||||
#### for TEGRA X1
|
||||
|
||||
Using a 64bit OS:
|
||||
@@ -96,7 +102,7 @@ Using a 64bit OS:
|
||||
-D ODROIDN2=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
```
|
||||
|
||||
#### for Snapdragon 845
|
||||
#### for Snapdragon
|
||||
|
||||
Using a 64bit OS:
|
||||
|
||||
@@ -104,6 +110,14 @@ Using a 64bit OS:
|
||||
-D SD845=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
-D SD888=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
```
|
||||
|
||||
Depending how recent your Snapdragon is
|
||||
|
||||
#### for Phytium
|
||||
|
||||
Using a 64bit OS:
|
||||
@@ -111,6 +125,13 @@ Using a 64bit OS:
|
||||
-D PHYTIUM=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
```
|
||||
|
||||
#### for ADLink machines
|
||||
|
||||
Using a 64bit OS:
|
||||
```
|
||||
-D ADLINK=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
```
|
||||
|
||||
#### for M1
|
||||
|
||||
Only test on Asahi for now, using the default "16K page" kernel
|
||||
@@ -151,6 +172,26 @@ Using a 64bit OS:
|
||||
-D LX2160A=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
```
|
||||
|
||||
#### for Termux
|
||||
|
||||
You must have ARM64 Device for build box64.
|
||||
|
||||
##### in CHRoot/PRoot
|
||||
|
||||
```
|
||||
-D ARM64=1 -DCMAKE_C_COMPILER=gcc -DBAD_SIGNAL=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
```
|
||||
|
||||
##### in Termux (Native)
|
||||
|
||||
NOTE: BUILDING BOX64 IN TERMUX NATIVE IS EXPERIMENTAL AND DOESN'T GONNA RUN LINUX BINARIES IN NATIVE TERMUX BOX64!!!
|
||||
|
||||
You also needed have `libandroid-sysv-semaphore` and `libandroid-spawn` libraries:
|
||||
|
||||
```
|
||||
-D TERMUX=1 -D -DCMAKE_C_COMPILER=clang CMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
```
|
||||
|
||||
#### for x86_64 Linux
|
||||
```
|
||||
-D LD80BITS=1 -D NOALIGN=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
@@ -159,7 +200,7 @@ If you encounter some linking errors, try using `NOLOADADDR=ON` (`cmake -D NOLOA
|
||||
|
||||
----
|
||||
|
||||
### use ccmake
|
||||
### Use ccmake
|
||||
|
||||
Alternatively, you can **use the curses-bases ccmake (or any other gui frontend for cmake)** to select wich platform to use interactively.
|
||||
|
||||
@@ -180,12 +221,19 @@ To have a trace enabled build (***the interpreter will be slightly slower***), a
|
||||
#### To have ARM Dynarec
|
||||
|
||||
Dynarec is only available on ARM (for the meantime), Activate it by using `-DARM_DYNAREC=1`.
|
||||
###### *Note: VFPv3 and NEON are required for Dynarec.*
|
||||
|
||||
#### To have a build using less memory
|
||||
|
||||
You can use `-DSAVE_MEM` to have a build that will try to save some memory. It's, for now, only increasing the jumptable from 4 level to 5 levels. The added granularity avoid wasting space, but the 1 level more to the jumptable means there is on read from memory more when jumping between blocks.
|
||||
|
||||
#### Not building from a git clone
|
||||
|
||||
If you are not building from a git clone (for example, downloading a release source code zip from github), you need to use `-DNOGIT=1` from cmake to be able to build (box64 uses git SHA1 to show last commit in version number).
|
||||
|
||||
#### Use faster linker
|
||||
|
||||
You need to add `-DWITH_MOLD=1` if GNU ld is extremely slow. Then run `mold -run make -j4` to build (make sure [Mold](https://github.com/rui314/mold) is installed).
|
||||
|
||||
----
|
||||
|
||||
Testing
|
||||
|
||||
Executable → Regular
+40
-11
@@ -3,7 +3,10 @@ Usage
|
||||
----
|
||||
|
||||
There are many environment variables to control Box64 behaviour.
|
||||
Env. var with * can also be put inside box64rc files
|
||||
Env. var with * can also be put inside box64rc files.
|
||||
Box64 look for 2 places for rcfile: `/etc/box64.box64rc` and `~/.box64rc`
|
||||
The second takes precedence to the first, on an APP level
|
||||
(that means if an [MYAPP] my appears in both file, only the settings in `~/.box64rc` will be applied)
|
||||
|
||||
#### BOX64_LOG *
|
||||
Controls the Verbosity level of the logs
|
||||
@@ -49,7 +52,7 @@ Only on build with trace enabled. Trace allow the logging of all instruction exe
|
||||
* 0xXXXXXXX-0xYYYYYYY : Trace only between the 2 addresses.
|
||||
|
||||
#### BOX64_TRACE_INIT *
|
||||
Use BOX64_TRACE_INIT instead of BOX_TRACE to start trace before the initialisation of libraries and the running program
|
||||
Use BOX64_TRACE_INIT instead of BOX64_TRACE to start trace before the initialisation of libraries and the running program
|
||||
* 0 : No trace. (Default.)
|
||||
* 1 : Trace enabled. The trace start with the initialisation of all depending libraries is done.
|
||||
|
||||
@@ -153,8 +156,9 @@ Define Box64's Dynarec max allowed forward value when building Block.
|
||||
#### BOX64_DYNAREC_STRONGMEM *
|
||||
Enable/Disable simulation of Strong Memory model
|
||||
* 0 : Don't try anything special (Default.)
|
||||
* 1 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model while trying to limit performance impact (Default when libmonobdwgc-2.0.so is loaded)
|
||||
* 2 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model
|
||||
* 1 : Enable some Memory Barrier when writting to memory (on some MOV opcode) to simulate Strong Memory Model while trying to limit performance impact (Default when libmonobdwgc-2.0.so is loaded)
|
||||
* 2 : All 1. plus a memory barrier on every write to memory using MOV
|
||||
* 3 : All 2. plus Memory Barrier when reading from memory and on some SSE/SSE2 opcodes too
|
||||
|
||||
#### BOX64_DYNAREC_X87DOUBLE *
|
||||
Force the use of Double for x87 emulation
|
||||
@@ -179,8 +183,8 @@ Handling of flags on CALL/RET opcodes
|
||||
|
||||
#### BOX64_DYNAREC_CALLRET *
|
||||
Optimisation of CALL/RET opcodes (not compatible with jit/dynarec/smc)
|
||||
* 0 : Don't optimize CALL/RET, use Jump Table for boths (Default)
|
||||
* 1 : Try to optimized CALL/RET, skipping the use of the JumpTable when possible (will crash if blacks are invalidate, so probably incompatible with JIT/Dynarec)
|
||||
* 0 : Don't optimize CALL/RET, use Jump Table for boths
|
||||
* 1 : Try to optimized CALL/RET, skipping the use of the JumpTable when possible (Default)
|
||||
|
||||
#### BOX64_DYNAREC_HOTPAGE *
|
||||
Handling of HotPage (Page being both executed and written)
|
||||
@@ -192,6 +196,11 @@ Will use a faster handling of HotPage (Page being both executed and written)
|
||||
* 0 : use regular hotpage (Default)
|
||||
* 1 : Use faster hotpage, taking the risk of running obsolete JIT code (might be faster, but more prone to crash)
|
||||
|
||||
#### BOX64_DYNAREC_ALIGNED_ATOMICS *
|
||||
Generated code for aligned atomics only
|
||||
* 0 : The code generated can handle unaligned atomics (Default)
|
||||
* 1 : Generated code only for aligned atomics (faster and less code generated, but will SEGBUS if LOCK prefix is unsed on unaligned data)
|
||||
|
||||
#### BOX64_DYNAREC_BLEEDING_EDGE *
|
||||
Detect MonoBleedingEdge and apply conservative settings
|
||||
* 0 : Don't detect MonoBleedingEdge
|
||||
@@ -222,11 +231,21 @@ Handling of x87 80bits long double
|
||||
* 0 : Try to handle 80bits long double as precise as possible (Default)
|
||||
* 1 : Handle them as double
|
||||
|
||||
#### BOX64_SYNC_ROUNDING *
|
||||
Box64 will sync rounding mode with fesetround/fegetround.
|
||||
* 0 : Disable rounding mode syncing. (Default.)
|
||||
* 1 : Enable rounding mode syncing.
|
||||
|
||||
#### BOX64_LIBCEF *
|
||||
Detect libcef and apply malloc_hack settings
|
||||
* 0 : Don't detect libcef
|
||||
* 1 : Detect libcef, and apply MALLOC_HACK=2 if detected (Default)
|
||||
|
||||
#### BOX64_SDL2_JGUID *
|
||||
Need a workaround for SDL_GetJoystickGUIDInfo function for wrapped SDL2
|
||||
* 0 : Don't use any workaround
|
||||
* 1 : Use a workaround for program that use the private SDL_GetJoystickGUIDInfo function with 1 missing argument
|
||||
|
||||
#### BOX64_LIBGL *
|
||||
* libXXXX set the name for libGL (defaults to libGL.so.1).
|
||||
* /PATH/TO/libGLXXX : Sets the name and path for libGL
|
||||
@@ -282,12 +301,17 @@ Disables the load of vulkan libraries.
|
||||
* 0 : Load vulkan libraries if found.
|
||||
* 1 : Disables the load of vulkan libraries, both the native and the i386 version (can be useful on Pi4, where the vulkan driver is not quite there yet.)
|
||||
|
||||
#### BOX64_FUTEX_WAITV *
|
||||
Use of the new fuext_waitc syscall
|
||||
* 0 : Do not try to use it, return unsupported (Default for BAD_SIGNAL build)
|
||||
* 1 : let program use the syscall if the host system support it (Default for other build)
|
||||
|
||||
#### BOX64_BASH *
|
||||
Define x86_64 bash to launch script
|
||||
* yyyy
|
||||
Will use yyyy as x86_64 bash to launch script. yyyy needs to be a full path to a valid x86_64 version of bash
|
||||
|
||||
#### BOX64_ENV
|
||||
#### BOX64_ENV *
|
||||
* XXX=yyyy
|
||||
will add XXX=yyyy env. var.
|
||||
|
||||
@@ -295,6 +319,10 @@ Define x86_64 bash to launch script
|
||||
* XXX=yyyy
|
||||
will add XXX=yyyy env. var. and continue with BOX86_ENV2 ... until var doesn't exist
|
||||
|
||||
#### BOX64_RESERVE_HIGH
|
||||
* 0 : Don't try to pe-reserve high memory (beyond 47bits) (Default)
|
||||
* 1 : Try to reserve (without allocating it) memory beyond 47bits (seems unstable)
|
||||
|
||||
#### BOX64_JITGDB *
|
||||
* 0 : Just print the Segfault message on segfault (default)
|
||||
* 1 : Launch `gdb` when a segfault, bus error or illegal instruction signal is trapped, attached to the offending process and go in an endless loop, waiting.
|
||||
@@ -305,6 +333,7 @@ Define x86_64 bash to launch script
|
||||
* 2 : Launch `gdbserver` when a segfault, bus error or illegal instruction signal is trapped, attached to the offending process, and go in an endless loop, waiting.
|
||||
Use `gdb /PATH/TO/box64` and then `target remote 127.0.0.1:1234` to connect to the gdbserver (or use actual IP if not on the machine). After that, the procedure is the same as with ` BOX64_JITGDB=1`.
|
||||
This mode can be usefullwhen programs redirect all console output to a file (like Unity3D Games)
|
||||
* 3 : Launch `lldb` when a segfault, bus error or illegal instruction signal is trapped, attached to the offending process and go in an endless loop, waiting.
|
||||
|
||||
#### BOX64_NORCFILES
|
||||
If the env var exist, no rc files (like /etc/box64.box64rc and ~/.box64rc) will be loaded
|
||||
@@ -318,10 +347,10 @@ Those variables are only valid inside a rcfile:
|
||||
* 0 : Nothing special
|
||||
* 1 : Added "--no-sandbox" to command line arguments (usefull for chrome based programs)
|
||||
|
||||
#### BOX64_INPROCESSGPU
|
||||
* 0 : Nothing special
|
||||
* 1 : Added "--in-process-gpu" to command line arguments (usefull for chrome based programs)
|
||||
|
||||
#### BOX64_EXIT
|
||||
* 0 : Nothing special
|
||||
* 1 : Just exit, don't try to run the program
|
||||
|
||||
#### BOX64_RESERVE_HIGH
|
||||
* 0 : Don't try to pe-reserve high memory (beyond 47bits) (Default)
|
||||
* 1 : Try to reserve (without allocating it) memory beyond 47bits (seems unstable)
|
||||
+20
-1
@@ -55,6 +55,11 @@ F<~/.bashrc> may override the setting from your command line. Example:
|
||||
When set to 1, add C<--no-sandbox> to command line arguments (useful for chrome
|
||||
based programs).
|
||||
|
||||
=item B<BOX64_INPROCESSGPU=0|1>
|
||||
|
||||
When set to 1, add C<--in-process-gpu> to command line arguments (useful for chrome
|
||||
based programs).
|
||||
|
||||
=item B<BOX64_EXIT>=I<0|1>
|
||||
|
||||
When set to 1, just exit, don't try to run the program.
|
||||
@@ -146,7 +151,7 @@ Only on build with trace enabled. Trace allow the logging of all instruction exe
|
||||
|
||||
=item B<BOX64_TRACE_INIT>=I<0|1>
|
||||
|
||||
Use B<BOX64_TRACE_INIT> instead of B<BOX_TRACE> to start trace before the
|
||||
Use B<BOX64_TRACE_INIT> instead of B<BOX64_TRACE> to start trace before the
|
||||
initialization of libraries and the running program
|
||||
|
||||
* 0 : No trace. (Default.)
|
||||
@@ -371,6 +376,13 @@ Handling of x87 80bits long double
|
||||
* 0 : Try to handle 80bits long double as precise as possible (Default)
|
||||
* 1 : Handle them as double
|
||||
|
||||
=item B<BOX64_SYNC_ROUNDING>=I<0|1>
|
||||
|
||||
Box64 will sync rounding mode with fesetround/fegetround.
|
||||
|
||||
* 0 : Disable rounding mode syncing. (Default.)
|
||||
* 1 : Enable rounding mode syncing.
|
||||
|
||||
=item B<BOX64_LIBCEF>=I<0|1>
|
||||
|
||||
Detect libcef and apply malloc_hack settings
|
||||
@@ -451,6 +463,13 @@ Disables the load of vulkan libraries.
|
||||
* 0 : Load vulkan libraries if found.
|
||||
* 1 : Disables the load of vulkan libraries, both the native and the i386 version (can be useful on Pi4, where the vulkan driver is not quite there yet.)
|
||||
|
||||
=item B<BOX64_FUTEX_WAITV>=I<0|1>
|
||||
|
||||
Use of the new fuext_waitc syscall
|
||||
|
||||
* 0 : Do not try to use it, return unsupported (default for BAD_SIGNAL build)
|
||||
* 1 : let program use the syscall if the host system support it (Default for other build)
|
||||
|
||||
=item B<BOX64_BASH>=I<yyyy>
|
||||
|
||||
Define x86_64 bash to launch script. Will use yyyy as x86_64 bash to launch
|
||||
|
||||
Executable → Regular
File mode changed.
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
Executable → Regular
File mode changed.
|
Before Width: | Height: | Size: 180 KiB After Width: | Height: | Size: 180 KiB |
+27
-1
@@ -402,6 +402,7 @@ def readFiles(files: Iterable[Filename]) -> Tuple[JumbledGlobals, JumbledRedirec
|
||||
or match("libGL", "libEGL") \
|
||||
or match("libc", "tcmallocminimal") \
|
||||
or match("libc", "tbbmallocproxy") \
|
||||
or match("libc", "androidshmem") \
|
||||
or match("tcmallocminimal", "tbbmallocproxy"):
|
||||
continue
|
||||
|
||||
@@ -824,6 +825,10 @@ def main(root: str, files: Iterable[Filename], ver: str):
|
||||
allowed_regs : str = "cCwWiuIUlLp"
|
||||
allowed_fpr : str = "fd"
|
||||
|
||||
# Detect functions which return in an x87 register
|
||||
retx87_wraps: Dict[ClausesStr, List[FunctionType]] = {}
|
||||
return_x87: str = "DK"
|
||||
|
||||
# Sanity checks
|
||||
forbidden_simple: str = "EDKVOSNMHPAxX"
|
||||
assert(len(allowed_simply) + len(allowed_regs) + len(allowed_fpr) + len(forbidden_simple) == len(allowed_conv.values))
|
||||
@@ -831,6 +836,7 @@ def main(root: str, files: Iterable[Filename], ver: str):
|
||||
assert(all(c not in allowed_simply + allowed_regs for c in allowed_fpr))
|
||||
assert(all(c not in allowed_simply + allowed_regs + allowed_fpr for c in forbidden_simple))
|
||||
assert(all(c in allowed_simply + allowed_regs + allowed_fpr + forbidden_simple for c in allowed_conv.values))
|
||||
assert(all(c in allowed_conv.values for c in return_x87))
|
||||
|
||||
def check_simple(v: FunctionType) -> Optional[int]:
|
||||
regs_count: int = 0
|
||||
@@ -867,6 +873,15 @@ def main(root: str, files: Iterable[Filename], ver: str):
|
||||
simple_wraps[k] = tmp
|
||||
simple_idxs = sorted(simple_wraps.keys(), key=lambda x: Clauses(x).splitdef())
|
||||
|
||||
def check_return_x87(v: FunctionType) -> bool:
|
||||
return v[0] in return_x87
|
||||
|
||||
for k in gbls:
|
||||
tmp = [v for v in gbls[k] if check_return_x87(v)]
|
||||
if tmp:
|
||||
retx87_wraps[k] = tmp
|
||||
retx87_idxs = sorted(retx87_wraps.keys(), key=lambda x: Clauses(x).splitdef())
|
||||
|
||||
# Now the files rebuilding part
|
||||
# File headers and guards
|
||||
files_header = {
|
||||
@@ -1381,6 +1396,17 @@ def main(root: str, files: Iterable[Filename], ver: str):
|
||||
file.write("#endif\n")
|
||||
file.write("\treturn 0;\n}\n")
|
||||
|
||||
# Write the isRetX87Wrapper function
|
||||
file.write("\nint isRetX87Wrapper(wrapper_t fun) {\n")
|
||||
for k in retx87_idxs:
|
||||
if k != str(Clauses()):
|
||||
file.write("#if " + k + "\n")
|
||||
for vf in retx87_wraps[k]:
|
||||
file.write("\tif (fun == &" + vf + ") return 1;\n")
|
||||
if k != str(Clauses()):
|
||||
file.write("#endif\n")
|
||||
file.write("\treturn 0;\n}\n")
|
||||
|
||||
file.write(files_guard["wrapper.c"].format(lbr="{", rbr="}", version=ver))
|
||||
|
||||
# Rewrite the wrapper.h file:
|
||||
@@ -1454,6 +1480,6 @@ if __name__ == '__main__':
|
||||
if v == "--":
|
||||
limit.append(i)
|
||||
Define.defines = list(map(DefineType, sys.argv[2:limit[0]]))
|
||||
if main(sys.argv[1], sys.argv[limit[0]+1:], "2.2.0.17") != 0:
|
||||
if main(sys.argv[1], sys.argv[limit[0]+1:], "2.2.0.18") != 0:
|
||||
exit(2)
|
||||
exit(0)
|
||||
Executable → Regular
+4
-1
@@ -11,6 +11,9 @@ endif( NOT TEST_OUTPUT )
|
||||
if( NOT TEST_REFERENCE )
|
||||
message( FATAL_ERROR "Require TEST_REFERENCE to be defined" )
|
||||
endif( NOT TEST_REFERENCE )
|
||||
if(NOT DEFINED ENV{INTERPRETER})
|
||||
set(ENV{INTERPRETER} "")
|
||||
endif()
|
||||
|
||||
set(ENV{BOX64_LOG} 0)
|
||||
set(ENV{BOX64_NOBANNER} 1)
|
||||
@@ -24,7 +27,7 @@ endif( EXISTS ${CMAKE_SOURCE_DIR}/x64lib )
|
||||
|
||||
# run the test program, capture the stdout/stderr and the result var
|
||||
execute_process(
|
||||
COMMAND ${TEST_PROGRAM} ${TEST_ARGS} ${TEST_ARGS2}
|
||||
COMMAND $ENV{INTERPRETER} ${TEST_PROGRAM} ${TEST_ARGS} ${TEST_ARGS2}
|
||||
OUTPUT_FILE ${TEST_OUTPUT}
|
||||
ERROR_VARIABLE TEST_ERROR
|
||||
RESULT_VARIABLE TEST_RESULT
|
||||
|
||||
Executable → Regular
+7
-1
@@ -68,6 +68,8 @@ void free_tlsdatasize(void* p)
|
||||
tlsdatasize_t *data = (tlsdatasize_t*)p;
|
||||
box_free(data->ptr);
|
||||
box_free(p);
|
||||
if(my_context)
|
||||
pthread_setspecific(my_context->tlskey, NULL);
|
||||
}
|
||||
|
||||
void x64Syscall(x64emu_t *emu);
|
||||
@@ -259,6 +261,8 @@ box64context_t *NewBox64Context(int argc)
|
||||
context->segtls[4].present = 1;
|
||||
context->segtls[4].is32bits = 1;
|
||||
|
||||
context->globdata = NewMapSymbols();
|
||||
|
||||
initAllHelpers(context);
|
||||
|
||||
return context;
|
||||
@@ -276,6 +280,7 @@ void FreeBox64Context(box64context_t** context)
|
||||
|
||||
box64context_t* ctx = *context; // local copy to do the cleanning
|
||||
|
||||
//clean_current_emuthread(); // cleaning main thread seems a bad idea
|
||||
if(ctx->local_maplib)
|
||||
FreeLibrarian(&ctx->local_maplib, NULL);
|
||||
if(ctx->maplib)
|
||||
@@ -340,7 +345,6 @@ void FreeBox64Context(box64context_t** context)
|
||||
void* ptr;
|
||||
if ((ptr = pthread_getspecific(ctx->tlskey)) != NULL) {
|
||||
free_tlsdatasize(ptr);
|
||||
pthread_setspecific(ctx->tlskey, NULL);
|
||||
}
|
||||
pthread_key_delete(ctx->tlskey);
|
||||
|
||||
@@ -353,6 +357,8 @@ void FreeBox64Context(box64context_t** context)
|
||||
if(ctx->emu_sig)
|
||||
FreeX64Emu(&ctx->emu_sig);
|
||||
|
||||
FreeMapSymbols(&ctx->globdata);
|
||||
|
||||
finiAllHelpers(ctx);
|
||||
|
||||
#ifdef DYNAREC
|
||||
|
||||
Executable → Regular
+1
-1
@@ -3,6 +3,6 @@
|
||||
|
||||
#define BOX64_MAJOR 0
|
||||
#define BOX64_MINOR 2
|
||||
#define BOX64_REVISION 3
|
||||
#define BOX64_REVISION 6
|
||||
|
||||
#endif //__BOX64_VERSION_H_
|
||||
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
+461
-141
File diff suppressed because it is too large.
Load diff
Executable → Regular
+375
-47
@@ -92,24 +92,24 @@
|
||||
|
||||
// MOVZ
|
||||
#define MOVZ_gen(sf, hw, imm16, Rd) ((sf)<<31 | 0b10<<29 | 0b100101<<23 | (hw)<<21 | (imm16)<<5 | (Rd))
|
||||
#define MOVZx(Rd, imm16) EMIT(MOVZ_gen(1, 0, ((uint16_t)imm16)&0xffff, Rd))
|
||||
#define MOVZx_LSL(Rd, imm16, shift) EMIT(MOVZ_gen(1, (shift)/16, ((uint16_t)imm16)&0xffff, Rd))
|
||||
#define MOVZw(Rd, imm16) EMIT(MOVZ_gen(0, 0, ((uint16_t)imm16)&0xffff, Rd))
|
||||
#define MOVZw_LSL(Rd, imm16, shift) EMIT(MOVZ_gen(0, (shift)/16, ((uint16_t)imm16)&0xffff, Rd))
|
||||
#define MOVZx(Rd, imm16) EMIT(MOVZ_gen(1, 0, ((uint16_t)(imm16))&0xffff, Rd))
|
||||
#define MOVZx_LSL(Rd, imm16, shift) EMIT(MOVZ_gen(1, (shift)/16, ((uint16_t)(imm16))&0xffff, Rd))
|
||||
#define MOVZw(Rd, imm16) EMIT(MOVZ_gen(0, 0, ((uint16_t)(imm16))&0xffff, Rd))
|
||||
#define MOVZw_LSL(Rd, imm16, shift) EMIT(MOVZ_gen(0, (shift)/16, ((uint16_t)(imm16))&0xffff, Rd))
|
||||
|
||||
// MOVN
|
||||
#define MOVN_gen(sf, hw, imm16, Rd) ((sf)<<31 | 0b00<<29 | 0b100101<<23 | (hw)<<21 | (imm16)<<5 | (Rd))
|
||||
#define MOVNx(Rd, imm16) EMIT(MOVN_gen(1, 0, ((uint16_t)imm16)&0xffff, Rd))
|
||||
#define MOVNx_LSL(Rd, imm16, shift) EMIT(MOVN_gen(1, (shift)/16, ((uint16_t)imm16)&0xffff, Rd))
|
||||
#define MOVNw(Rd, imm16) EMIT(MOVN_gen(0, 0, ((uint16_t)imm16)&0xffff, Rd))
|
||||
#define MOVNw_LSL(Rd, imm16, shift) EMIT(MOVN_gen(0, (shift)/16, ((uint16_t)imm16)&0xffff, Rd))
|
||||
#define MOVNx(Rd, imm16) EMIT(MOVN_gen(1, 0, ((uint16_t)(imm16))&0xffff, Rd))
|
||||
#define MOVNx_LSL(Rd, imm16, shift) EMIT(MOVN_gen(1, (shift)/16, ((uint16_t)(imm16))&0xffff, Rd))
|
||||
#define MOVNw(Rd, imm16) EMIT(MOVN_gen(0, 0, ((uint16_t)(imm16))&0xffff, Rd))
|
||||
#define MOVNw_LSL(Rd, imm16, shift) EMIT(MOVN_gen(0, (shift)/16, ((uint16_t)(imm16))&0xffff, Rd))
|
||||
|
||||
// MOVK
|
||||
#define MOVK_gen(sf, hw, imm16, Rd) ((sf)<<31 | 0b11<<29 | 0b100101<<23 | (hw)<<21 | (imm16)<<5 | (Rd))
|
||||
#define MOVKx(Rd, imm16) EMIT(MOVK_gen(1, 0, ((uint16_t)imm16)&0xffff, Rd))
|
||||
#define MOVKx_LSL(Rd, imm16, shift) EMIT(MOVK_gen(1, (shift)/16, ((uint16_t)imm16)&0xffff, Rd))
|
||||
#define MOVKw(Rd, imm16) EMIT(MOVK_gen(0, 0, ((uint16_t)imm16)&0xffff, Rd))
|
||||
#define MOVKw_LSL(Rd, imm16, shift) EMIT(MOVK_gen(0, (shift)/16, ((uint16_t)imm16)&0xffff, Rd))
|
||||
#define MOVKx(Rd, imm16) EMIT(MOVK_gen(1, 0, ((uint16_t)(imm16))&0xffff, Rd))
|
||||
#define MOVKx_LSL(Rd, imm16, shift) EMIT(MOVK_gen(1, (shift)/16, ((uint16_t)(imm16))&0xffff, Rd))
|
||||
#define MOVKw(Rd, imm16) EMIT(MOVK_gen(0, 0, ((uint16_t)(imm16))&0xffff, Rd))
|
||||
#define MOVKw_LSL(Rd, imm16, shift) EMIT(MOVK_gen(0, (shift)/16, ((uint16_t)(imm16))&0xffff, Rd))
|
||||
|
||||
// This macro will give a -Wsign-compare warning, probably bug #38341
|
||||
#define MOV32w(Rd, imm32) \
|
||||
@@ -200,6 +200,12 @@
|
||||
#define SBCSw_REG(Rd, Rn, Rm) EMIT(ADDSUBC_gen(0, 1, 1, Rm, Rn, Rd))
|
||||
#define SBCSxw_REG(Rd, Rn, Rm) EMIT(ADDSUBC_gen(rex.w, 1, 1, Rm, Rn, Rd))
|
||||
|
||||
// CCMP compare if cond is true, set nzcv if false
|
||||
#define CCMP_reg(sf, Rm, cond, Rn, nzcv) ((sf)<<31 | 1<<30 | 1<<29 | 0b11010010<<21 | (Rm)<<16 | (cond)<<12 | (Rn)<<5 | (nzcv))
|
||||
#define CCMPw(Wn, Wm, nzcv, cond) EMIT(CCMP_reg(0, Wm, cond, Wn, nzcv))
|
||||
#define CCMPx(Xn, Xm, nzcv, cond) EMIT(CCMP_reg(1, Xm, cond, Xn, nzcv))
|
||||
#define CCMPxw(Xn, Xm, nzcv, cond) EMIT(CCMP_reg(rex.w, Xm, cond, Xn, nzcv))
|
||||
|
||||
// ADR
|
||||
#define ADR_gen(immlo, immhi, Rd) ((immlo)<<29 | 0b10000<<24 | (immhi)<<5 | (Rd))
|
||||
#define ADR_S20(Rd, imm) EMIT(ADR_gen((imm)&3, ((imm)>>2)&0x7ffff, (Rd)))
|
||||
@@ -240,6 +246,7 @@
|
||||
#define LDRxw_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b10+rex.w, Rm, 0b011, 0, Rn, Rt))
|
||||
#define LDRz_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(rex.is32bits?0b10:0b11, Rm, 0b011, 0, Rn, Rt))
|
||||
#define LDRB_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b00, Rm, 0b011, 0, Rn, Rt))
|
||||
#define LDRB_REG_UXTW(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b00, Rm, 0b010, 0, Rn, Rt))
|
||||
#define LDRH_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b01, Rm, 0b011, 0, Rn, Rt))
|
||||
|
||||
#define LDRS_U12_gen(size, op1, opc, imm12, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | (opc)<<22 | (imm12)<<10 | (Rn)<<5 | (Rt))
|
||||
@@ -363,6 +370,9 @@
|
||||
#define POP2_32(reg1, reg2) LDPw_S7_postindex(reg1, reg2, xRSP, 8)
|
||||
#define PUSH2_32(reg1, reg2) STPw_S7_preindex(reg2, reg1, xRSP, -8)
|
||||
|
||||
#define POP1_16(reg) LDRH_S9_postindex(reg, xRSP, 2)
|
||||
#define PUSH1_16(reg) STRH_S9_preindex(reg, xRSP, -2)
|
||||
|
||||
#define POP1z(reg) if(rex.is32bits) {POP1_32(reg);} else {POP1(reg);}
|
||||
#define PUSH1z(reg) if(rex.is32bits) {PUSH1_32(reg);} else {PUSH1(reg);}
|
||||
#define POP2z(reg1, reg2) if(rex.is32bits) {POP2_32(reg1, reg2);} else {POP2(reg1, reg2);}
|
||||
@@ -424,6 +434,13 @@
|
||||
// Data Memory Barrier
|
||||
#define DMB_gen(CRm) (0b1101010100<<22 | 0b011<<16 | 0b0011<<12 | (CRm)<<8 | 1<<7 | 0b01<<5 | 0b11111)
|
||||
#define DMB_ISH() EMIT(DMB_gen(0b1011))
|
||||
#define DMB_SY() EMIT(DMB_gen(0b1111))
|
||||
|
||||
// Data Synchronization Barrier
|
||||
#define DSB_gen(CRm) (0b1101010100<<22 | 0b011<<16 | 0b0011<<12 | (CRm)<<8 | 1<<7 | 0b00<<5 | 0b11111)
|
||||
#define DSB_ISH() EMIT(DSB_gen(0b1011))
|
||||
#define DSB_ISHST() EMIT(DSB_gen(0b1010))
|
||||
#define DSB_SY() EMIT(DSB_gen(0b1111))
|
||||
|
||||
// Break
|
||||
#define BRK_gen(imm16) (0b11010100<<24 | 0b001<<21 | (((imm16)&0xffff)<<5))
|
||||
@@ -487,9 +504,9 @@
|
||||
#define CSNEGx(Rd, Rn, Rm, cond) EMIT(CSNEG_gen(1, Rm, cond, Rn, Rd))
|
||||
#define CSNEGw(Rd, Rn, Rm, cond) EMIT(CSNEG_gen(0, Rm, cond, Rn, Rd))
|
||||
#define CSNEGxw(Rd, Rn, Rm, cond) EMIT(CSNEG_gen(rex.w, Rm, cond, Rn, Rd))
|
||||
#define CNEGx(Rd, Rn, cond) CSNEGx(Rn, Rn, Rn, invCond(cond))
|
||||
#define CNEGw(Rd, Rn, cond) CSNEGw(Rn, Rn, Rn, invCond(cond))
|
||||
#define CNEGxw(Rd, Rn, cond) CSNEGxw(Rn, Rn, Rn, invCond(cond))
|
||||
#define CNEGx(Rd, Rn, cond) CSNEGx(Rn, Rn, Rd, invCond(cond))
|
||||
#define CNEGw(Rd, Rn, cond) CSNEGw(Rn, Rn, Rd, invCond(cond))
|
||||
#define CNEGxw(Rd, Rn, cond) CSNEGxw(Rn, Rn, Rd, invCond(cond))
|
||||
|
||||
// AND / ORR
|
||||
#define LOGIC_gen(sf, opc, N, immr, imms, Rn, Rd) ((sf)<<31 | (opc)<<29 | 0b100100<<23 | (N)<<22 | (immr)<<16 | (imms)<<10 | (Rn)<<5 | Rd)
|
||||
@@ -534,6 +551,15 @@
|
||||
#define EORx_REG_LSR(Rd, Rn, Rm, lsr) EMIT(LOGIC_REG_gen(1, 0b10, 0b01, 0, Rm, lsr, Rn, Rd))
|
||||
#define EORw_REG_LSR(Rd, Rn, Rm, lsr) EMIT(LOGIC_REG_gen(0, 0b10, 0b01, 0, Rm, lsr, Rn, Rd))
|
||||
#define EORxw_REG_LSR(Rd, Rn, Rm, lsr) EMIT(LOGIC_REG_gen(rex.w, 0b10, 0b01, 0, Rm, lsr, Rn, Rd))
|
||||
#define EONx_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(1, 0b10, 0b00, 1, Rm, 0, Rn, Rd))
|
||||
#define EONw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(0, 0b10, 0b00, 1, Rm, 0, Rn, Rd))
|
||||
#define EONxw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(rex.w, 0b10, 0b00, 1, Rm, 0, Rn, Rd))
|
||||
#define EONx_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(1, 0b10, 0b00, 1, Rm, lsl, Rn, Rd))
|
||||
#define EONw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(0, 0b10, 0b00, 1, Rm, lsl, Rn, Rd))
|
||||
#define EONxw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(rex.w, 0b10, 0b00, 1, Rm, lsl, Rn, Rd))
|
||||
#define EONx_REG_LSR(Rd, Rn, Rm, lsr) EMIT(LOGIC_REG_gen(1, 0b10, 0b01, 1, Rm, lsr, Rn, Rd))
|
||||
#define EONw_REG_LSR(Rd, Rn, Rm, lsr) EMIT(LOGIC_REG_gen(0, 0b10, 0b01, 1, Rm, lsr, Rn, Rd))
|
||||
#define EONxw_REG_LSR(Rd, Rn, Rm, lsr) EMIT(LOGIC_REG_gen(rex.w, 0b10, 0b01, 1, Rm, lsr, Rn, Rd))
|
||||
#define MOVx_REG(Rd, Rm) ORRx_REG(Rd, xZR, Rm)
|
||||
#define MOVw_REG(Rd, Rm) ORRw_REG(Rd, xZR, Rm)
|
||||
#define MOVxw_REG(Rd, Rm) ORRxw_REG(Rd, xZR, Rm)
|
||||
@@ -560,6 +586,12 @@
|
||||
#define BICx_REG BICx
|
||||
#define BICw_REG BICw
|
||||
#define BICxw_REG BICxw
|
||||
#define BICx_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(1, 0b00, 0b00, 1, Rm, lsl, Rn, Rd))
|
||||
#define BICw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(0, 0b00, 0b00, 1, Rm, lsl, Rn, Rd))
|
||||
#define BICxw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(rex.w, 0b00, 0b00, 1, Rm, lsl, Rn, Rd))
|
||||
#define BICx_REG_LSR(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(1, 0b00, 0b01, 1, Rm, lsl, Rn, Rd))
|
||||
#define BICw_REG_LSR(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(0, 0b00, 0b01, 1, Rm, lsl, Rn, Rd))
|
||||
#define BICxw_REG_LSR(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(rex.w, 0b00, 0b01, 1, Rm, lsl, Rn, Rd))
|
||||
#define TSTx_REG(Rn, Rm) ANDSx_REG(xZR, Rn, Rm)
|
||||
#define TSTw_REG(Rn, Rm) ANDSw_REG(wZR, Rn, Rm)
|
||||
#define TSTxw_REG(Rn, Rm) ANDSxw_REG(xZR, Rn, Rm)
|
||||
@@ -575,12 +607,12 @@
|
||||
#define BFMx(Rd, Rn, immr, imms) EMIT(BFM_gen(1, 0b01, 1, immr, imms, Rn, Rd))
|
||||
#define BFMw(Rd, Rn, immr, imms) EMIT(BFM_gen(0, 0b01, 0, immr, imms, Rn, Rd))
|
||||
#define BFMxw(Rd, Rn, immr, imms) EMIT(BFM_gen(rex.w, 0b01, rex.w, immr, imms, Rn, Rd))
|
||||
#define BFIx(Rd, Rn, lsb, width) BFMx(Rd, Rn, ((-lsb)%64)&0x3f, (width)-1)
|
||||
#define BFIw(Rd, Rn, lsb, width) BFMw(Rd, Rn, ((-lsb)%32)&0x1f, (width)-1)
|
||||
#define BFIx(Rd, Rn, lsb, width) BFMx(Rd, Rn, ((-(lsb))%64)&0x3f, (width)-1)
|
||||
#define BFIw(Rd, Rn, lsb, width) BFMw(Rd, Rn, ((-(lsb))%32)&0x1f, (width)-1)
|
||||
#define BFIxw(Rd, Rn, lsb, width) if(rex.w) {BFIx(Rd, Rn, lsb, width);} else {BFIw(Rd, Rn, lsb, width);}
|
||||
#define BFCx(Rd, lsb, width) BFMx(Rd, xZR, ((-lsb)%64)&0x3f, (width)-1)
|
||||
#define BFCw(Rd, lsb, width) BFMw(Rd, xZR, ((-lsb)%32)&0x1f, (width)-1)
|
||||
#define BFCxw(Rd, lsb, width) BFMxw(Rd, xZR, rex.w?(((-lsb)%64)&0x3f):(((-lsb)%32)&0x1f), (width)-1)
|
||||
#define BFCx(Rd, lsb, width) BFMx(Rd, xZR, ((-(lsb))%64)&0x3f, (width)-1)
|
||||
#define BFCw(Rd, lsb, width) BFMw(Rd, xZR, ((-(lsb))%32)&0x1f, (width)-1)
|
||||
#define BFCxw(Rd, lsb, width) BFMxw(Rd, xZR, rex.w?(((-(lsb))%64)&0x3f):(((-(lsb))%32)&0x1f), (width)-1)
|
||||
// Insert lsb:width part of Rn into low part of Rd (leaving rest of Rd untouched)
|
||||
#define BFXILx(Rd, Rn, lsb, width) EMIT(BFM_gen(1, 0b01, 1, (lsb), (lsb)+(width)-1, Rn, Rd))
|
||||
// Insert lsb:width part of Rn into low part of Rd (leaving rest of Rd untouched)
|
||||
@@ -619,9 +651,9 @@
|
||||
#define SBFMx(Rd, Rn, immr, imms) EMIT(SBFM_gen(1, 1, immr, imms, Rn, Rd))
|
||||
#define SBFMw(Rd, Rn, immr, imms) EMIT(SBFM_gen(0, 0, immr, imms, Rn, Rd))
|
||||
#define SBFMxw(Rd, Rn, immr, imms) EMIT(SBFM_gen(rex.w, rex.w, immr, imms, Rn, Rd))
|
||||
#define SBFXx(Rd, Rn, lsb, width) SBFMx(Rd, Rn, lsb, lsb+width-1)
|
||||
#define SBFXw(Rd, Rn, lsb, width) SBFMw(Rd, Rn, lsb, lsb+width-1)
|
||||
#define SBFXxw(Rd, Rn, lsb, width) SBFMxw(Rd, Rn, lsb, lsb+width-1)
|
||||
#define SBFXx(Rd, Rn, lsb, width) SBFMx(Rd, Rn, lsb, (lsb)+(width)-1)
|
||||
#define SBFXw(Rd, Rn, lsb, width) SBFMw(Rd, Rn, lsb, (lsb)+(width)-1)
|
||||
#define SBFXxw(Rd, Rn, lsb, width) SBFMxw(Rd, Rn, lsb, (lsb)+(width)-1)
|
||||
#define SXTBx(Rd, Rn) SBFMx(Rd, Rn, 0, 7)
|
||||
#define SXTBw(Rd, Rn) SBFMw(Rd, Rn, 0, 7)
|
||||
#define SXTHx(Rd, Rn) SBFMx(Rd, Rn, 0, 15)
|
||||
@@ -765,13 +797,13 @@
|
||||
// imm16 must be 4-aligned
|
||||
#define VLDR128_U12(Qt, Rn, imm16) EMIT(VMEM_gen(0b00, 0b11, ((uint32_t)((imm16)>>4))&0xfff, Rn, Qt))
|
||||
// (imm14) must be 3-aligned
|
||||
#define VSTR32_U12(Dt, Rn, imm14) EMIT(VMEM_gen(0b10, 0b00, ((uint32_t)(imm14>>2))&0xfff, Rn, Dt))
|
||||
#define VSTR32_U12(Dt, Rn, imm14) EMIT(VMEM_gen(0b10, 0b00, ((uint32_t)((imm14)>>2))&0xfff, Rn, Dt))
|
||||
// (imm15) must be 3-aligned
|
||||
#define VSTR64_U12(Dt, Rn, imm15) EMIT(VMEM_gen(0b11, 0b00, ((uint32_t)(imm15>>3))&0xfff, Rn, Dt))
|
||||
#define VSTR64_U12(Dt, Rn, imm15) EMIT(VMEM_gen(0b11, 0b00, ((uint32_t)((imm15)>>3))&0xfff, Rn, Dt))
|
||||
// imm16 must be 4-aligned
|
||||
#define VSTR128_U12(Qt, Rn, imm16) EMIT(VMEM_gen(0b00, 0b10, ((uint32_t)((imm16)>>4))&0xfff, Rn, Qt))
|
||||
// (imm13) must be 1-aligned
|
||||
#define VSTR16_U12(Ht, Rn, imm13) EMIT(VMEM_gen(0b01, 0b00, ((uint32_t)(imm13>>1))&0xfff, Rn, Ht))
|
||||
#define VSTR16_U12(Ht, Rn, imm13) EMIT(VMEM_gen(0b01, 0b00, ((uint32_t)((imm13)>>1))&0xfff, Rn, Ht))
|
||||
|
||||
#define VMEMUR_vector(size, opc, imm9, Rn, Rt) ((size)<<30 | 0b111<<27 | 1<<26 | (opc)<<22 | (imm9)<<12 | (Rn)<<5 | (Rt))
|
||||
// signed offset, no alignement!
|
||||
@@ -933,6 +965,15 @@
|
||||
#define VSRI_16(Vd, Vn, shift) EMIT(VSRI_vector(0, 0b0010 | ((shift)>>3)&1, (shift)&7, Vn, Vd))
|
||||
#define VSRI_32(Vd, Vn, shift) EMIT(VSRI_vector(0, 0b0100 | (((shift)>>3)&3), (shift)&7, Vn, Vd))
|
||||
|
||||
// Reverse elements in 64-bit doublewords (vector). This instruction reverses the order of 8-bit, 16-bit, or 32-bit elements in each doubleword
|
||||
#define VREVx_vector(Q, U, size, o0, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 0b10000<<17 | (o0)<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
#define VREV64_32(Vd, Vn) EMIT(VREVx_vector(0, 0, 0b10, 0, Vn, Vd))
|
||||
#define VREV64_16(Vd, Vn) EMIT(VREVx_vector(0, 0, 0b01, 0, Vn, Vd))
|
||||
#define VREV64_8(Vd, Vn) EMIT(VREVx_vector(0, 0, 0b00, 0, Vn, Vd))
|
||||
#define VREV64Q_32(Vd, Vn) EMIT(VREVx_vector(1, 0, 0b10, 0, Vn, Vd))
|
||||
#define VREV64Q_16(Vd, Vn) EMIT(VREVx_vector(1, 0, 0b01, 0, Vn, Vd))
|
||||
#define VREV64Q_8(Vd, Vn) EMIT(VREVx_vector(1, 0, 0b00, 0, Vn, Vd))
|
||||
|
||||
// Integer MATH
|
||||
#define ADDSUB_vector(Q, U, size, Rm, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b10000<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define VADDQ_8(Vd, Vn, Vm) EMIT(ADDSUB_vector(1, 0, 0b00, Vm, Vn, Vd))
|
||||
@@ -950,6 +991,10 @@
|
||||
#define VSUB_16(Vd, Vn, Vm) EMIT(ADDSUB_vector(0, 1, 0b01, Vm, Vn, Vd))
|
||||
#define VSUB_32(Vd, Vn, Vm) EMIT(ADDSUB_vector(0, 1, 0b10, Vm, Vn, Vd))
|
||||
|
||||
#define ADDSUB_scalar(U, size, Rm, Rn, Rd) (01<<30 | (U)<<29 | 0b11110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b10000<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define ADD_64(Vd, Vn, Vm) EMIT(ADDSUB_scalar(0, 0b11, Vm, Vn, Vd))
|
||||
#define SUB_64(Vd, Vn, Vm) EMIT(ADDSUB_scalar(1, 0b11, Vm, Vn, Vd))
|
||||
|
||||
#define NEGABS_vector(Q, U, size, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 0b10000<<17 | 0b01011<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
#define NEG_8(Vd, Vn) EMIT(NEGABS_vector(0, 1, 0b00, Vn, Vd))
|
||||
#define NEG_16(Vd, Vn) EMIT(NEGABS_vector(0, 1, 0b01, Vn, Vd))
|
||||
@@ -1072,6 +1117,12 @@
|
||||
#define FADDP_vector(Q, sz, Rm, Rn, Rd) ((Q)<<30 | 1<<29 | 0b01110<<24 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b11010<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define VFADDPQS(Vd, Vn, Vm) EMIT(FADDP_vector(1, 0, Vm, Vn, Vd))
|
||||
#define VFADDPQD(Vd, Vn, Vm) EMIT(FADDP_vector(1, 1, Vm, Vn, Vd))
|
||||
#define VFADDPS(Vd, Vn, Vm) EMIT(FADDP_vector(0, 0, Vm, Vn, Vd))
|
||||
#define VFADDPD(Vd, Vn, Vm) EMIT(FADDP_vector(0, 1, Vm, Vn, Vd))
|
||||
|
||||
#define FADDP_scalar(sz, Rn, Rd) (0b01<<30 | 1<<29 | 0b11110<<24 | (sz)<<22 | 0b11000<<17 | 0b01101<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
#define FADDPS(Sd, Sn) EMIT(FADDP_scalar(0, Sn, Sd))
|
||||
#define FADDPD(Dd, Dn) EMIT(FADDP_scalar(1, Dn, Dd))
|
||||
|
||||
// NEG / ABS
|
||||
#define FNEGABS_scalar(type, opc, Rn, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | (opc)<<15 | 0b10000<<10 | (Rn)<<5 | (Rd))
|
||||
@@ -1338,22 +1389,12 @@
|
||||
#define VFRINTRDQ(Vd,Vn, mode) EMIT(FRINT_vector(1, 0, (mode)&1, 1, ((mode)>>1)&1, Vn, Vd))
|
||||
// round with mode, mode is 0 = TieEven, 1=+inf, 2=-inf, 3=zero
|
||||
#define VFRINTRSQ(Vd,Vn, mode) EMIT(FRINT_vector(1, 0, (mode)&1, 0, ((mode)>>1)&1, Vn, Vd))
|
||||
#define VFRINTRS(Vd, Vn, mode) EMIT(FRINT_vector(0, 0, (mode)&1, 0, ((mode)>>1)&1, Vn, Vd))
|
||||
|
||||
#define FRINTI_scalar(type, Rn, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | 0b001<<18 | 0b111<<15 | 0b10000<<10 | (Rn)<<5 | (Rd))
|
||||
#define FRINTIS(Sd, Sn) EMIT(FRINTI_scalar(0b00, Sn, Sd))
|
||||
#define FRINTID(Dd, Dn) EMIT(FRINTI_scalar(0b01, Dn, Dd))
|
||||
|
||||
|
||||
#define FRINTxx_scalar(type, op, Rn, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | 0b0100<<17 | (op)<<15 | 0b10000<<10 | (Rn)<<5 | (Rd))
|
||||
#define FRINT32ZS(Sd, Sn) EMIT(FRINTxx_scalar(0b00, 0b00, Sn, Sd))
|
||||
#define FRINT32ZD(Dd, Dn) EMIT(FRINTxx_scalar(0b01, 0b00, Dn, Dd))
|
||||
#define FRINT32XS(Sd, Sn) EMIT(FRINTxx_scalar(0b00, 0b01, Sn, Sd))
|
||||
#define FRINT32XD(Dd, Dn) EMIT(FRINTxx_scalar(0b01, 0b01, Dn, Dd))
|
||||
#define FRINT64ZS(Sd, Sn) EMIT(FRINTxx_scalar(0b00, 0b10, Sn, Sd))
|
||||
#define FRINT64ZD(Dd, Dn) EMIT(FRINTxx_scalar(0b01, 0b10, Dn, Dd))
|
||||
#define FRINT64XS(Sd, Sn) EMIT(FRINTxx_scalar(0b00, 0b11, Sn, Sd))
|
||||
#define FRINT64XD(Dd, Dn) EMIT(FRINTxx_scalar(0b01, 0b11, Dn, Dd))
|
||||
|
||||
#define FRINT_scalar(type, rmode, Rn, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | 0b001<<18 | (rmode)<<15 | 0b10000<<10 | (Rn)<<5 | (Rd))
|
||||
// round toward 0 (truncate)
|
||||
#define FRINTZS(Sd, Sn) EMIT(FRINT_scalar(0b00, 0b011, Sn, Sd))
|
||||
@@ -1424,14 +1465,23 @@
|
||||
#define VUZP1Q_64(Rt, Rn, Rm) EMIT(UZP_gen(1, 0b11, Rm, 0, Rn, Rt))
|
||||
#define VUZP2Q_64(Rt, Rn, Rm) EMIT(UZP_gen(1, 0b11, Rm, 1, Rn, Rt))
|
||||
|
||||
#define DUP_gen(Q, imm5, Rn, Rd) ((Q)<<30 | 0b01110000<<21 | (imm5)<<16 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define VDUP_8(Vd, Vn, idx) EMIT(DUP_gen(0, ((idx)<<1|1), Vn, Vd))
|
||||
#define VDUPQ_8(Vd, Vn, idx) EMIT(DUP_gen(1, ((idx)<<1|1), Vn, Vd))
|
||||
#define VDUP_16(Vd, Vn, idx) EMIT(DUP_gen(0, ((idx)<<2|0b10), Vn, Vd))
|
||||
#define VDUPQ_16(Vd, Vn, idx) EMIT(DUP_gen(1, ((idx)<<2|0b10), Vn, Vd))
|
||||
#define VDUP_32(Vd, Vn, idx) EMIT(DUP_gen(0, ((idx)<<3|0b100), Vn, Vd))
|
||||
#define VDUPQ_32(Vd, Vn, idx) EMIT(DUP_gen(1, ((idx)<<3|0b100), Vn, Vd))
|
||||
#define VDUPQ_64(Vd, Vn, idx) EMIT(DUP_gen(1, ((idx)<<4|0b1000), Vn, Vd))
|
||||
#define DUP_element(Q, imm5, Rn, Rd) ((Q)<<30 | 0b01110000<<21 | (imm5)<<16 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define VDUP_8(Vd, Vn, idx) EMIT(DUP_element(0, ((idx)<<1|1), Vn, Vd))
|
||||
#define VDUPQ_8(Vd, Vn, idx) EMIT(DUP_element(1, ((idx)<<1|1), Vn, Vd))
|
||||
#define VDUP_16(Vd, Vn, idx) EMIT(DUP_element(0, ((idx)<<2|0b10), Vn, Vd))
|
||||
#define VDUPQ_16(Vd, Vn, idx) EMIT(DUP_element(1, ((idx)<<2|0b10), Vn, Vd))
|
||||
#define VDUP_32(Vd, Vn, idx) EMIT(DUP_element(0, ((idx)<<3|0b100), Vn, Vd))
|
||||
#define VDUPQ_32(Vd, Vn, idx) EMIT(DUP_element(1, ((idx)<<3|0b100), Vn, Vd))
|
||||
#define VDUPQ_64(Vd, Vn, idx) EMIT(DUP_element(1, ((idx)<<4|0b1000), Vn, Vd))
|
||||
|
||||
#define DUP_general(Q, imm5, Rn, Rd) ((Q)<<30 | 0b01110000<<21 | (imm5)<<16 | 0b11<<10 | (Rn)<<5 | (Rd))
|
||||
#define VDUPB(Vd, Wn) EMIT(DUP_general(0, 0b1, Wn, Vd))
|
||||
#define VDUPQB(Vd, Wn) EMIT(DUP_general(1, 0b1, Wn, Vd))
|
||||
#define VDUPH(Vd, Wn) EMIT(DUP_general(0, 0b10, Wn, Vd))
|
||||
#define VDUPQH(Vd, Wn) EMIT(DUP_general(1, 0b10, Wn, Vd))
|
||||
#define VDUPS(Vd, Wn) EMIT(DUP_general(0, 0b100, Wn, Vd))
|
||||
#define VDUPQS(Vd, Wn) EMIT(DUP_general(1, 0b100, Wn, Vd))
|
||||
#define VDUPQD(Vd, Xn) EMIT(DUP_general(1, 0b1000, Xn, Vd))
|
||||
|
||||
// TBL
|
||||
#define TBL_gen(Q, Rm, len, op, Rn, Rd) ((Q)<<30 | 0b001110<<24 | (Rm)<<16 | (len)<<13 | (op)<<12 | (Rn)<<5 | (Rd))
|
||||
@@ -1459,7 +1509,6 @@
|
||||
#define VTRNQ1_32(Vd, Vn, Vm) EMIT(TRN_gen(1, 0b10, Vm, 0, Vn, Vd))
|
||||
#define VTRNQ1_16(Vd, Vn, Vm) EMIT(TRN_gen(1, 0b01, Vm, 0, Vn, Vd))
|
||||
#define VTRNQ1_8(Vd, Vn, Vm) EMIT(TRN_gen(1, 0b00, Vm, 0, Vn, Vd))
|
||||
#define VSWP(Vd, Vn) VTRNQ1_64(Vd, Vn, Vn)
|
||||
#define VTRNQ2_64(Vd, Vn, Vm) EMIT(TRN_gen(1, 0b11, Vm, 1, Vn, Vd))
|
||||
#define VTRNQ2_32(Vd, Vn, Vm) EMIT(TRN_gen(1, 0b10, Vm, 1, Vn, Vd))
|
||||
#define VTRNQ2_16(Vd, Vn, Vm) EMIT(TRN_gen(1, 0b01, Vm, 1, Vn, Vd))
|
||||
@@ -1568,6 +1617,15 @@
|
||||
#define CMEQQ_0_16(Rd, Rn) EMIT(CMEQ_0_vector(1, 0b01, Rn, Rd))
|
||||
#define CMEQQ_0_32(Rd, Rn) EMIT(CMEQ_0_vector(1, 0b10, Rn, Rd))
|
||||
#define CMEQQ_0_64(Rd, Rn) EMIT(CMEQ_0_vector(1, 0b11, Rn, Rd))
|
||||
// Greater Than 0
|
||||
#define CMCond_0_vector(Q, U, size, op, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 0b10000<<17 | 0b0100<<13 | (op)<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
#define CMGT_0_8(Rd, Rn) EMIT(CMCond_0_vector(0, 0, 0b00, 0, Rn, Rd))
|
||||
#define CMGT_0_16(Rd, Rn) EMIT(CMCond_0_vector(0, 0, 0b01, 0, Rn, Rd))
|
||||
#define CMGT_0_32(Rd, Rn) EMIT(CMCond_0_vector(0, 0, 0b10, 0, Rn, Rd))
|
||||
#define CMGTQ_0_8(Rd, Rn) EMIT(CMCond_0_vector(1, 0, 0b00, 0, Rn, Rd))
|
||||
#define CMGTQ_0_16(Rd, Rn) EMIT(CMCond_0_vector(1, 0, 0b01, 0, Rn, Rd))
|
||||
#define CMGTQ_0_32(Rd, Rn) EMIT(CMCond_0_vector(1, 0, 0b10, 0, Rn, Rd))
|
||||
#define CMGTQ_0_64(Rd, Rn) EMIT(CMCond_0_vector(1, 0, 0b11, 0, Rn, Rd))
|
||||
|
||||
// Vector Float CMP
|
||||
// EQual
|
||||
@@ -1726,9 +1784,11 @@
|
||||
// MOV Immediate
|
||||
#define MOVI_vector(Q, op, abc, cmode, defgh, Rd) ((Q)<<30 | (op)<<29 | 0b0111100000<<19 | (abc)<<16 | (cmode)<<12 | 1<<10 | (defgh)<<5 | (Rd))
|
||||
#define MOVIQ_8(Rd, imm8) EMIT(MOVI_vector(1, 0, (((imm8)>>5)&0b111), 0b1110, ((imm8)&0b11111), Rd))
|
||||
#define MOVIQ_16(Rd, imm8, lsl8) EMIT(MOVI_vector(1, 0, (((imm8)>>5)&0b111), 0b1000|((lsl8)?0b10:0), ((imm8)&0b11111), Rd))
|
||||
#define MOVI_8(Rd, imm8) EMIT(MOVI_vector(0, 0, (((imm8)>>5)&0b111), 0b1110, ((imm8)&0b11111), Rd))
|
||||
#define MOVI_16(Rd, imm8) EMIT(MOVI_vector(0, 0, (((imm8)>>5)&0b111), 0b1000, ((imm8)&0b11111), Rd))
|
||||
#define MOVI_16(Rd, imm8, lsl8) EMIT(MOVI_vector(0, 0, (((imm8)>>5)&0b111), 0b1000|((lsl8)?0b10:0), ((imm8)&0b11111), Rd))
|
||||
#define MOVI_32(Rd, imm8) EMIT(MOVI_vector(0, 0, (((imm8)>>5)&0b111), 0b0000, ((imm8)&0b11111), Rd))
|
||||
#define MOVI_64(Rd, imm8) EMIT(MOVI_vector(0, 1, (((imm8)>>5)&0b111), 0b1110, ((imm8)&0b11111), Rd))
|
||||
|
||||
// SHLL and eXtend Long
|
||||
#define SHLL_vector(Q, U, immh, immb, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b011110<<23 | (immh)<<19 | (immb)<<16 | 0b10100<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
@@ -1888,4 +1948,272 @@
|
||||
#define PMULL_128(Rd, Rn, Rm) EMIT(PMULL_gen(0, 0b11, Rm, Rn, Rd))
|
||||
#define PMULL2_128(Rd, Rn, Rm) EMIT(PMULL_gen(1, 0b11, Rm, Rn, Rd))
|
||||
|
||||
// ATOMIC extension
|
||||
#define ATOMIC_gen(size, A, R, Rs, opc, Rn, Rt) ((size)<<30 | 0b111<<27 | (A)<<23 | (R)<<22 | 1<<21 | (Rs)<<16 | (opc)<<12 | (Rn)<<5 | (Rt))
|
||||
// Atomic ADD
|
||||
#define LDADDxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b000, Rn, Rt))
|
||||
#define LDADDAxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 0, Rs, 0b000, Rn, Rt))
|
||||
#define LDADDALxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 1, Rs, 0b000, Rn, Rt))
|
||||
#define LDADDLxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b000, Rn, Rt))
|
||||
#define STADDxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b000, Rn, 0b11111))
|
||||
#define STADDLxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b000, Rn, 0b11111))
|
||||
#define LDADDB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b000, Rn, Rt))
|
||||
#define LDADDAB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 0, Rs, 0b000, Rn, Rt))
|
||||
#define LDADDALB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 1, Rs, 0b000, Rn, Rt))
|
||||
#define LDADDLB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b000, Rn, Rt))
|
||||
#define STADDB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b000, Rn, 0b11111))
|
||||
#define STADDLB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b000, Rn, 0b11111))
|
||||
#define LDADDH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b000, Rn, Rt))
|
||||
#define LDADDAH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 0, Rs, 0b000, Rn, Rt))
|
||||
#define LDADDALH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 1, Rs, 0b000, Rn, Rt))
|
||||
#define LDADDLH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b000, Rn, Rt))
|
||||
#define STADDH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b000, Rn, 0b11111))
|
||||
#define STADDLH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b000, Rn, 0b11111))
|
||||
// Atomic AND with complement (i.e. BIC)
|
||||
#define LDCLRxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b001, Rn, Rt))
|
||||
#define LDCLRAxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 0, Rs, 0b001, Rn, Rt))
|
||||
#define LDCLRALxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 1, Rs, 0b001, Rn, Rt))
|
||||
#define LDCLRLxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b001, Rn, Rt))
|
||||
#define STCLRxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b001, Rn, 0b11111))
|
||||
#define STCLRLxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b001, Rn, 0b11111))
|
||||
#define LDCLRB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b001, Rn, Rt))
|
||||
#define LDCLRAB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 0, Rs, 0b001, Rn, Rt))
|
||||
#define LDCLRALB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 1, Rs, 0b001, Rn, Rt))
|
||||
#define LDCLRLB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b001, Rn, Rt))
|
||||
#define STCLRB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b001, Rn, 0b11111))
|
||||
#define STCLRLB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b001, Rn, 0b11111))
|
||||
#define LDCLRH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b001, Rn, Rt))
|
||||
#define LDCLRAH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 0, Rs, 0b001, Rn, Rt))
|
||||
#define LDCLRALH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 1, Rs, 0b001, Rn, Rt))
|
||||
#define LDCLRLH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b001, Rn, Rt))
|
||||
#define STCLRH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b001, Rn, 0b11111))
|
||||
#define STCLRLH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b001, Rn, 0b11111))
|
||||
// Atomic EOR
|
||||
#define LDEORxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b010, Rn, Rt))
|
||||
#define LDEORAxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 0, Rs, 0b010, Rn, Rt))
|
||||
#define LDEORALxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 1, Rs, 0b010, Rn, Rt))
|
||||
#define LDEORLxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b010, Rn, Rt))
|
||||
#define STEORxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b010, Rn, 0b11111))
|
||||
#define STEORLxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b010, Rn, 0b11111))
|
||||
#define LDEORB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b010, Rn, Rt))
|
||||
#define LDEORAB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 0, Rs, 0b010, Rn, Rt))
|
||||
#define LDEORALB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 1, Rs, 0b010, Rn, Rt))
|
||||
#define LDEORLB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b010, Rn, Rt))
|
||||
#define STEORB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b010, Rn, 0b11111))
|
||||
#define STEORLB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b010, Rn, 0b11111))
|
||||
#define LDEORH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b010, Rn, Rt))
|
||||
#define LDEORAH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 0, Rs, 0b010, Rn, Rt))
|
||||
#define LDEORALH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 1, Rs, 0b010, Rn, Rt))
|
||||
#define LDEORLH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b010, Rn, Rt))
|
||||
#define STEORH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b010, Rn, 0b11111))
|
||||
#define STEORLH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b010, Rn, 0b11111))
|
||||
// Atomic OR
|
||||
#define LDSETxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b011, Rn, Rt))
|
||||
#define LDSETAxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 0, Rs, 0b011, Rn, Rt))
|
||||
#define LDSETALxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 1, Rs, 0b011, Rn, Rt))
|
||||
#define LDSETLxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b011, Rn, Rt))
|
||||
#define STSETxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b011, Rn, 0b11111))
|
||||
#define STSETLxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b011, Rn, 0b11111))
|
||||
#define LDSETB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b011, Rn, Rt))
|
||||
#define LDSETAB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 0, Rs, 0b011, Rn, Rt))
|
||||
#define LDSETALB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 1, Rs, 0b011, Rn, Rt))
|
||||
#define LDSETLB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b011, Rn, Rt))
|
||||
#define STSETB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b011, Rn, 0b11111))
|
||||
#define STSETLB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b011, Rn, 0b11111))
|
||||
#define LDSETH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b011, Rn, Rt))
|
||||
#define LDSETAH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 0, Rs, 0b011, Rn, Rt))
|
||||
#define LDSETALH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 1, Rs, 0b011, Rn, Rt))
|
||||
#define LDSETLH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b011, Rn, Rt))
|
||||
#define STSETH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b011, Rn, 0b11111))
|
||||
#define STSETLH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b011, Rn, 0b11111))
|
||||
// Atomic Signel Max
|
||||
#define LDSMAXxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b100, Rn, Rt))
|
||||
#define LDSMAXAxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 0, Rs, 0b100, Rn, Rt))
|
||||
#define LDSMAXALxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 1, Rs, 0b100, Rn, Rt))
|
||||
#define LDSMAXLxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b100, Rn, Rt))
|
||||
#define STSMAXxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b100, Rn, 0b11111))
|
||||
#define STSMAXLxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b100, Rn, 0b11111))
|
||||
#define LDSMAXB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b100, Rn, Rt))
|
||||
#define LDSMAXAB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 0, Rs, 0b100, Rn, Rt))
|
||||
#define LDSMAXALB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 1, Rs, 0b100, Rn, Rt))
|
||||
#define LDSMAXLB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b100, Rn, Rt))
|
||||
#define STSMAXB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b100, Rn, 0b11111))
|
||||
#define STSMAXLB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b100, Rn, 0b11111))
|
||||
#define LDSMAXH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b100, Rn, Rt))
|
||||
#define LDSMAXAH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 0, Rs, 0b100, Rn, Rt))
|
||||
#define LDSMAXALH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 1, Rs, 0b100, Rn, Rt))
|
||||
#define LDSMAXLH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b100, Rn, Rt))
|
||||
#define STSMAXH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b100, Rn, 0b11111))
|
||||
#define STSMAXLH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b100, Rn, 0b11111))
|
||||
// Atomic Signed Min
|
||||
#define LDSMINxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b101, Rn, Rt))
|
||||
#define LDSMINAxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 0, Rs, 0b101, Rn, Rt))
|
||||
#define LDSMINALxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 1, Rs, 0b101, Rn, Rt))
|
||||
#define LDSMINLxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b101, Rn, Rt))
|
||||
#define STSMINxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b101, Rn, 0b11111))
|
||||
#define STSMINLxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b101, Rn, 0b11111))
|
||||
#define LDSMINB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b101, Rn, Rt))
|
||||
#define LDSMINAB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 0, Rs, 0b101, Rn, Rt))
|
||||
#define LDSMINALB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 1, Rs, 0b101, Rn, Rt))
|
||||
#define LDSMINLB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b101, Rn, Rt))
|
||||
#define STSMINB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b101, Rn, 0b11111))
|
||||
#define STSMINLB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b101, Rn, 0b11111))
|
||||
#define LDSMINH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b101, Rn, Rt))
|
||||
#define LDSMINAH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 0, Rs, 0b101, Rn, Rt))
|
||||
#define LDSMINALH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 1, Rs, 0b101, Rn, Rt))
|
||||
#define LDSMINLH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b101, Rn, Rt))
|
||||
#define STSMINH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b101, Rn, 0b11111))
|
||||
#define STSMINLH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b101, Rn, 0b11111))
|
||||
// Atomic Unsigned Max
|
||||
#define LDUMAXxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b110, Rn, Rt))
|
||||
#define LDUMAXAxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 0, Rs, 0b110, Rn, Rt))
|
||||
#define LDUMAXALxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 1, Rs, 0b110, Rn, Rt))
|
||||
#define LDUMAXLxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b110, Rn, Rt))
|
||||
#define STUMAXxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b110, Rn, 0b11111))
|
||||
#define STUMAXLxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b110, Rn, 0b11111))
|
||||
#define LDUMAXB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b110, Rn, Rt))
|
||||
#define LDUMAXAB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 0, Rs, 0b110, Rn, Rt))
|
||||
#define LDUMAXALB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 1, Rs, 0b110, Rn, Rt))
|
||||
#define LDUMAXLB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b110, Rn, Rt))
|
||||
#define STUMAXB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b110, Rn, 0b11111))
|
||||
#define STUMAXLB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b110, Rn, 0b11111))
|
||||
#define LDUMAXH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b110, Rn, Rt))
|
||||
#define LDUMAXAH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 0, Rs, 0b110, Rn, Rt))
|
||||
#define LDUMAXALH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 1, Rs, 0b110, Rn, Rt))
|
||||
#define LDUMAXLH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b110, Rn, Rt))
|
||||
#define STUMAXH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b110, Rn, 0b11111))
|
||||
#define STUMAXLH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b110, Rn, 0b11111))
|
||||
// Atomic Unsigned Min
|
||||
#define LDUMINxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b111, Rn, Rt))
|
||||
#define LDUMINAxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 0, Rs, 0b111, Rn, Rt))
|
||||
#define LDUMINALxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 1, Rs, 0b111, Rn, Rt))
|
||||
#define LDUMINLxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b111, Rn, Rt))
|
||||
#define STUMINxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b111, Rn, 0b11111))
|
||||
#define STUMINLxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b111, Rn, 0b11111))
|
||||
#define LDUMINB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b111, Rn, Rt))
|
||||
#define LDUMINAB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 0, Rs, 0b111, Rn, Rt))
|
||||
#define LDUMINALB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 1, Rs, 0b111, Rn, Rt))
|
||||
#define LDUMINLB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b111, Rn, Rt))
|
||||
#define STUMINB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b111, Rn, 0b11111))
|
||||
#define STUMINLB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b111, Rn, 0b11111))
|
||||
#define LDUMINH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b111, Rn, Rt))
|
||||
#define LDUMINAH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 0, Rs, 0b111, Rn, Rt))
|
||||
#define LDUMINALH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 1, Rs, 0b111, Rn, Rt))
|
||||
#define LDUMINLH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b111, Rn, Rt))
|
||||
#define STUMINH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b111, Rn, 0b11111))
|
||||
#define STUMINLH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b111, Rn, 0b11111))
|
||||
|
||||
// SWAPxx(Xs, Xt, Xn) : [Xn] => Xt, Xs => [Xn]
|
||||
#define SWAP_gen(size, A, R, Rs, Rn, Rt) ((size)<<30 | 0b111<<27 | (A)<<23 | (R)<<22 | 1<<21 | (Rs)<<16 | 1<<15 | (Rn)<<5 | (Rt))
|
||||
#define SWPxw(Rs, Rt, Rn) EMIT(SWAP_gen(0b10+rex.w, 0, 0, Rs, Rn, Rt))
|
||||
#define SWPAxw(Rs, Rt, Rn) EMIT(SWAP_gen(0b10+rex.w, 1, 0, Rs, Rn, Rt))
|
||||
#define SWPALxw(Rs, Rt, Rn) EMIT(SWAP_gen(0b10+rex.w, 1, 1, Rs, Rn, Rt))
|
||||
#define SWPLxw(Rs, Rt, Rn) EMIT(SWAP_gen(0b10+rex.w, 0, 1, Rs, Rn, Rt))
|
||||
#define SWPB(Rs, Rt, Rn) EMIT(SWAP_gen(0b00, 0, 0, Rs, Rn, Rt))
|
||||
#define SWPAB(Rs, Rt, Rn) EMIT(SWAP_gen(0b00, 1, 0, Rs, Rn, Rt))
|
||||
#define SWPALB(Rs, Rt, Rn) EMIT(SWAP_gen(0b00, 1, 1, Rs, Rn, Rt))
|
||||
#define SWPLB(Rs, Rt, Rn) EMIT(SWAP_gen(0b00, 0, 1, Rs, Rn, Rt))
|
||||
#define SWPH(Rs, Rt, Rn) EMIT(SWAP_gen(0b01, 0, 0, Rs, Rn, Rt))
|
||||
#define SWPAH(Rs, Rt, Rn) EMIT(SWAP_gen(0b01, 1, 0, Rs, Rn, Rt))
|
||||
#define SWPALH(Rs, Rt, Rn) EMIT(SWAP_gen(0b01, 1, 1, Rs, Rn, Rt))
|
||||
#define SWPLH(Rs, Rt, Rn) EMIT(SWAP_gen(0b01, 0, 1, Rs, Rn, Rt))
|
||||
|
||||
#define CAS_gen(size, L, Rs, O0, Rn, Rt) ((size)<<30 | 0b001000<<24 | 1<<23 | (L)<<22 | 1<<21 | (Rs)<<16 | (O0)<<15 | 0b11111<<10 | (Rn)<<5 | (Rt))
|
||||
// Compare and Swap compare Rs with [Rn], write Rt is same, return old [Rn] in Rs
|
||||
#define CASxw(Rs, Rt, Rn) EMIT(CAS_gen(0b10+rex.w, 0, Rs, 0, Rn, Rt))
|
||||
#define CASAxw(Rs, Rt, Rn) EMIT(CAS_gen(0b10+rex.w, 1, Rs, 0, Rn, Rt))
|
||||
#define CASALxw(Rs, Rt, Rn) EMIT(CAS_gen(0b10+rex.w, 1, Rs, 1, Rn, Rt))
|
||||
#define CASLxw(Rs, Rt, Rn) EMIT(CAS_gen(0b10+rex.w, 0, Rs, 1, Rn, Rt))
|
||||
#define CASB(Rs, Rt, Rn) EMIT(CAS_gen(0b00, 0, Rs, 0, Rn, Rt))
|
||||
#define CASAB(Rs, Rt, Rn) EMIT(CAS_gen(0b00, 1, Rs, 0, Rn, Rt))
|
||||
#define CASALB(Rs, Rt, Rn) EMIT(CAS_gen(0b00, 1, Rs, 1, Rn, Rt))
|
||||
#define CASLB(Rs, Rt, Rn) EMIT(CAS_gen(0b00, 0, Rs, 1, Rn, Rt))
|
||||
#define CASH(Rs, Rt, Rn) EMIT(CAS_gen(0b01, 0, Rs, 0, Rn, Rt))
|
||||
#define CASAH(Rs, Rt, Rn) EMIT(CAS_gen(0b01, 1, Rs, 0, Rn, Rt))
|
||||
#define CASALH(Rs, Rt, Rn) EMIT(CAS_gen(0b01, 1, Rs, 1, Rn, Rt))
|
||||
#define CASLH(Rs, Rt, Rn) EMIT(CAS_gen(0b01, 0, Rs, 1, Rn, Rt))
|
||||
|
||||
#define CASP_gen(size, L, Rs, O0, Rn, Rt) ((size)<<30 | 0b001000<<24 | 0<<23 | (L)<<22 | 1<<21 | (Rs)<<16 | (O0)<<15 | 0b11111<<10 | (Rn)<<5 | (Rt))
|
||||
// Compare and Swap with pair, Rs, Rs+1 and Rt,Rt+1 with [Rt]
|
||||
#define CASPxw(Rs, Rt, Rn) EMIT(CASP_gen(0b00+rex.w, 0, Rs, 0, Rn, Rt))
|
||||
#define CASPAxw(Rs, Rt, Rn) EMIT(CASP_gen(0b00+rex.w, 1, Rs, 0, Rn, Rt))
|
||||
#define CASPALxw(Rs, Rt, Rn) EMIT(CASP_gen(0b00+rex.w, 1, Rs, 1, Rn, Rt))
|
||||
#define CASPLxw(Rs, Rt, Rn) EMIT(CASP_gen(0b00+rex.w, 0, Rs, 1, Rn, Rt))
|
||||
|
||||
// FLAGM extension
|
||||
// Invert Carry Flag
|
||||
#define CFINV() EMIT(0b1101010100<<22 | 0b0100<<12 | 0b000<<5 | 0b11111)
|
||||
|
||||
#define RMIF_gen(imm6, Rn, mask) (0b10111010000<<21 | (imm6)<<15 | 0b00001<<10 | (Rn)<<5 | (mask))
|
||||
// Rotate right reg and use as NZCV
|
||||
#define RMIF(Xn, shift, mask) EMIT(RMIF_gen(shift, Xn, mask))
|
||||
|
||||
#define SETF_gen(sz, Rn) (0b00111010000<<21 | (sz)<<14 | 0b0010<<10 | (Rn)<<5 | 0b1101)
|
||||
// Set NZVc with 8bit value of reg: N=bit7, Z=[0..7]==0, V=bit8 eor bit7, C unchanged
|
||||
#define SETF8(Wn) EMIT(SETF_gen(0, Wn))
|
||||
// Set NZVc with 16bit value of reg: N=bit15, Z=[0..15]==0, V=bit16 eor bit15, C unchanged
|
||||
#define SETF16(Wn) EMIT(SETF_gen(1, Wn))
|
||||
|
||||
// FLAGM2 extension
|
||||
// NZCV -> N=0 Z=C|V C=C&!V V=0
|
||||
#define AXFLAG() EMIT(0b1101010100<<22 | 0b0100<<12 | 0b010<<5 | 0b11111)
|
||||
// NZCV -> N=!C&!Z Z=Z&C C=C|Z V=!C&Z
|
||||
#define XAFLAG() EMIT(0b1101010100<<22 | 0b0100<<12 | 0b001<<5 | 0b11111)
|
||||
|
||||
// FRINTTS extension
|
||||
#define FRINTxx_scalar(type, op, Rn, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | 0b0100<<17 | (op)<<15 | 0b10000<<10 | (Rn)<<5 | (Rd))
|
||||
#define FRINT32ZS(Sd, Sn) EMIT(FRINTxx_scalar(0b00, 0b00, Sn, Sd))
|
||||
#define FRINT32ZD(Dd, Dn) EMIT(FRINTxx_scalar(0b01, 0b00, Dn, Dd))
|
||||
#define FRINT32XS(Sd, Sn) EMIT(FRINTxx_scalar(0b00, 0b01, Sn, Sd))
|
||||
#define FRINT32XD(Dd, Dn) EMIT(FRINTxx_scalar(0b01, 0b01, Dn, Dd))
|
||||
#define FRINT64ZS(Sd, Sn) EMIT(FRINTxx_scalar(0b00, 0b10, Sn, Sd))
|
||||
#define FRINT64ZD(Dd, Dn) EMIT(FRINTxx_scalar(0b01, 0b10, Dn, Dd))
|
||||
#define FRINT64XS(Sd, Sn) EMIT(FRINTxx_scalar(0b00, 0b11, Sn, Sd))
|
||||
#define FRINT64XD(Dd, Dn) EMIT(FRINTxx_scalar(0b01, 0b11, Dn, Dd))
|
||||
|
||||
// CRC32 extension
|
||||
#define CRC32C_gen(sf, Rm, sz, Rn, Rd) ((sf)<<31 | 0b11010110<<21 | (Rm)<<16 | 0b010<<13 | 1<<12 | (sz)<<10 | (Rn)<<5 | (Rd))
|
||||
#define CRC32CB(Wd, Wn, Wm) EMIT(CRC32C_gen(0, Wm, 0b00, Wn, Wd))
|
||||
#define CRC32CH(Wd, Wn, Wm) EMIT(CRC32C_gen(0, Wm, 0b01, Wn, Wd))
|
||||
#define CRC32CW(Wd, Wn, Wm) EMIT(CRC32C_gen(0, Wm, 0b10, Wn, Wd))
|
||||
#define CRC32CX(Wd, Wn, Xm) EMIT(CRC32C_gen(1, Xm, 0b11, Wn, Wd))
|
||||
#define CRC32Cxw(Wd, Wn, Rm) EMIT(CRC32C_gen(rex.w, Rm, 0b10|rex.w, Wn, Wd))
|
||||
|
||||
// SHA1 extension
|
||||
#define SHA1H_gen(Rn, Rd) (0b01011110<<24 | 0b10100<<17 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
// SHA1 fixed rotate (ROL 30 of 32bits value)
|
||||
#define SHA1H(Sd, Sn) EMIT(SHA1H_gen(Sn, Sd))
|
||||
|
||||
#define SHA1SU1_gen(Rn, Rd) (0b01011110<<24 | 0b10100<<17 | 0b00001<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
// SHA1 schedule update 1
|
||||
#define SHA1SU1(Vd, Vn) EMIT(SHA1SU1_gen(Vn, Vd))
|
||||
|
||||
#define SHA1C_gen(Rm, Rn, Rd) (0b01011110<<24 | (Rm)<<16 | (Rn)<<5 | (Rd))
|
||||
// SHA1 hash update (choose)
|
||||
#define SHA1C(Qd, Sn, Vm) EMIT(SHA1C_gen(Vm, Sn, Qd))
|
||||
|
||||
#define SHA1M_gen(Rm, Rn, Rd) (0b01011110<<24 | (Rm)<<16 | 0b010<<12 | (Rn)<<5 | (Rd))
|
||||
// SHA1 hash update (majority)
|
||||
#define SHA1M(Qd, Sn, Vm) EMIT(SHA1M_gen(Vm, Sn, Qd))
|
||||
|
||||
#define SHA1P_gen(Rm, Rn, Rd) (0b01011110<<24 | (Rm)<<16 | 0b001<<12 | (Rn)<<5 | (Rd))
|
||||
// SHA1 hash update (parity)
|
||||
#define SHA1P(Qd, Sn, Vm) EMIT(SHA1P_gen(Vm, Sn, Qd))
|
||||
|
||||
#define SHA256SU0_gen(Rn,Rd) (0b01011110<<24 | 0b10100<<17 | 0b00010<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
//SHA256 schedule update 0
|
||||
#define SHA256SU0(Vd, Vn) EMIT(SHA256SU0_gen(Vn, Vd))
|
||||
|
||||
#define SHA256SU1_gen(Rm, Rn, Rd) (0b01011110<<24 | (Rm)<<16 | 0b110<<12 | (Rn)<<5 | (Rd))
|
||||
//SHA256 schedule update 1
|
||||
#define SHA256SU1(Vd, Vn, Vm) EMIT(SHA256SU1_gen(Vm, Vn, Vd))
|
||||
|
||||
#define SHA256H_gen(Rm, Rn, Rd) (0b01011110<<24 | (Rm)<<16 | 0b100<<12 | (Rn)<<5 | (Rd))
|
||||
//SHA256 hash update (part 1)
|
||||
#define SHA256H(Vd, Vn, Vm) EMIT(SHA256H_gen(Vm, Vn, Vd))
|
||||
|
||||
#define SHA256H2_gen(Rm, Rn, Rd) (0b01011110<<24 | (Rm)<<16 | 0b101<<12 | (Rn)<<5 | (Rd))
|
||||
//SHA256 hash update (part 2)
|
||||
#define SHA256H2(Vd, Vn, Vm) EMIT(SHA256H2_gen(Vm, Vn, Vd))
|
||||
|
||||
#endif //__ARM64_EMITTER_H__
|
||||
Executable → Regular
File mode changed.
Executable → Regular
+21
@@ -29,6 +29,10 @@
|
||||
.global arm64_lock_incif0
|
||||
.global arm64_lock_decifnot0
|
||||
.global arm64_lock_store
|
||||
.global arm64_lock_store_dd
|
||||
.global arm64_lock_get_b
|
||||
.global arm64_lock_get_d
|
||||
.global arm64_lock_get_dd
|
||||
|
||||
arm64_lock_read_b:
|
||||
dmb ish
|
||||
@@ -254,3 +258,20 @@ arm64_lock_store:
|
||||
str w1, [x0]
|
||||
dmb ish
|
||||
ret
|
||||
|
||||
arm64_lock_store_dd:
|
||||
str x1, [x0]
|
||||
dmb ish
|
||||
ret
|
||||
|
||||
arm64_lock_get_b:
|
||||
ldaxrb w0, [x0]
|
||||
ret
|
||||
|
||||
arm64_lock_get_d:
|
||||
ldaxr w0, [x0]
|
||||
ret
|
||||
|
||||
arm64_lock_get_dd:
|
||||
ldaxr x0, [x0]
|
||||
ret
|
||||
Executable → Regular
+25
-13
@@ -27,46 +27,58 @@ extern void arm64_lock_read_dq(uint64_t * a, uint64_t* b, void* addr);
|
||||
// STLXRD of ADDR, return 0 if ok, 1 if not
|
||||
extern int arm64_lock_write_dq(uint64_t a, uint64_t b, void* addr);
|
||||
|
||||
// Atomicaly exchange value at [p] with val, return old p
|
||||
// Atomically exchange value at [p] with val, return old p
|
||||
extern uintptr_t arm64_lock_xchg_dd(void* p, uintptr_t val);
|
||||
|
||||
// Atomicaly exchange value at [p] with val, return old p
|
||||
// Atomically exchange value at [p] with val, return old p
|
||||
extern uint32_t arm64_lock_xchg_d(void* p, uint32_t val);
|
||||
|
||||
// Atomicaly exchange value at [p] with val, return old p
|
||||
// Atomically exchange value at [p] with val, return old p
|
||||
extern uint32_t arm64_lock_xchg_h(void* p, uint32_t val);
|
||||
|
||||
// Atomicaly exchange value at [p] with val, return old p
|
||||
// Atomically exchange value at [p] with val, return old p
|
||||
extern uint32_t arm64_lock_xchg_b(void* p, uint32_t val);
|
||||
|
||||
// Atomicaly store value to [p] only if [p] is NULL. Return old [p] value
|
||||
// Atomically store value to [p] only if [p] is NULL. Return old [p] value
|
||||
extern uint32_t arm64_lock_storeifnull_d(void*p, uint32_t val);
|
||||
|
||||
// Atomicaly store value to [p] only if [p] is NULL. Return old [p] value
|
||||
// Atomically store value to [p] only if [p] is NULL. Return old [p] value
|
||||
extern void* arm64_lock_storeifnull(void*p, void* val);
|
||||
|
||||
// Atomicaly store value to [p] only if [p] is ref. Return new [p] value (so val or old)
|
||||
// Atomically store value to [p] only if [p] is ref. Return new [p] value (so val or old)
|
||||
extern void* arm64_lock_storeifref(void*p, void* val, void* ref);
|
||||
|
||||
// Atomicaly store value to [p] only if [p] is ref. Return new [p] value (so val or old)
|
||||
// Atomically store value to [p] only if [p] is ref. Return new [p] value (so val or old)
|
||||
extern uint32_t arm64_lock_storeifref_d(void*p, uint32_t val, uint32_t ref);
|
||||
|
||||
// Atomicaly store value to [p] only if [p] is ref. Return new [p] value (so val or old)
|
||||
// Atomically store value to [p] only if [p] is ref. Return new [p] value (so val or old)
|
||||
extern uint32_t arm64_lock_storeifref2_d(void*p, uint32_t val, uint32_t ref);
|
||||
|
||||
// decrement atomicaly the byte at [p] (but only if p not 0)
|
||||
// decrement atomically the byte at [p] (but only if p not 0)
|
||||
extern void arm64_lock_decifnot0b(void*p);
|
||||
|
||||
// atomic store (with memory barrier)
|
||||
extern void arm64_lock_storeb(void*p, uint8_t b);
|
||||
|
||||
// increment atomicaly the int at [p] only if it was 0. Return the old value of [p]
|
||||
// increment atomically the int at [p] only if it was 0. Return the old value of [p]
|
||||
extern int arm64_lock_incif0(void*p);
|
||||
|
||||
// decrement atomicaly the int at [p] (but only if p not 0)
|
||||
// decrement atomically the int at [p] (but only if p not 0)
|
||||
extern int arm64_lock_decifnot0(void*p);
|
||||
|
||||
// atomic store (with memory barrier)
|
||||
extern void arm64_lock_store(void*p, uint32_t v);
|
||||
|
||||
#endif //__ARM64_LOCK__H__
|
||||
// atomic store (with memory barrier)
|
||||
extern void arm64_lock_store_dd(void*p, uint64_t v);
|
||||
|
||||
// atomic get (with memory barrier)
|
||||
extern uint8_t arm64_lock_get_b(void*p);
|
||||
|
||||
// atomic get (with memory barrier)
|
||||
extern uint32_t arm64_lock_get_d(void*p);
|
||||
|
||||
// atomic get (with memory barrier)
|
||||
extern void* arm64_lock_get_dd(void*p);
|
||||
|
||||
#endif //__ARM64_LOCK__H__
|
||||
Executable → Regular
File mode changed.
Executable → Regular
+245
-12
@@ -16,7 +16,7 @@ static const char* conds[] = {"cEQ", "cNE", "cCS", "cCC", "cMI", "cPL", "cVS", "
|
||||
#define abs(A) (((A)<0)?(-(A)):(A))
|
||||
|
||||
typedef struct arm64_print_s {
|
||||
int N, S, U, L, Q;
|
||||
int N, S, U, L, Q, A, R;
|
||||
int t, n, m, d, t2, a;
|
||||
int f, c, o, h, p;
|
||||
int i, r, s;
|
||||
@@ -60,6 +60,8 @@ int isMask(uint32_t opcode, const char* mask, arm64_print_t *a)
|
||||
case 'N': a->N = (a->N<<1) | v; break;
|
||||
case 'S': a->S = (a->S<<1) | v; break;
|
||||
case 'U': a->U = (a->U<<1) | v; break;
|
||||
case 'A': a->A = (a->A<<1) | v; break;
|
||||
case 'R': a->R = (a->R<<1) | v; break;
|
||||
case 'L': a->L = (a->L<<1) | v; break;
|
||||
case 'Q': a->Q = (a->Q<<1) | v; break;
|
||||
case 't': a->t = (a->t<<1) | v; break;
|
||||
@@ -182,22 +184,22 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
}
|
||||
if(isMask(opcode, "01111000010iiiiiiiii00nnnnnttttt", &a)) {
|
||||
int offset = signExtend(imm, 9);
|
||||
snprintf(buff, sizeof(buff), "LDRUH %s, [%s, %s0x%x]", Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));
|
||||
snprintf(buff, sizeof(buff), "LDURH %s, [%s, %s0x%x]", Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "001110001x0iiiiiiiii00nnnnnttttt", &a)) {
|
||||
int offset = signExtend(imm, 9);
|
||||
snprintf(buff, sizeof(buff), "LDRUSB %s, [%s, %s0x%x]", a.x?Xt[Rt]:Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));
|
||||
snprintf(buff, sizeof(buff), "LDURSB %s, [%s, %s0x%x]", a.x?Xt[Rt]:Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "011110001x0iiiiiiiii00nnnnnttttt", &a)) {
|
||||
int offset = signExtend(imm, 9);
|
||||
snprintf(buff, sizeof(buff), "LDRUSH %s, [%s, %s0x%x]", a.x?Xt[Rt]:Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));
|
||||
snprintf(buff, sizeof(buff), "LDURSH %s, [%s, %s0x%x]", a.x?Xt[Rt]:Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "10111000100iiiiiiiii00nnnnnttttt", &a)) {
|
||||
int offset = signExtend(imm, 9);
|
||||
snprintf(buff, sizeof(buff), "LDRUSW %s, [%s, %s0x%x]", Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));
|
||||
snprintf(buff, sizeof(buff), "LDURSW %s, [%s, %s0x%x]", Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "1x111000000iiiiiiiii00nnnnnttttt", &a)) {
|
||||
@@ -213,7 +215,7 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
}
|
||||
if(isMask(opcode, "01111000000iiiiiiiii00nnnnnttttt", &a)) {
|
||||
int offset = signExtend(imm, 9);
|
||||
snprintf(buff, sizeof(buff), "STRUH %s, [%s, %s0x%x]", Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));
|
||||
snprintf(buff, sizeof(buff), "STURH %s, [%s, %s0x%x]", Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "1x11100101iiiiiiiiiiiinnnnnttttt", &a)) {
|
||||
@@ -795,6 +797,11 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
snprintf(buff, sizeof(buff), "CSEL %s, %s, %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], conds[cond]);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "f1111010010mmmmmcccc00nnnnn0iiii", &a)) {
|
||||
snprintf(buff, sizeof(buff), "CCMP %s, %s, %s 0x%x", sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], conds[cond], imm);
|
||||
return buff;
|
||||
}
|
||||
|
||||
// MISC Bits
|
||||
if(isMask(opcode, "f10110101100000000010onnnnnddddd", &a)) {
|
||||
snprintf(buff, sizeof(buff), "CL%c %s, %s", option?'S':'Z', sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn]);
|
||||
@@ -950,6 +957,22 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
snprintf(buff, sizeof(buff), "VCMEQ V%d.%s, V%d.%s, V%d.%s", Rd, Vd, Rn, Vd, Rm, Vd);
|
||||
return buff;
|
||||
}
|
||||
// CMP zero
|
||||
if(isMask(opcode, "0QU01110ff100000100o10nnnnnddddd", &a)) {
|
||||
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
|
||||
const char* Z[] = {"GT", "GE", "EQ", "LE"};
|
||||
const char* Vd = Y[((sf)<<1) | a.Q];
|
||||
const char* Cond = Z[(a.o << 1 | a.U)];
|
||||
snprintf(buff, sizeof(buff), "VCM%s V%d.%s, V%d.%s, #0", Cond, Rd, Vd, Rn, Vd);
|
||||
return buff;
|
||||
}
|
||||
// CMPLT zero
|
||||
if(isMask(opcode, "0Q001110ff100000101010nnnnnddddd", &a)) {
|
||||
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
|
||||
const char* Vd = Y[((sf)<<1) | a.Q];
|
||||
snprintf(buff, sizeof(buff), "VCMLT V%d.%s, V%d.%s, #0", Rd, Vd, Rn, Vd);
|
||||
return buff;
|
||||
}
|
||||
// MIN/MAX
|
||||
if(isMask(opcode, "0QU01110ff1mmmmm0110o1nnnnnddddd", &a)) {
|
||||
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
|
||||
@@ -965,11 +988,21 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
snprintf(buff, sizeof(buff), "MOVI V%d.%s, #0x%x", Rd, Vd, imm);
|
||||
return buff;
|
||||
}
|
||||
// MOV immediate (not)shifted 16bits & 32bits
|
||||
// MOV immediate notshifted 16bits & 32bits
|
||||
if(isMask(opcode, "0Q00111100000iiif00001iiiiiddddd", &a)) {
|
||||
const char* Y[] = {"2S", "4S", "4H", "8H"};
|
||||
const char* Vd = Y[(sf<<1)| a.Q];
|
||||
snprintf(buff, sizeof(buff), "MOVI V%d.%s, #0x%x", Rd, Vd, imm);
|
||||
int sh = 0;
|
||||
|
||||
snprintf(buff, sizeof(buff), "MOVI V%d.%s, #0x%x", Rd, Vd, imm<<sh);
|
||||
return buff;
|
||||
}
|
||||
// MOV immediate shifted 16bits
|
||||
if(isMask(opcode, "0Q00111100000iii101001iiiiiddddd", &a)) {
|
||||
const char* Y[] = {"4H", "8H"};
|
||||
const char* Vd = Y[a.Q];
|
||||
|
||||
snprintf(buff, sizeof(buff), "MOVI V%d.%s, #0x%x", Rd, Vd, imm<<8);
|
||||
return buff;
|
||||
}
|
||||
|
||||
@@ -1034,7 +1067,30 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
if(!offset)
|
||||
snprintf(buff, sizeof(buff), "%s %c%d, [%s]", op?"STR":"LDR", s, Rt, XtSp[Rn]);
|
||||
else
|
||||
snprintf(buff, sizeof(buff), "%s %c%d, [%s, %d]", op?"STR":"LDR", s, Rt, XtSp[Rn], offset);
|
||||
snprintf(buff, sizeof(buff), "%s %c%d, [%s, 0x%x]", op?"STR":"LDR", s, Rt, XtSp[Rn], offset);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "ss111100cc1mmmmmoooS10nnnnnttttt", &a)) {
|
||||
char s = '?';
|
||||
int size=imms;
|
||||
int op=0;
|
||||
if(size==0 && opc==1) {s='B';}
|
||||
else if(size==1 && opc==1) {s='H';}
|
||||
else if(size==2 && opc==1) {s='S';}
|
||||
else if(size==3 && opc==1) {s='D';}
|
||||
else if(size==0 && opc==3) {s='Q'; size = 4;}
|
||||
else if(size==0 && opc==0) {s='B'; op=1;}
|
||||
else if(size==1 && opc==0) {s='H'; op=1;}
|
||||
else if(size==2 && opc==0) {s='S'; op=1;}
|
||||
else if(size==3 && opc==0) {s='D'; op=1;}
|
||||
else if(size==0 && opc==2) {s='Q'; op=1; size = 4;}
|
||||
|
||||
const char* extend[] = {"?0", "?1", "UXTW", "LSL", "?4", "?5", "SXTW", "SXTX"};
|
||||
int amount = size*a.S;
|
||||
if(option==3 && !amount)
|
||||
snprintf(buff, sizeof(buff), "%s %c%d, [%s, %s]", op?"STR":"LDR", s, Rt, XtSp[Rn], ((option&1)==0)?Wt[Rm]:Xt[Rm]);
|
||||
else
|
||||
snprintf(buff, sizeof(buff), "%s %c%d, [%s, %s, %s %d]", op?"STR":"LDR", s, Rt, XtSp[Rn], ((option&1)==0)?Wt[Rm]:Xt[Rm], extend[option], amount);
|
||||
return buff;
|
||||
}
|
||||
|
||||
@@ -1094,6 +1150,20 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
return buff;
|
||||
}
|
||||
|
||||
// FADDP
|
||||
if(isMask(opcode, "0Q1011100f1mmmmm110101nnnnnddddd", &a)) {
|
||||
char s = a.Q?'V':'D';
|
||||
char d = sf?'D':'S';
|
||||
int n = (a.Q && !sf)?4:2;
|
||||
snprintf(buff, sizeof(buff), "VFADDP %c%d.%d%c, %c%d.%d%c, %c%d.%d%c", s, Rd, n, d, s, Rn, n, d, s, Rm, n, d);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "011111100f110000110110nnnnnddddd", &a)) {
|
||||
char s = (sf==0)?'S':((sf==1)?'D':'?');
|
||||
snprintf(buff, sizeof(buff), "FADDP %c%d, %c%d, %c%d", s, Rd, s, Rn, s, Rm);
|
||||
return buff;
|
||||
}
|
||||
|
||||
// SQRT
|
||||
if(isMask(opcode, "0Q1011101f100001111110nnnnnddddd", &a)) {
|
||||
char s = a.Q?'V':'D';
|
||||
@@ -1107,7 +1177,19 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
snprintf(buff, sizeof(buff), "FSQRT %c%d, %c%d", s, Rd, s, Rn);
|
||||
return buff;
|
||||
}
|
||||
|
||||
// FPRINTX
|
||||
if(isMask(opcode, "0Q1011100f100001100110nnnnnddddd", &a)) {
|
||||
char s = a.Q?'V':'D';
|
||||
char d = sf?'D':'S';
|
||||
int n = (a.Q && !sf)?4:2;
|
||||
snprintf(buff, sizeof(buff), "VFRINTX %c%d.%d%c, %c%d.%d%c", s, Rd, n, d, s, Rn, n, d);
|
||||
return buff;
|
||||
}
|
||||
if (isMask(opcode, "00011110ff100111010000nnnnnddddd", &a)) {
|
||||
char s = (sf==0)?'S':((sf==1)?'D':'?');
|
||||
snprintf(buff, sizeof(buff), "FRINTX %c%d, %c%d", s, Rd, s, Rn);
|
||||
return buff;
|
||||
}
|
||||
// FRINTI
|
||||
if(isMask(opcode, "0Q1011101f100001100110nnnnnddddd", &a)) {
|
||||
char s = a.Q?'V':'D';
|
||||
@@ -1290,6 +1372,14 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
snprintf(buff, sizeof(buff), "FCVT%sS %s, %c%d", roundings[a.c], sf?Xt[Rd]:Wt[Rd], s, Rn);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "0QU01110of100001101o10nnnnnddddd", &a)) {
|
||||
const char* Y[] = {"2S", "4S", "??", "2D"};
|
||||
const char* Z[] = {"S", "S", "??", "D"};
|
||||
const char* Vd = Y[(sf<<1) | a.Q];
|
||||
const char* roundings[] = {"N", "M", "P", "Z"};
|
||||
snprintf(buff, sizeof(buff), "VFCVT%s%s%s%s V%d.%s, V%d.%s", roundings[option], a.U?"U":"S", a.Q?"Q":"", Z[(sf<<1)|a.Q], Rd, Vd, Rn, Vd);
|
||||
return buff;
|
||||
}
|
||||
|
||||
// FMOV
|
||||
if(isMask(opcode, "00011110pp100000010000nnnnnddddd", &a)) {
|
||||
@@ -1487,7 +1577,7 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
|
||||
// DUP
|
||||
if(isMask(opcode, "0Q001110000iiiii000001nnnnnddddd", &a)) {
|
||||
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "2D", "??"};
|
||||
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
|
||||
const char* Z[] = {"B", "H", "S", "D"};
|
||||
int sz = 3;
|
||||
if((imm&0b0001)==0b0001) sz=0;
|
||||
@@ -1499,7 +1589,18 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
snprintf(buff, sizeof(buff), "DUP V%d.%s, V%d.%s[%d]", Rd, Vd, Rn, Vn, sh);
|
||||
return buff;
|
||||
}
|
||||
|
||||
|
||||
if(isMask(opcode, "0Q001110000iiiii000011nnnnnddddd", &a)) {
|
||||
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
|
||||
int sz = 3;
|
||||
if((imm&0b0001)==0b0001) sz=0;
|
||||
else if((imm&0b0011)==0b0010) sz=1;
|
||||
else if((imm&0b0111)==0b0100) sz=2;
|
||||
const char* Vd = Y[(sz<<1)|a.Q];
|
||||
snprintf(buff, sizeof(buff), "DUP V%d.%s, X%d", Rd, Vd, Rn);
|
||||
return buff;
|
||||
}
|
||||
|
||||
// AES
|
||||
if(isMask(opcode, "0100111000101000010f10nnnnnddddd", &a)) {
|
||||
snprintf(buff, sizeof(buff), "AES%c V%d.16B, V%d.16B", sf?'D':'E', Rd, Rn);
|
||||
@@ -1525,7 +1626,139 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
snprintf(buff, sizeof(buff), "DMB %s", (Rn==0b1011)?"ISH":"???");
|
||||
return buff;
|
||||
}
|
||||
// DSB ISH/ISHST
|
||||
if(isMask(opcode, "11010101000000110011nnnn10011111", &a)) {
|
||||
snprintf(buff, sizeof(buff), "DSB %s", (Rn==0b1011)?"ISH":((Rn==0b1010)?"ISHST":"???"));
|
||||
return buff;
|
||||
}
|
||||
|
||||
// CASxw
|
||||
if(isMask(opcode, "1f0010001L1ssssso11111nnnnnttttt", &a)) {
|
||||
snprintf(buff, sizeof(buff), "CAS%s%s %s, %s, [%s]", a.o?"A":"", a.L?"L":"", sf?Xt[Rs]:Wt[Rs], sf?Xt[Rt]:Wt[Rt], XtSp[Rn]);
|
||||
return buff;
|
||||
}
|
||||
// CAS B/H
|
||||
if(isMask(opcode, "0f0010001L1ssssso11111nnnnnttttt", &a)) {
|
||||
snprintf(buff, sizeof(buff), "CAS%s%s%s %s, %s, [%s]", a.o?"A":"", a.L?"L":"", sf?"H":"B", Xt[Rs], Xt[Rt], XtSp[Rn]);
|
||||
return buff;
|
||||
}
|
||||
// CASPxw
|
||||
if(isMask(opcode, "0f0010000L1ssssso11111nnnnnttttt", &a)) {
|
||||
snprintf(buff, sizeof(buff), "CASP%s%s %s,%s, %s,%s, [%s]", a.o?"A":"", a.L?"L":"", sf?Xt[Rs]:Wt[Rs], sf?Xt[Rs+1]:Wt[Rs+1], sf?Xt[Rt]:Wt[Rt], sf?Xt[Rt+1]:Wt[Rt+1], XtSp[Rn]);
|
||||
return buff;
|
||||
}
|
||||
// SWPxw
|
||||
if(isMask(opcode, "1f111000AR1sssss100000nnnnnttttt", &a)) {
|
||||
snprintf(buff, sizeof(buff), "SWP%s%s %s, %s, [%s]", a.A?"A":"", a.R?"L":"", sf?Xt[Rs]:Wt[Rs], sf?Xt[Rt]:Wt[Rt], XtSp[Rn]);
|
||||
return buff;
|
||||
}
|
||||
// SWPxw
|
||||
if(isMask(opcode, "0f111000AR1sssss100000nnnnnttttt", &a)) {
|
||||
snprintf(buff, sizeof(buff), "CAS%s%s%s %s, %s, [%s]", a.A?"A":"", a.R?"L":"", sf?"H":"B", Xt[Rs], Xt[Rt], XtSp[Rn]);
|
||||
return buff;
|
||||
}
|
||||
// LDXXXxw
|
||||
if(isMask(opcode, "1f111000AR1sssss0ooo00nnnnnttttt", &a)) {
|
||||
const char* ops[] = { "ADD", "CLR", "EOR", "SET", "SMAX, SMIN", "UMAX", "UMIN" };
|
||||
if((Rt == 0b11111) && !a.A) {
|
||||
snprintf(buff, sizeof(buff), "ST%s%s %s, [%s]", ops[a.o], a.R?"L":"", sf?Xt[Rs]:Wt[Rs], XtSp[Rn]);
|
||||
} else {
|
||||
snprintf(buff, sizeof(buff), "LD%s%s%s %s, %s, [%s]", ops[a.o], a.A?"A":"", a.R?"L":"", sf?Xt[Rs]:Wt[Rs], sf?Xt[Rt]:Wt[Rt], XtSp[Rn]);
|
||||
}
|
||||
return buff;
|
||||
}
|
||||
// LDXXX B/H
|
||||
if(isMask(opcode, "0f111000AR1sssss0ooo00nnnnnttttt", &a)) {
|
||||
const char* ops[] = { "ADD", "CLR", "EOR", "SET", "SMAX, SMIN", "UMAX", "UMIN" };
|
||||
if((Rt == 0b11111) && !a.A) {
|
||||
snprintf(buff, sizeof(buff), "ST%s%s%s %s, [%s]", ops[a.o], a.R?"L":"", sf?"H":"B", Xt[Rs], XtSp[Rn]);
|
||||
} else {
|
||||
snprintf(buff, sizeof(buff), "LD%s%s%s%s %s, %s, [%s]", ops[a.o], a.A?"A":"", a.R?"L":"", sf?"H":"B", Xt[Rs], Xt[Rt], XtSp[Rn]);
|
||||
}
|
||||
return buff;
|
||||
}
|
||||
// AXFLAG
|
||||
if(isMask(opcode, "11010101000000000100000001011111", &a)) {
|
||||
snprintf(buff, sizeof(buff), "AXFLAG");
|
||||
return buff;
|
||||
}
|
||||
// XAFLAG
|
||||
if(isMask(opcode, "11010101000000000100000000111111", &a)) {
|
||||
snprintf(buff, sizeof(buff), "XAFLAG");
|
||||
return buff;
|
||||
}
|
||||
// CFINV
|
||||
if(isMask(opcode, "11010101000000000100000000011111", &a)) {
|
||||
snprintf(buff, sizeof(buff), "CFINV");
|
||||
return buff;
|
||||
}
|
||||
// RMIF
|
||||
if(isMask(opcode, "10111010000iiiiii00001nnnnn0oooo", &a)) {
|
||||
snprintf(buff, sizeof(buff), "RMIF %s, #%d, #0x%x", Xt[Rn], imm, opc);
|
||||
return buff;
|
||||
}
|
||||
// SETF
|
||||
if(isMask(opcode, "00111010000000000f0010nnnnn01101", &a)) {
|
||||
snprintf(buff, sizeof(buff), "SETF%d %s", 8<<sf, Xt[Rn]);
|
||||
return buff;
|
||||
}
|
||||
// REV64
|
||||
if(isMask(opcode, "0Q001110ff100000000010nnnnnddddd", &a)) {
|
||||
const char* T[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "??"};
|
||||
int sz = sf;
|
||||
const char* Vn = T[(sz<<1)|a.Q];
|
||||
const char* Vd = T[(sz<<1)|a.Q];
|
||||
snprintf(buff, sizeof(buff), "REV64 V%d.%s, V%d.%s",Rd, Vd, Rn, Vn);
|
||||
return buff;
|
||||
}
|
||||
//TRNx
|
||||
if(isMask(opcode, "0Q001110ff0mmmmm0o1010nnnnnddddd", &a)) {
|
||||
const char* T[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
|
||||
int sz = sf;
|
||||
const char* Vn = T[(sz<<1)|a.Q];
|
||||
const char* Vm = T[(sz<<1)|a.Q];
|
||||
const char* Vd = T[(sz<<1)|a.Q];
|
||||
snprintf(buff, sizeof(buff), "TRN%d V%d.%s, V%d.%s, V%d.%s", a.o+1, Rd, Vd, Rn, Vn, Rm, Vm);
|
||||
return buff;
|
||||
}
|
||||
//SHA1 stuffs
|
||||
if(isMask(opcode, "0101111000101000000010nnnnnddddd", &a)) {
|
||||
snprintf(buff, sizeof(buff), "SHA1H S%d, S%d", Rd, Rn);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "0101111000101000000110nnnnnddddd", &a)) {
|
||||
snprintf(buff, sizeof(buff), "SHA1SU1 V%d.4S, V%d.4S", Rd, Rn);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "01011110000mmmmm000000nnnnnddddd", &a)) {
|
||||
snprintf(buff, sizeof(buff), "SHA1C Q%d, S%d, V%d.4S", Rd, Rn, Rm);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "01011110000mmmmm001000nnnnnddddd", &a)) {
|
||||
snprintf(buff, sizeof(buff), "SHA1M Q%d, S%d, V%d.4S", Rd, Rn, Rm);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "01011110000mmmmm000100nnnnnddddd", &a)) {
|
||||
snprintf(buff, sizeof(buff), "SHA1P Q%d, S%d, V%d.4S", Rd, Rn, Rm);
|
||||
return buff;
|
||||
}
|
||||
//SHA256 stuffs
|
||||
if(isMask(opcode, "0101111000101000001010nnnnnddddd", &a)) {
|
||||
snprintf(buff, sizeof(buff), "SHA256SU0 V%d.4S, V%d.4S", Rd, Rn);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "01011110000mmmmm011000nnnnnddddd", &a)) {
|
||||
snprintf(buff, sizeof(buff), "SHA256SU1 V%d.4S, V%d.4S, V%d.4S", Rd, Rn, Rm);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "01011110000mmmmm010000nnnnnddddd", &a)) {
|
||||
snprintf(buff, sizeof(buff), "SHA256H Q%d, Q%d, V%d.4S", Rd, Rn, Rm);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "01011110000mmmmm010100nnnnnddddd", &a)) {
|
||||
snprintf(buff, sizeof(buff), "SHA256H2 Q%d, Q%d, V%d.4S", Rd, Rn, Rm);
|
||||
return buff;
|
||||
}
|
||||
|
||||
snprintf(buff, sizeof(buff), "%08X ???", __builtin_bswap32(opcode));
|
||||
return buff;
|
||||
|
||||
Executable → Regular
File mode changed.
Executable → Regular
+595
-270
File diff suppressed because it is too large.
Load diff
Executable → Regular
+686
-101
File diff suppressed because it is too large.
Load diff
@@ -58,6 +58,16 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x01:
|
||||
INST_NAME("ADD Seg:Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETEDO(x4, 0);
|
||||
emit_add32(dyn, ninst, rex, ed, gd, x3, x5);
|
||||
WBACKO(x4);
|
||||
break;
|
||||
case 0x03:
|
||||
INST_NAME("ADD Gd, Seg:Ed");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
@@ -223,8 +233,8 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
UFLAG_RES(gd);
|
||||
LSRx(x3, gd, 32);
|
||||
UFLAG_OP1(x3);
|
||||
UFLAG_DF(x3, d_imul32);
|
||||
MOVw_REG(gd, gd);
|
||||
UFLAG_DF(x3, d_imul32);
|
||||
} else {
|
||||
MULxw(gd, gd, ed);
|
||||
}
|
||||
@@ -268,6 +278,28 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x21:
|
||||
INST_NAME("AND Seg:Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETEDO(x4, 0);
|
||||
emit_and32(dyn, ninst, rex, ed, gd, x3, x5);
|
||||
WBACKO(x4);
|
||||
break;
|
||||
|
||||
case 0x29:
|
||||
INST_NAME("SUB Seg:Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETEDO(x4, 0);
|
||||
emit_sub32(dyn, ninst, rex, ed, gd, x3, x5);
|
||||
WBACKO(x4);
|
||||
break;
|
||||
|
||||
case 0x2B:
|
||||
INST_NAME("SUB Gd, Seg:Ed");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
@@ -278,6 +310,17 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
emit_sub32(dyn, ninst, rex, gd, ed, x3, x4);
|
||||
break;
|
||||
|
||||
case 0x31:
|
||||
INST_NAME("XOR Seg:Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETEDO(x4, 0);
|
||||
emit_xor32(dyn, ninst, rex, ed, gd, x3, x5);
|
||||
WBACKO(x4);
|
||||
break;
|
||||
|
||||
case 0x33:
|
||||
INST_NAME("XOR Gd, Seg:Ed");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
@@ -337,10 +380,22 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x64:
|
||||
addr = dynarec64_64(dyn, addr, ip, ninst, rex, rep, _FS, ok, need_epilog);
|
||||
break;
|
||||
case 0x65:
|
||||
addr = dynarec64_64(dyn, addr, ip, ninst, rex, rep, _GS, ok, need_epilog);
|
||||
break;
|
||||
case 0x66:
|
||||
addr = dynarec64_6664(dyn, addr, ip, ninst, rex, seg, ok, need_epilog);
|
||||
break;
|
||||
case 0x67:
|
||||
if(rex.is32bits)
|
||||
addr = dynarec64_6764_32(dyn, addr, ip, ninst, rex, rep, seg, ok, need_epilog);
|
||||
else {
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x80:
|
||||
nextop = F8;
|
||||
@@ -514,7 +569,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
gd = (nextop&0x38)>>3;
|
||||
gb1 = xRAX+(gd&3);
|
||||
gb2 = ((gd&4)>>2);
|
||||
gb2 = ((gd&4)<<1);
|
||||
}
|
||||
if(MODREG) {
|
||||
if(rex.rex) {
|
||||
@@ -538,7 +593,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
LDRB_REG(x4, wback, x4);
|
||||
ed = x4;
|
||||
}
|
||||
BFIx(gb1, ed, gb2*8, 8);
|
||||
BFIx(gb1, ed, gb2, 8);
|
||||
break;
|
||||
case 0x89:
|
||||
INST_NAME("MOV Seg:Ed, Gd");
|
||||
@@ -584,7 +639,22 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x8E:
|
||||
INST_NAME("MOV Seg,Ew");
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
nextop = F8;
|
||||
u8 = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
|
||||
LDRH_REG(x1, wback, x4);
|
||||
ed = x1;
|
||||
}
|
||||
STRH_U12(ed, xEmu, offsetof(x64emu_t, segs[u8]));
|
||||
STRw_U12(wZR, xEmu, offsetof(x64emu_t, segs_serial[u8]));
|
||||
break;
|
||||
case 0x8F:
|
||||
INST_NAME("POP FS:Ed");
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
@@ -604,6 +674,9 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x90:
|
||||
INST_NAME("NOP");
|
||||
break;
|
||||
|
||||
case 0xA1:
|
||||
INST_NAME("MOV EAX,FS:Od");
|
||||
@@ -884,7 +957,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
GETEDO(x6, 4);
|
||||
i64 = F32S;
|
||||
MOV64xw(x2, i64);
|
||||
emit_test32(dyn, ninst, rex, ed, x2, x3, x4);
|
||||
emit_test32(dyn, ninst, rex, ed, x2, x3, x4, x5);
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("NOT Ed");
|
||||
@@ -902,7 +975,6 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 4:
|
||||
INST_NAME("MUL EAX, Ed");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
UFLAG_DF(x2, rex.w?d_mul64:d_mul32);
|
||||
GETEDO(x6, 0);
|
||||
if(rex.w) {
|
||||
if(ed==xRDX) gd=x3; else gd=xRDX;
|
||||
@@ -916,11 +988,11 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
UFLAG_RES(xRAX);
|
||||
UFLAG_OP1(xRDX);
|
||||
UFLAG_DF(x2, rex.w?d_mul64:d_mul32);
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("IMUL EAX, Ed");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
UFLAG_DF(x2, rex.w?d_imul64:d_imul32);
|
||||
GETEDO(x6, 0);
|
||||
if(rex.w) {
|
||||
if(ed==xRDX) gd=x3; else gd=xRDX;
|
||||
@@ -934,6 +1006,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
UFLAG_RES(xRAX);
|
||||
UFLAG_OP1(xRDX);
|
||||
UFLAG_DF(x2, rex.w?d_imul64:d_imul32);
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("DIV Ed");
|
||||
@@ -1048,6 +1121,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
GETEDOz(x6, 0);
|
||||
if(box64_dynarec_callret && box64_dynarec_bigblock>1) {
|
||||
BARRIER(BARRIER_FULL);
|
||||
BARRIER_NEXT(BARRIER_FULL);
|
||||
} else {
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
*need_epilog = 0;
|
||||
@@ -1055,12 +1129,15 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
GETIP_(addr);
|
||||
if(box64_dynarec_callret) {
|
||||
SET_HASCALLRET();
|
||||
// Push actual return address
|
||||
if(addr < (dyn->start+dyn->isize)) {
|
||||
// there is a next...
|
||||
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->native_size)):0;
|
||||
ADR_S20(x4, j64);
|
||||
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2);
|
||||
} else {
|
||||
MESSAGE(LOG_NONE, "\tCALLRET set return to Jmptable(%p)\n", (void*)addr);
|
||||
j64 = getJumpTableAddress64(addr);
|
||||
TABLE64(x4, j64);
|
||||
LDRx_U12(x4, x4, 0);
|
||||
|
||||
Executable → Regular
+401
-155
@@ -15,6 +15,7 @@
|
||||
#include "emu/x64run_private.h"
|
||||
#include "x64trace.h"
|
||||
#include "dynarec_native.h"
|
||||
#include "custommem.h"
|
||||
|
||||
#include "arm64_printer.h"
|
||||
#include "dynarec_arm64_private.h"
|
||||
@@ -42,7 +43,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
MAYUSE(j64);
|
||||
MAYUSE(lock);
|
||||
|
||||
while((opcode==0x2E) || (opcode==0x36) || (opcode==0x66)) // ignoring CS:, SS: or multiple 0x66
|
||||
while((opcode==0x2E) || (opcode==0x36) || (opcode==0x26) || (opcode==0x66)) // ignoring CS:, SS:, ES: or multiple 0x66
|
||||
opcode = F8;
|
||||
|
||||
while((opcode==0xF2) || (opcode==0xF3)) {
|
||||
@@ -82,6 +83,25 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
emit_add16(dyn, ninst, x1, x2, x3, x4);
|
||||
BFIx(xRAX, x1, 0, 16);
|
||||
break;
|
||||
case 0x06:
|
||||
if(rex.is32bits) {
|
||||
INST_NAME("PUSH ES");
|
||||
LDRH_U12(x1, xEmu, offsetof(x64emu_t, segs[_ES]));
|
||||
PUSH1_32(x1);
|
||||
} else {
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
case 0x07:
|
||||
if(rex.is32bits) {
|
||||
INST_NAME("POP ES");
|
||||
POP1_32(x1);
|
||||
STRH_U12(x1, xEmu, offsetof(x64emu_t, segs[_ES]));
|
||||
STRw_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_ES]));
|
||||
} else {
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x09:
|
||||
INST_NAME("OR Ew, Gw");
|
||||
@@ -112,7 +132,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
|
||||
case 0x0F:
|
||||
addr = dynarec64_660F(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
|
||||
switch(rep) {
|
||||
case 0: addr = dynarec64_660F(dyn, addr, ip, ninst, rex, ok, need_epilog); break;
|
||||
case 1: addr = dynarec64_66F20F(dyn, addr, ip, ninst, rex, ok, need_epilog); break;
|
||||
case 2: addr = dynarec64_66F30F(dyn, addr, ip, ninst, rex, ok, need_epilog); break;
|
||||
}
|
||||
break;
|
||||
case 0x11:
|
||||
INST_NAME("ADC Ew, Gw");
|
||||
@@ -175,6 +199,25 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
emit_sbb16(dyn, ninst, x1, x2, x3, x4);
|
||||
BFIx(xRAX, x1, 0, 16);
|
||||
break;
|
||||
case 0x1E:
|
||||
if(rex.is32bits) {
|
||||
INST_NAME("PUSH DS");
|
||||
LDRH_U12(x1, xEmu, offsetof(x64emu_t, segs[_DS]));
|
||||
PUSH1_32(x1);
|
||||
} else {
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
case 0x1F:
|
||||
if(rex.is32bits) {
|
||||
INST_NAME("POP DS");
|
||||
POP1_32(x1);
|
||||
STRH_U12(x1, xEmu, offsetof(x64emu_t, segs[_DS]));
|
||||
STRw_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_DS]));
|
||||
} else {
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x21:
|
||||
INST_NAME("AND Ew, Gw");
|
||||
@@ -319,35 +362,78 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
emit_dec16(dyn, ninst, x1, x2, x3);
|
||||
BFIw(gd, x1, 0, 16);
|
||||
break;
|
||||
|
||||
case 0x50:
|
||||
case 0x51:
|
||||
case 0x52:
|
||||
case 0x53:
|
||||
case 0x54:
|
||||
case 0x55:
|
||||
case 0x56:
|
||||
case 0x57:
|
||||
if(rex.is32bits) {
|
||||
INST_NAME("PUSH reg");
|
||||
gd = xRAX+(opcode&0x07);
|
||||
if (gd==xRSP) {
|
||||
MOVw_REG(x1, xRSP);
|
||||
PUSH1_16(x1);
|
||||
} else {
|
||||
PUSH1_16(gd);
|
||||
}
|
||||
} else {
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
case 0x58:
|
||||
case 0x59:
|
||||
case 0x5A:
|
||||
case 0x5B:
|
||||
case 0x5C:
|
||||
case 0x5D:
|
||||
case 0x5E:
|
||||
case 0x5F:
|
||||
if(rex.is32bits) {
|
||||
INST_NAME("POP reg");
|
||||
gd = xRAX+(opcode&0x07);
|
||||
POP1_16(x1);
|
||||
BFIw(gd, x1, 0, 16);
|
||||
} else {
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
case 0x60:
|
||||
if(rex.is32bits) {
|
||||
INST_NAME("PUSHA 16 (32bits)");
|
||||
INST_NAME("PUSHA 16bits (32bits)");
|
||||
MOVw_REG(x1, xRSP);
|
||||
STRH_S9_preindex(xRAX, xRSP, -2);
|
||||
STRH_S9_preindex(xRCX, xRSP, -2);
|
||||
STRH_S9_preindex(xRDX, xRSP, -2);
|
||||
STRH_S9_preindex(xRBX, xRSP, -2);
|
||||
STRH_S9_preindex(x1, xRSP, -2);
|
||||
STRH_S9_preindex(xRBP, xRSP, -2);
|
||||
STRH_S9_preindex(xRSI, xRSP, -2);
|
||||
STRH_S9_preindex(xRDI, xRSP, -2);
|
||||
PUSH1_16(xRAX);
|
||||
PUSH1_16(xRCX);
|
||||
PUSH1_16(xRDX);
|
||||
PUSH1_16(xRBX);
|
||||
PUSH1_16(x1);
|
||||
PUSH1_16(xRBP);
|
||||
PUSH1_16(xRSI);
|
||||
PUSH1_16(xRDI);
|
||||
} else {
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
case 0x61:
|
||||
if(rex.is32bits) {
|
||||
INST_NAME("POPA 16 (32bits)");
|
||||
MOVw_REG(x1, xRSP);
|
||||
LDRH_S9_postindex(xRDI, xRSP, 2);
|
||||
LDRH_S9_postindex(xRSI, xRSP, 2);
|
||||
LDRH_S9_postindex(xRBP, xRSP, 2);
|
||||
LDRH_S9_postindex(x1, xRSP, 2);
|
||||
LDRH_S9_postindex(xRBX, xRSP, 2);
|
||||
LDRH_S9_postindex(xRDX, xRSP, 2);
|
||||
LDRH_S9_postindex(xRCX, xRSP, 2);
|
||||
LDRH_S9_postindex(xRAX, xRSP, 2);
|
||||
INST_NAME("POPA 16bits (32bits)");
|
||||
POP1_16(x1);
|
||||
BFIw(xRDI, x1, 0, 16);
|
||||
POP1_16(x1);
|
||||
BFIw(xRSI, x1, 0, 16);
|
||||
POP1_16(x1);
|
||||
BFIw(xRBP, x1, 0, 16);
|
||||
POP1_16(x1); // RSP ignored
|
||||
POP1_16(x1);
|
||||
BFIw(xRBX, x1, 0, 16);
|
||||
POP1_16(x1);
|
||||
BFIw(xRDX, x1, 0, 16);
|
||||
POP1_16(x1);
|
||||
BFIw(xRCX, x1, 0, 16);
|
||||
POP1_16(x1);
|
||||
BFIw(xRAX, x1, 0, 16);
|
||||
} else {
|
||||
DEFAULT;
|
||||
}
|
||||
@@ -372,7 +458,6 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
nextop = F8;
|
||||
UFLAG_DF(x1, d_imul16);
|
||||
GETSEW(x1, (opcode==0x69)?2:1);
|
||||
if(opcode==0x69) i32 = F16S; else i32 = F8S;
|
||||
MOV32w(x2, i32);
|
||||
@@ -380,6 +465,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
UFLAG_RES(x2);
|
||||
gd=x2;
|
||||
GWBACK;
|
||||
UFLAG_DF(x1, d_imul16);
|
||||
break;
|
||||
|
||||
case 0x70:
|
||||
@@ -505,19 +591,36 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
GETGD;
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
SMDMB();
|
||||
TSTx_mask(ed, 1, 0, 0); // mask=1
|
||||
B_MARK(cNE);
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, ed);
|
||||
STLXRH(x3, gd, ed);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
B_MARK2_nocond;
|
||||
MARK;
|
||||
LDRH_U12(x1, ed, 0);
|
||||
STRH_U12(gd, ed, 0);
|
||||
MARK2;
|
||||
SMDMB();
|
||||
if(!ALIGNED_ATOMICH) {
|
||||
TSTx_mask(ed, 1, 0, 0); // mask=1
|
||||
B_MARK(cNE);
|
||||
}
|
||||
if(arm64_atomics) {
|
||||
SWPALH(gd, x1, ed);
|
||||
SMDMB();
|
||||
if(!ALIGNED_ATOMICH) {
|
||||
B_MARK2_nocond;
|
||||
}
|
||||
} else {
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, ed);
|
||||
STLXRH(x3, gd, ed);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
SMDMB();
|
||||
if(!ALIGNED_ATOMICH) {
|
||||
B_MARK2_nocond;
|
||||
}
|
||||
}
|
||||
if(!ALIGNED_ATOMICH) {
|
||||
MARK;
|
||||
LDRH_U12(x1, ed, 0);
|
||||
LDAXRB(x3, ed);
|
||||
STLXRB(x3, gd, ed);
|
||||
CBNZx_MARK(x3);
|
||||
STRH_U12(gd, ed, 0);
|
||||
SMDMB();
|
||||
MARK2;
|
||||
}
|
||||
BFIx(gd, x1, 0, 16);
|
||||
}
|
||||
break;
|
||||
@@ -557,7 +660,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("MOV EW, Seg");
|
||||
nextop=F8;
|
||||
u8 = (nextop&0x38)>>3;
|
||||
LDRw_U12(x3, xEmu, offsetof(x64emu_t, segs[u8]));
|
||||
LDRH_U12(x3, xEmu, offsetof(x64emu_t, segs[u8]));
|
||||
if((nextop&0xC0)==0xC0) { // reg <= seg
|
||||
UXTHw(xRAX+(nextop&7)+(rex.b<<3), x3);
|
||||
} else { // mem <= seg
|
||||
@@ -567,6 +670,22 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x8E:
|
||||
INST_NAME("MOV Seg,Ew");
|
||||
nextop = F8;
|
||||
u8 = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
|
||||
LDH(x1, wback, fixedaddress);
|
||||
ed = x1;
|
||||
}
|
||||
STRH_U12(ed, xEmu, offsetof(x64emu_t, segs[u8]));
|
||||
STRw_U12(wZR, xEmu, offsetof(x64emu_t, segs_serial[u8]));
|
||||
break;
|
||||
|
||||
case 0x90:
|
||||
case 0x91:
|
||||
case 0x92:
|
||||
@@ -589,7 +708,34 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0x98:
|
||||
INST_NAME("CBW");
|
||||
SXTBw(x1, xRAX);
|
||||
BFIw(xRAX, x1, 0, 16);
|
||||
BFIx(xRAX, x1, 0, 16);
|
||||
break;
|
||||
case 0x99:
|
||||
INST_NAME("CWD");
|
||||
SXTHw(x1, xRAX);
|
||||
BFXILx(xRDX, x1, 16, 16);
|
||||
break;
|
||||
case 0x9C:
|
||||
INST_NAME("PUSHF");
|
||||
READFLAGS(X_ALL);
|
||||
PUSH1_16(xFlags);
|
||||
break;
|
||||
case 0x9D:
|
||||
INST_NAME("POPF");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
POP1_16(x1); // probably not usefull...
|
||||
BFIw(xFlags, x1, 0, 16);
|
||||
MOV32w(x1, 0x3F7FD7);
|
||||
ANDw_REG(xFlags, xFlags, x1);
|
||||
ORRw_mask(xFlags, xFlags, 0b011111, 0); //mask=0x00000002
|
||||
SET_DFNONE(x1);
|
||||
if(box64_wine) { // should this be done all the time?
|
||||
TBZ_NEXT(xFlags, F_TF);
|
||||
MOV64x(x1, addr);
|
||||
STORE_XEMU_CALL(x1);
|
||||
CALL(native_singlestep, -1);
|
||||
BFCw(xFlags, F_TF, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xA1:
|
||||
@@ -599,6 +745,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
else
|
||||
u64 = F64;
|
||||
MOV64z(x1, u64);
|
||||
if(isLockAddress(u64)) lock=1; else lock = 0;
|
||||
SMREADLOCK(lock);
|
||||
LDRH_U12(x2, x1, 0);
|
||||
BFIx(xRAX, x2, 0, 16);
|
||||
break;
|
||||
@@ -610,8 +758,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
else
|
||||
u64 = F64;
|
||||
MOV64z(x1, u64);
|
||||
if(isLockAddress(u64)) lock=1; else lock = 0;
|
||||
STRH_U12(xRAX, x1, 0);
|
||||
SMWRITE();
|
||||
SMWRITELOCK(lock);
|
||||
break;
|
||||
|
||||
case 0xA5:
|
||||
@@ -719,20 +868,23 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
CBZx_NEXT(xRCX);
|
||||
TBNZ_MARK2(xFlags, F_DF);
|
||||
MARK; // Part with DF==0
|
||||
LDRH_S9_postindex(xRAX, xRSI, 2);
|
||||
LDRH_S9_postindex(x2, xRSI, 2);
|
||||
SUBx_U12(xRCX, xRCX, 1);
|
||||
CBNZx_MARK(xRCX);
|
||||
B_NEXT_nocond;
|
||||
B_MARK3_nocond;
|
||||
MARK2; // Part with DF==1
|
||||
LDRH_S9_postindex(xRAX, xRSI, -2);
|
||||
LDRH_S9_postindex(x2, xRSI, -2);
|
||||
SUBx_U12(xRCX, xRCX, 1);
|
||||
CBNZx_MARK2(xRCX);
|
||||
MARK3;
|
||||
BFIx(xRAX, x2, 0, 16);
|
||||
// done
|
||||
} else {
|
||||
INST_NAME("STOSW");
|
||||
INST_NAME("LODSW");
|
||||
GETDIR(x3, 2);
|
||||
LDRH_U12(xRAX, xRSI, 0);
|
||||
LDRH_U12(x2, xRSI, 0);
|
||||
ADDx_REG(xRSI, xRSI, x3);
|
||||
BFIx(xRAX, x2, 0, 16);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -794,23 +946,29 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("ROL Ew, Ib");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
GETEW(x1, 1);
|
||||
u8 = F8;
|
||||
MOV32w(x2, u8);
|
||||
CALL_(rol16, x1, x3);
|
||||
EWBACK;
|
||||
if(geted_ib(dyn, addr, ninst, nextop)&15) {
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
|
||||
GETEW(x1, 1);
|
||||
u8 = F8;
|
||||
emit_rol16c(dyn, ninst, x1, u8&15, x4, x5);
|
||||
EWBACK;
|
||||
} else {
|
||||
FAKEED;
|
||||
F8;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("ROR Ew, Ib");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
GETEW(x1, 1);
|
||||
u8 = F8;
|
||||
MOV32w(x2, u8);
|
||||
CALL_(ror16, x1, x3);
|
||||
EWBACK;
|
||||
if(geted_ib(dyn, addr, ninst, nextop)&15) {
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
|
||||
GETEW(x1, 1);
|
||||
u8 = F8;
|
||||
emit_ror16c(dyn, ninst, x1, u8&15, x4, x5);
|
||||
EWBACK;
|
||||
} else {
|
||||
FAKEED;
|
||||
F8;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("RCL Ew, Ib");
|
||||
@@ -837,42 +995,42 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 4:
|
||||
case 6:
|
||||
INST_NAME("SHL Ew, Ib");
|
||||
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
GETEW(x1, 1);
|
||||
u8 = F8;
|
||||
UFLAG_IF {MOV32w(x2, (u8&0x1f));}
|
||||
UFLAG_OP12(ed, x2)
|
||||
LSLw_IMM(ed, ed, u8&0x1f);
|
||||
EWBACK;
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_shl16);
|
||||
if(geted_ib(dyn, addr, ninst, nextop)&0x1f) {
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
GETEW(x1, 0);
|
||||
u8 = (F8)&0x1f;
|
||||
emit_shl16c(dyn, ninst, x1, u8, x5, x4);
|
||||
EWBACK;
|
||||
} else {
|
||||
FAKEED;
|
||||
F8;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("SHR Ed, Ib");
|
||||
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
GETEW(x1, 1);
|
||||
u8 = F8;
|
||||
UFLAG_IF {MOV32w(x2, (u8&0x1f));}
|
||||
UFLAG_OP12(ed, x2)
|
||||
LSRw_IMM(ed, ed, u8&0x1f);
|
||||
EWBACK;
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_shr16);
|
||||
if(geted_ib(dyn, addr, ninst, nextop)&0x1f) {
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
GETEW(x1, 0);
|
||||
u8 = (F8)&0x1f;
|
||||
emit_shr16c(dyn, ninst, x1, u8, x5, x4);
|
||||
EWBACK;
|
||||
} else {
|
||||
FAKEED;
|
||||
F8;
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("SAR Ed, Ib");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
|
||||
GETSEW(x1, 1);
|
||||
u8 = F8;
|
||||
UFLAG_IF {MOV32w(x2, (u8&0x1f));}
|
||||
UFLAG_OP12(ed, x2)
|
||||
ASRw(ed, ed, (u8&0x1f));
|
||||
EWBACK;
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_sar16);
|
||||
if(geted_ib(dyn, addr, ninst, nextop)&0x1f) {
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
GETSEW(x1, 0);
|
||||
u8 = (F8)&0x1f;
|
||||
emit_sar16c(dyn, ninst, x1, u8, x5, x4);
|
||||
EWBACK;
|
||||
} else {
|
||||
FAKEED;
|
||||
F8;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -895,108 +1053,186 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
|
||||
case 0xD1:
|
||||
case 0xD3:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
if(opcode==0xD1) {
|
||||
INST_NAME("ROL Ew, 1");
|
||||
MOV32w(x2, 1);
|
||||
} else {
|
||||
INST_NAME("ROL Ew, CL");
|
||||
ANDw_mask(x2, xRCX, 0, 0b00100);
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
INST_NAME("ROL Ew, 1");
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
|
||||
GETEW(x1, 0);
|
||||
CALL_(rol16, x1, x3);
|
||||
emit_rol16c(dyn, ninst, x1, 1, x5, x4);
|
||||
EWBACK;
|
||||
break;
|
||||
case 1:
|
||||
if(opcode==0xD1) {
|
||||
INST_NAME("ROR Ew, 1");
|
||||
MOV32w(x2, 1);
|
||||
} else {
|
||||
INST_NAME("ROR Ew, CL");
|
||||
ANDw_mask(x2, xRCX, 0, 0b00100);
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
INST_NAME("ROR Ew, 1");
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
|
||||
GETEW(x1, 0);
|
||||
CALL_(ror16, x1, x3);
|
||||
emit_ror16c(dyn, ninst, x1, 1, x5, x4);
|
||||
EWBACK;
|
||||
break;
|
||||
case 2:
|
||||
if(opcode==0xD1) {INST_NAME("RCL Ew, 1"); } else { INST_NAME("RCL Ew, CL");}
|
||||
INST_NAME("RCL Ew, 1");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
if(opcode==0xD1) {MOV32w(x2, 1);} else {ANDw_mask(x2, xRCX, 0, 0b00100);}
|
||||
MOV32w(x2, 1);
|
||||
GETEW(x1, 0);
|
||||
CALL_(rcl16, x1, x3);
|
||||
EWBACK;
|
||||
break;
|
||||
case 3:
|
||||
if(opcode==0xD1) {INST_NAME("RCR Ew, 1");} else {INST_NAME("RCR Ew, CL");}
|
||||
INST_NAME("RCR Ew, 1");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
if(opcode==0xD1) {MOV32w(x2, 1);} else {ANDw_mask(x2, xRCX, 0, 0b00100);}
|
||||
MOV32w(x2, 1);
|
||||
GETEW(x1, 0);
|
||||
CALL_(rcr16, x1, x3);
|
||||
EWBACK;
|
||||
break;
|
||||
case 4:
|
||||
case 6:
|
||||
if(opcode==0xD1) {
|
||||
INST_NAME("SHL Ew, 1");
|
||||
MOV32w(x4, 1);
|
||||
} else {
|
||||
INST_NAME("SHL Ew, CL");
|
||||
ANDw_mask(x4, xRCX, 0, 0b00100);
|
||||
}
|
||||
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
INST_NAME("SHL Ew, 1");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
GETEW(x1, 0);
|
||||
UFLAG_OP12(ed, x4)
|
||||
LSLw_REG(ed, ed, x4);
|
||||
emit_shl16c(dyn, ninst, x1, 1, x5, x4);
|
||||
EWBACK;
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_shl16);
|
||||
break;
|
||||
case 5:
|
||||
if(opcode==0xD1) {
|
||||
INST_NAME("SHR Ew, 1");
|
||||
MOV32w(x4, 1);
|
||||
} else {
|
||||
INST_NAME("SHR Ew, CL");
|
||||
ANDw_mask(x4, xRCX, 0, 0b00100);
|
||||
}
|
||||
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
INST_NAME("SHR Ew, 1");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
GETEW(x1, 0);
|
||||
UFLAG_OP12(ed, x4)
|
||||
LSRw_REG(ed, ed, x4);
|
||||
emit_shr16c(dyn, ninst, x1, 1, x5, x4);
|
||||
EWBACK;
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_shr16);
|
||||
break;
|
||||
case 7:
|
||||
if(opcode==0xD1) {
|
||||
INST_NAME("SAR Ew, 1");
|
||||
MOV32w(x4, 1);
|
||||
} else {
|
||||
INST_NAME("SAR Ew, CL");
|
||||
ANDw_mask(x4, xRCX, 0, 0b00100);
|
||||
}
|
||||
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
INST_NAME("SAR Ew, 1");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
GETSEW(x1, 0);
|
||||
UFLAG_OP12(ed, x4)
|
||||
ASRw_REG(ed, ed, x4);
|
||||
emit_sar16c(dyn, ninst, x1, 1, x5, x4);
|
||||
EWBACK;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xD3:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("ROL Ew, CL");
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET);
|
||||
if(box64_dynarec_safeflags>1)
|
||||
MAYSETFLAGS();
|
||||
UFLAG_IF {
|
||||
TSTw_mask(xRCX, 0, 0b00100); //mask=0x00000001f
|
||||
B_NEXT(cEQ);
|
||||
}
|
||||
ANDw_mask(x2, xRCX, 0, 0b00011); //mask=0x00000000f
|
||||
MOV32w(x4, 16);
|
||||
SUBx_REG(x2, x4, x2);
|
||||
GETEW(x1, 0);
|
||||
ORRw_REG_LSL(ed, ed, ed, 16);
|
||||
LSRw_REG(ed, ed, x2);
|
||||
EWBACK;
|
||||
UFLAG_IF { // calculate flags directly
|
||||
CMPSw_U12(x2, 15);
|
||||
B_MARK(cNE);
|
||||
ADDxw_REG_LSR(x3, ed, ed, 15);
|
||||
BFIw(xFlags, x3, F_OF, 1);
|
||||
MARK;
|
||||
BFIw(xFlags, ed, F_CF, 1);
|
||||
UFLAG_DF(x2, d_none);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("ROR Ew, CL");
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET);
|
||||
if(box64_dynarec_safeflags>1)
|
||||
MAYSETFLAGS();
|
||||
UFLAG_IF {
|
||||
TSTw_mask(xRCX, 0, 0b00100); //mask=0x00000001f
|
||||
B_NEXT(cEQ);
|
||||
}
|
||||
ANDw_mask(x2, xRCX, 0, 0b00011); //mask=0x00000000f
|
||||
GETEW(x1, 0);
|
||||
ORRw_REG_LSL(ed, ed, ed, 16);
|
||||
LSRw_REG(ed, ed, x2);
|
||||
EWBACK;
|
||||
UFLAG_IF { // calculate flags directly
|
||||
CMPSw_U12(x2, 1);
|
||||
B_MARK(cNE);
|
||||
LSRxw(x2, ed, 14); // x2 = d>>14
|
||||
EORw_REG_LSR(x2, x2, x2, 1); // x2 = ((d>>14) ^ ((d>>14)>>1))
|
||||
BFIw(xFlags, x2, F_OF, 1);
|
||||
MARK;
|
||||
BFXILw(xFlags, ed, 15, 1);
|
||||
UFLAG_DF(x2, d_none);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("RCL Ew, CL");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
ANDw_mask(x2, xRCX, 0, 0b00100);
|
||||
GETEW(x1, 0);
|
||||
CALL_(rcl16, x1, x3);
|
||||
EWBACK;
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("RCR Ew, CL");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
ANDw_mask(x2, xRCX, 0, 0b00100);
|
||||
GETEW(x1, 0);
|
||||
CALL_(rcr16, x1, x3);
|
||||
EWBACK;
|
||||
break;
|
||||
case 4:
|
||||
case 6:
|
||||
INST_NAME("SHL Ew, CL");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
if(box64_dynarec_safeflags>1)
|
||||
MAYSETFLAGS();
|
||||
UFLAG_IF {
|
||||
ANDSw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
|
||||
B_NEXT(cEQ);
|
||||
} else {
|
||||
ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
|
||||
}
|
||||
GETEW(x1, 0);
|
||||
emit_shl16(dyn, ninst, x1, x2, x5, x4);
|
||||
EWBACK;
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("SHR Ew, CL");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
if(box64_dynarec_safeflags>1)
|
||||
MAYSETFLAGS();
|
||||
UFLAG_IF {
|
||||
ANDSw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
|
||||
B_NEXT(cEQ);
|
||||
} else {
|
||||
ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
|
||||
}
|
||||
GETEW(x1, 0);
|
||||
emit_shr16(dyn, ninst, x1, x2, x5, x4);
|
||||
EWBACK;
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("SAR Ew, CL");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
if(box64_dynarec_safeflags>1)
|
||||
MAYSETFLAGS();
|
||||
UFLAG_IF {
|
||||
ANDSw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
|
||||
B_NEXT(cEQ);
|
||||
} else {
|
||||
ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
|
||||
}
|
||||
GETSEW(x1, 0);
|
||||
emit_sar16(dyn, ninst, x1, x2, x5, x4);
|
||||
EWBACK;
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_sar16);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -1032,24 +1268,24 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 4:
|
||||
INST_NAME("MUL AX, Ew");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
UFLAG_DF(x1, d_mul16);
|
||||
GETEW(x1, 0);
|
||||
UXTHw(x2, xRAX);
|
||||
MULw(x1, x2, x1);
|
||||
UFLAG_RES(x1);
|
||||
BFIx(xRAX, x1, 0, 16);
|
||||
BFXILx(xRDX, x1, 16, 16);
|
||||
UFLAG_DF(x1, d_mul16);
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("IMUL AX, Ew");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
UFLAG_DF(x1, d_imul16);
|
||||
GETSEW(x1, 0);
|
||||
SXTHw(x2, xRAX);
|
||||
MULw(x1, x2, x1);
|
||||
UFLAG_RES(x1);
|
||||
BFIx(xRAX, x1, 0, 16);
|
||||
BFXILx(xRDX, x1, 16, 16);
|
||||
UFLAG_DF(x1, d_imul16);
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("DIV Ew");
|
||||
@@ -1064,7 +1300,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("IDIV Ew");
|
||||
NOTEST(x1);
|
||||
SKIPTEST(x1);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
GETSEW(x1, 0);
|
||||
UXTHw(x2, xRAX);
|
||||
@@ -1094,6 +1330,16 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
emit_dec16(dyn, ninst, x1, x2, x4);
|
||||
EWBACK;
|
||||
break;
|
||||
case 6: // Push Ew
|
||||
if(rex.is32bits) {
|
||||
INST_NAME("PUSH Ew");
|
||||
GETEW(x1, 0);
|
||||
PUSH1_16(ed);
|
||||
} else {
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
|
||||
Executable → Regular
+540
-114
@@ -20,10 +20,11 @@
|
||||
#include "dynarec_arm64_private.h"
|
||||
#include "dynarec_arm64_functions.h"
|
||||
#include "dynarec_arm64_helper.h"
|
||||
#include "emu/x64compstrings.h"
|
||||
|
||||
uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)rep; (void)need_epilog;
|
||||
(void)ip; (void)need_epilog;
|
||||
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop, u8;
|
||||
@@ -48,6 +49,8 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
MAYUSE(j64);
|
||||
#if STEP > 1
|
||||
static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
|
||||
static const int8_t mask_string8[] = { 7, 6, 5, 4, 3, 2, 1, 0 };
|
||||
static const int8_t mask_string16[] = { 15, 14, 13, 12, 11, 10, 9, 8 };
|
||||
static const int8_t round_round[] = { 0, 2, 1, 3};
|
||||
#endif
|
||||
|
||||
@@ -169,7 +172,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
nextop = F8;
|
||||
FAKEED;
|
||||
break;
|
||||
|
||||
|
||||
case 0x28:
|
||||
INST_NAME("MOVAPD Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -201,7 +204,92 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x2A:
|
||||
INST_NAME("CVTPI2PD Gx,Em");
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
GETEM(q1, 0);
|
||||
SXTL_32(v0, q1);
|
||||
SCVTQFD(v0, v0);
|
||||
break;
|
||||
case 0x2B:
|
||||
INST_NAME("MOVNTPD Ex,Gx");
|
||||
nextop = F8;
|
||||
GETGX(v0, 0);
|
||||
if(MODREG) {
|
||||
ed = (nextop&7)+(rex.b<<3);
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, ed);
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
|
||||
VST128(v0, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
case 0x2C:
|
||||
INST_NAME("CVTTPD2PI Gm,Ex");
|
||||
nextop = F8;
|
||||
GETGM(q0);
|
||||
GETEX(v1, 0, 0);
|
||||
if(box64_dynarec_fastround) {
|
||||
VFCVTZSQD(q0, v1);
|
||||
SQXTN_32(q0, q0);
|
||||
} else {
|
||||
MRS_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
ORRw_mask(x2, xZR, 1, 0); //0x80000000
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
for (int i=0; i<2; ++i) {
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
if (i) {
|
||||
VMOVeD(d0, 0, v1, i);
|
||||
FRINTZD(d0, d0);
|
||||
} else {
|
||||
FRINTZD(d0, v1);
|
||||
}
|
||||
FCVTZSwD(x1, d0);
|
||||
MRS_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ(x5, FPSR_IOC, 4+4);
|
||||
MOVw_REG(x1, x2);
|
||||
VMOVQSfrom(q0, i, x1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x2D:
|
||||
INST_NAME("CVTPD2PI Gm,Ex");
|
||||
nextop = F8;
|
||||
GETGM(q0);
|
||||
GETEX(v1, 0, 0);
|
||||
if(box64_dynarec_fastround) {
|
||||
u8 = sse_setround(dyn, ninst, x1, x2, x3);
|
||||
VFRINTIDQ(q0, v1);
|
||||
FCVTXN(q0, q0);
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
VFCVTZSS(q0, q0);
|
||||
} else {
|
||||
u8 = sse_setround(dyn, ninst, x1, x2, x3);
|
||||
MRS_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
ORRw_mask(x2, xZR, 1, 0); //0x80000000
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
for (int i=0; i<2; ++i) {
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
if (i) {
|
||||
VMOVeD(d0, 0, v1, i);
|
||||
FRINTID(d0, d0);
|
||||
} else {
|
||||
FRINTID(d0, v1);
|
||||
}
|
||||
FCVTZSwD(x1, d0);
|
||||
MRS_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ(x5, FPSR_IOC, 4+4);
|
||||
MOVw_REG(x1, x2);
|
||||
VMOVQSfrom(q0, i, x1);
|
||||
}
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
}
|
||||
break;
|
||||
case 0x2E:
|
||||
// no special check...
|
||||
case 0x2F:
|
||||
@@ -241,7 +329,16 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GETEX(q1, 0, 0);
|
||||
VADDPQ_32(q0, q0, q1);
|
||||
break;
|
||||
|
||||
case 0x03:
|
||||
INST_NAME("PHADDSW Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0, 1);
|
||||
GETEX(q1, 0, 0);
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
VUZP1Q_16(v0, q0, q1);
|
||||
VUZP2Q_16(q0, q0, q1);
|
||||
SQADDQ_16(q0, q0, v0);
|
||||
break;
|
||||
case 0x04:
|
||||
INST_NAME("PMADDUBSW Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -443,14 +540,14 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
case 0x20:
|
||||
INST_NAME("PMOVSXBW Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0, 0);
|
||||
GETEX64(q1, 0, 0);
|
||||
GETGX_empty(q0);
|
||||
SXTL_8(q0, q1); // 8bits->16bits
|
||||
break;
|
||||
case 0x21:
|
||||
INST_NAME("PMOVSXBD Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0, 0);
|
||||
GETEX32(q1, 0, 0);
|
||||
GETGX_empty(q0);
|
||||
SXTL_8(q0, q1); // 8bits->16bits
|
||||
SXTL_16(q0, q0); //16bits->32bits
|
||||
@@ -458,7 +555,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
case 0x22:
|
||||
INST_NAME("PMOVSXBQ Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0, 0);
|
||||
GETEX16(q1, 0, 0);
|
||||
GETGX_empty(q0);
|
||||
SXTL_8(q0, q1); // 8bits->16bits
|
||||
SXTL_16(q0, q0); //16bits->32bits
|
||||
@@ -467,14 +564,14 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
case 0x23:
|
||||
INST_NAME("PMOVSXWD Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0, 0);
|
||||
GETEX64(q1, 0, 0);
|
||||
GETGX_empty(q0);
|
||||
SXTL_16(q0, q1); // 16bits->32bits
|
||||
break;
|
||||
case 0x24:
|
||||
INST_NAME("PMOVSXWQ Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0, 0);
|
||||
GETEX32(q1, 0, 0);
|
||||
GETGX_empty(q0);
|
||||
SXTL_16(q0, q1); // 16bits->32bits
|
||||
SXTL_32(q0, q0); // 32bits->64bits
|
||||
@@ -482,7 +579,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
case 0x25:
|
||||
INST_NAME("PMOVSXDQ Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0, 0);
|
||||
GETEX64(q1, 0, 0);
|
||||
GETGX_empty(q0);
|
||||
SXTL_32(q0, q1); // 32bits->64bits
|
||||
break;
|
||||
@@ -539,14 +636,14 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
case 0x30:
|
||||
INST_NAME("PMOVZXBW Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0, 0);
|
||||
GETEX64(q1, 0, 0);
|
||||
GETGX_empty(q0);
|
||||
UXTL_8(q0, q1); // 8bits->16bits
|
||||
break;
|
||||
case 0x31:
|
||||
INST_NAME("PMOVZXBD Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0, 0);
|
||||
GETEX32(q1, 0, 0);
|
||||
GETGX_empty(q0);
|
||||
UXTL_8(q0, q1); // 8bits->16bits
|
||||
UXTL_16(q0, q0); //16bits->32bits
|
||||
@@ -554,7 +651,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
case 0x32:
|
||||
INST_NAME("PMOVZXBQ Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0, 0);
|
||||
GETEX16(q1, 0, 0);
|
||||
GETGX_empty(q0);
|
||||
UXTL_8(q0, q1); // 8bits->16bits
|
||||
UXTL_16(q0, q0); //16bits->32bits
|
||||
@@ -563,14 +660,14 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
case 0x33:
|
||||
INST_NAME("PMOVZXWD Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0, 0);
|
||||
GETEX64(q1, 0, 0);
|
||||
GETGX_empty(q0);
|
||||
UXTL_16(q0, q1); // 16bits->32bits
|
||||
break;
|
||||
case 0x34:
|
||||
INST_NAME("PMOVZXWQ Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0, 0);
|
||||
GETEX32(q1, 0, 0);
|
||||
GETGX_empty(q0);
|
||||
UXTL_16(q0, q1); // 16bits->32bits
|
||||
UXTL_32(q0, q0); // 32bits->64bits
|
||||
@@ -578,11 +675,18 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
case 0x35:
|
||||
INST_NAME("PMOVZXDQ Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0, 0);
|
||||
GETEX64(q1, 0, 0);
|
||||
GETGX_empty(q0);
|
||||
UXTL_32(q0, q1); // 32bits->64bits
|
||||
break;
|
||||
|
||||
case 0x37:
|
||||
INST_NAME("PCMPGTQ Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0, 0);
|
||||
GETGX(q0, 1);
|
||||
VCMGTQ_64(q0, q0, q1);
|
||||
break;
|
||||
case 0x38:
|
||||
INST_NAME("PMINSB Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
@@ -747,7 +851,37 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VEORQ(q0, q0, q1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xF0:
|
||||
INST_NAME("MOVBE Gw, Ew");
|
||||
nextop=F8;
|
||||
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3);
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
REV16x(x1, ed);
|
||||
BFIx(gd, x1, 0, 16);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<1, (1<<1)-1, rex, NULL, 0, 0);
|
||||
LDH(x1, ed, fixedaddress);
|
||||
REV16x(x1, x1);
|
||||
BFIx(gd, x1, 0, 16);
|
||||
}
|
||||
break;
|
||||
case 0xF1:
|
||||
INST_NAME("MOVBE Ew, Gw");
|
||||
nextop=F8;
|
||||
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3);
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
REV16x(x1, gd);
|
||||
BFIx(ed, x1, 0, 16);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<1, (1<<1)-1, rex, NULL, 0, 0);
|
||||
REV16x(x1, gd);
|
||||
STH(x1, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
@@ -833,7 +967,20 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VMOVeS(q0, i, q1, i);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0D:
|
||||
INST_NAME("PBLENDPD Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
GETGX(q0, 1);
|
||||
GETEX(q1, 0, 1);
|
||||
u8 = F8&0b11;
|
||||
if(u8==0b01) {
|
||||
VMOVeD(q0, 0, q1, 0);
|
||||
} else if(u8==0b10) {
|
||||
VMOVeD(q0, 1, q1, 1);
|
||||
} else if(u8==0b11) {
|
||||
VMOVQ(q0, q1);
|
||||
}
|
||||
break;
|
||||
case 0x0E:
|
||||
INST_NAME("PBLENDW Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
@@ -877,7 +1024,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GETEX(q1, 0, 1);
|
||||
u8 = F8;
|
||||
if(u8>31) {
|
||||
VEORQ(q0, q0, q0);
|
||||
VEORQ(q0, q0, q0);
|
||||
} else if(u8>15) {
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
VEORQ(d0, d0, d0);
|
||||
@@ -940,7 +1087,22 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x17:
|
||||
INST_NAME("EXTRACTPS Ew, Gx, Ib");
|
||||
nextop = F8;
|
||||
GETGX(q0, 0);
|
||||
if (MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
u8 = F8&0b11;
|
||||
MOVx_REG(ed, xZR);
|
||||
VMOVSto(ed, q0, u8);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0xfff<<2, 3, rex, NULL, 0, 1);
|
||||
u8 = F8&0b11;
|
||||
VMOVSto(x1, q0, u8);
|
||||
STW(x1, wback, fixedaddress);
|
||||
}
|
||||
break;
|
||||
case 0x20:
|
||||
INST_NAME("PINSRB Gx, ED, Ib");
|
||||
nextop = F8;
|
||||
@@ -949,7 +1111,30 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
u8 = F8;
|
||||
VMOVQBfrom(q0, (u8&15), ed);
|
||||
break;
|
||||
|
||||
case 0x21:
|
||||
INST_NAME("INSERTPS Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
GETGX(q0, 1);
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
VMOVQ(d0, q0);
|
||||
if (MODREG) {
|
||||
q1 = sse_get_reg(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 0);
|
||||
u8 = F8;
|
||||
VMOVeS(q0, (u8>>4)&3, q1, (u8>>6)&3);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 1);
|
||||
u8 = F8;
|
||||
LDW(x2, wback, fixedaddress);
|
||||
VMOVQSfrom(q0, (u8>>4)&3, x2);
|
||||
}
|
||||
uint8_t zmask = u8 & 0xf;
|
||||
for (uint8_t i=0; i<4; i++) {
|
||||
if (zmask & (1<<i)) {
|
||||
VMOVQSfrom(q0, i, wZR);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x22:
|
||||
INST_NAME("PINSRD Gx, ED, Ib");
|
||||
nextop = F8;
|
||||
@@ -963,6 +1148,28 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
INST_NAME("DPPS Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
GETGX(q0, 1);
|
||||
GETEX(q1, 0, 1);
|
||||
u8 = F8;
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
VFMULQS(v0, q0, q1);
|
||||
// mask some, duplicate all, mask some
|
||||
for(int i=0; i<4; ++i)
|
||||
if(!(u8&(1<<(4+i)))) {
|
||||
VMOVQSfrom(v0, i, xZR);
|
||||
}
|
||||
VFADDPQS(v0, v0, v0);
|
||||
FADDPS(v0, v0);
|
||||
VDUPQ_32(q0, v0, 0);
|
||||
for(int i=0; i<4; ++i)
|
||||
if(!(u8&(1<<i))) {
|
||||
VMOVQSfrom(q0, i, xZR);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x44:
|
||||
INST_NAME("PCLMULQDQ Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
@@ -991,7 +1198,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
sse_forget_reg(dyn, ninst, gd);
|
||||
MOV32w(x1, gd); // gx
|
||||
if(MODREG) {
|
||||
ed = (nextop&7)+(rex.b<<3);
|
||||
ed = (nextop&7)+(rex.b<<3);
|
||||
sse_forget_reg(dyn, ninst, ed);
|
||||
MOV32w(x2, ed);
|
||||
MOV32w(x3, 0); //p = NULL
|
||||
@@ -1008,6 +1215,181 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x60:
|
||||
INST_NAME("PCMPESTRM Gx, Ex, Ib");
|
||||
SETFLAGS(X_OF|X_CF|X_AF|X_ZF|X_SF|X_PF, SF_SET);
|
||||
nextop = F8;
|
||||
GETG;
|
||||
sse_forget_reg(dyn, ninst, gd);
|
||||
ADDx_U12(x3, xEmu, offsetof(x64emu_t, xmm[gd]));
|
||||
if(MODREG) {
|
||||
ed = (nextop&7)+(rex.b<<3);
|
||||
sse_reflect_reg(dyn, ninst, ed);
|
||||
ADDx_U12(x1, xEmu, offsetof(x64emu_t, xmm[ed]));
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 1);
|
||||
if(ed!=x1) {
|
||||
MOVx_REG(x1, ed);
|
||||
}
|
||||
}
|
||||
MOVx_REG(x2, xRDX);
|
||||
MOVx_REG(x4, xRAX);
|
||||
u8 = F8;
|
||||
MOV32w(x5, u8);
|
||||
CALL(sse42_compare_string_explicit_len, x1);
|
||||
q0 = sse_get_reg_empty(dyn, ninst, x2, gd);
|
||||
q1 = fpu_get_scratch(dyn);
|
||||
if(u8&0b1000000) {
|
||||
switch(u8&1) {
|
||||
case 0b00:
|
||||
VDUPQB(q0, x1); // load the low 8bits of the mask
|
||||
LSRw_IMM(x1, x1, 8);
|
||||
VDUPQB(q1, x1); // load the high 8bits of the mask
|
||||
VEXTQ_8(q0, q0, q1, 8); // low and hig bits mask
|
||||
TABLE64(x2, (uintptr_t)&mask_string8);
|
||||
VLDR64_U12(q1, x2, 0); // load shift
|
||||
VDUPQ_64(q1, q1, 0);
|
||||
USHLQ_8(q0, q0, q1); // extract 1 bit
|
||||
MOVIQ_8(q1, 0x80); // load mask
|
||||
VANDQ(q0, q0, q1);
|
||||
VSSHRQ_8(q0, q0, 7); // saturate the mask
|
||||
break;
|
||||
case 0b01:
|
||||
VDUPQH(q0, x1); // load the 8bits of the mask
|
||||
TABLE64(x2, (uintptr_t)&mask_string16);
|
||||
VLDR64_U12(q1, x2, 0); // load shift
|
||||
UXTL_8(q1, q1); // extend mask to 16bits
|
||||
USHLQ_16(q0, q0, q1); // extract 1 bit
|
||||
MOVIQ_16(q1, 0x80, 1); // load mask
|
||||
VANDQ(q0, q0, q1);
|
||||
VSSHRQ_16(q0, q0, 15); // saturate the mask
|
||||
}
|
||||
} else {
|
||||
VEORQ(q0, q0, q0);
|
||||
VMOVQHfrom(q0, 0, x1);
|
||||
}
|
||||
break;
|
||||
case 0x61:
|
||||
INST_NAME("PCMPESTRI Gx, Ex, Ib");
|
||||
SETFLAGS(X_OF|X_CF|X_AF|X_ZF|X_SF|X_PF, SF_SET);
|
||||
nextop = F8;
|
||||
GETG;
|
||||
sse_reflect_reg(dyn, ninst, gd);
|
||||
ADDx_U12(x3, xEmu, offsetof(x64emu_t, xmm[gd]));
|
||||
if(MODREG) {
|
||||
ed = (nextop&7)+(rex.b<<3);
|
||||
sse_reflect_reg(dyn, ninst, ed);
|
||||
ADDx_U12(x1, xEmu, offsetof(x64emu_t, xmm[ed]));
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 1);
|
||||
if(ed!=x1) {
|
||||
MOVx_REG(x1, ed);
|
||||
}
|
||||
}
|
||||
MOVx_REG(x2, xRDX);
|
||||
MOVx_REG(x4, xRAX);
|
||||
u8 = F8;
|
||||
MOV32w(x5, u8);
|
||||
CALL(sse42_compare_string_explicit_len, x1);
|
||||
CBNZw_MARK(x1);
|
||||
MOV32w(xRCX, (u8&1)?8:16);
|
||||
B_NEXT_nocond;
|
||||
MARK;
|
||||
if(u8&0b1000000) {
|
||||
CLZw(xRCX, x1);
|
||||
MOV32w(x2, 31);
|
||||
SUBw_REG(xRCX, x2, xRCX);
|
||||
} else {
|
||||
RBITxw(xRCX, x1);
|
||||
CLZw(xRCX, xRCX);
|
||||
}
|
||||
break;
|
||||
case 0x62:
|
||||
INST_NAME("PCMPISTRM Gx, Ex, Ib");
|
||||
SETFLAGS(X_OF|X_CF|X_AF|X_ZF|X_SF|X_PF, SF_SET);
|
||||
nextop = F8;
|
||||
GETG;
|
||||
sse_forget_reg(dyn, ninst, gd);
|
||||
ADDx_U12(x2, xEmu, offsetof(x64emu_t, xmm[gd]));
|
||||
if(MODREG) {
|
||||
ed = (nextop&7)+(rex.b<<3);
|
||||
sse_reflect_reg(dyn, ninst, ed);
|
||||
ADDx_U12(x1, xEmu, offsetof(x64emu_t, xmm[ed]));
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 1);
|
||||
if(ed!=x1) {
|
||||
MOVx_REG(x1, ed);
|
||||
}
|
||||
}
|
||||
u8 = F8;
|
||||
MOV32w(x3, u8);
|
||||
CALL(sse42_compare_string_implicit_len, x1);
|
||||
q0 = sse_get_reg_empty(dyn, ninst, x2, gd);
|
||||
q1 = fpu_get_scratch(dyn);
|
||||
if(u8&0b1000000) {
|
||||
switch(u8&1) {
|
||||
case 0b00:
|
||||
VDUPQB(q0, x1); // load the low 8bits of the mask
|
||||
LSRw_IMM(x1, x1, 8);
|
||||
VDUPQB(q1, x1); // load the high 8bits of the mask
|
||||
VEXTQ_8(q0, q0, q1, 8); // low and hig bits mask
|
||||
TABLE64(x2, (uintptr_t)&mask_string8);
|
||||
VLDR64_U12(q1, x2, 0); // load shift
|
||||
VDUPQ_64(q1, q1, 0);
|
||||
USHLQ_8(q0, q0, q1); // extract 1 bit
|
||||
MOVIQ_8(q1, 0x80); // load mask
|
||||
VANDQ(q0, q0, q1);
|
||||
VSSHRQ_8(q0, q0, 7); // saturate the mask
|
||||
break;
|
||||
case 0b01:
|
||||
VDUPQH(q0, x1); // load the 8bits of the mask
|
||||
TABLE64(x2, (uintptr_t)&mask_string16);
|
||||
VLDR64_U12(q1, x2, 0); // load shift
|
||||
UXTL_8(q1, q1); // extend mask to 16bits
|
||||
USHLQ_16(q0, q0, q1); // extract 1 bit
|
||||
MOVIQ_16(q1, 0x80, 1); // load mask
|
||||
VANDQ(q0, q0, q1);
|
||||
VSSHRQ_16(q0, q0, 15); // saturate the mask
|
||||
}
|
||||
} else {
|
||||
VEORQ(q0, q0, q0);
|
||||
VMOVQHfrom(q0, 0, x1);
|
||||
}
|
||||
break;
|
||||
case 0x63:
|
||||
INST_NAME("PCMPISTRI Gx, Ex, Ib");
|
||||
SETFLAGS(X_OF|X_CF|X_AF|X_ZF|X_SF|X_PF, SF_SET);
|
||||
nextop = F8;
|
||||
GETG;
|
||||
sse_reflect_reg(dyn, ninst, gd);
|
||||
ADDx_U12(x2, xEmu, offsetof(x64emu_t, xmm[gd]));
|
||||
if(MODREG) {
|
||||
ed = (nextop&7)+(rex.b<<3);
|
||||
sse_reflect_reg(dyn, ninst, ed);
|
||||
ADDx_U12(x1, xEmu, offsetof(x64emu_t, xmm[ed]));
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 1);
|
||||
if(ed!=x1) {
|
||||
MOVx_REG(x1, ed);
|
||||
}
|
||||
}
|
||||
u8 = F8;
|
||||
MOV32w(x3, u8);
|
||||
CALL(sse42_compare_string_implicit_len, x1);
|
||||
CBNZw_MARK(x1);
|
||||
MOV32w(xRCX, (u8&1)?8:16);
|
||||
B_NEXT_nocond;
|
||||
MARK;
|
||||
if(u8&0b1000000) {
|
||||
CLZw(xRCX, x1);
|
||||
MOV32w(x2, 31);
|
||||
SUBw_REG(xRCX, x2, xRCX);
|
||||
} else {
|
||||
RBITxw(xRCX, x1);
|
||||
CLZw(xRCX, xRCX);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xDF:
|
||||
INST_NAME("AESKEYGENASSIST Gx, Ex, Ib"); // AES-NI
|
||||
nextop = F8;
|
||||
@@ -1015,7 +1397,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
sse_forget_reg(dyn, ninst, gd);
|
||||
MOV32w(x1, gd); // gx
|
||||
if(MODREG) {
|
||||
ed = (nextop&7)+(rex.b<<3);
|
||||
ed = (nextop&7)+(rex.b<<3);
|
||||
sse_forget_reg(dyn, ninst, ed);
|
||||
MOV32w(x2, ed);
|
||||
MOV32w(x3, 0); //p = NULL
|
||||
@@ -1065,7 +1447,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
LSRx(x1, x1, 63);
|
||||
LSRx(gd, gd, 63);
|
||||
BFIx(gd, x1, 1, 1);
|
||||
break;
|
||||
break;
|
||||
case 0x51:
|
||||
INST_NAME("SQRTPD Gx, Ex");
|
||||
nextop = F8;
|
||||
@@ -1085,7 +1467,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VFSQRTQD(q1, q0);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 0x54:
|
||||
INST_NAME("ANDPD Gx, Ex");
|
||||
nextop = F8;
|
||||
@@ -1110,9 +1492,16 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
case 0x57:
|
||||
INST_NAME("XORPD Gx, Ex");
|
||||
nextop = F8;
|
||||
GETEX(q0, 0, 0);
|
||||
GETGX(v0, 1);
|
||||
VEORQ(v0, v0, q0);
|
||||
GETG;
|
||||
if(MODREG && ((nextop&7)+(rex.b<<3)==gd)) {
|
||||
// special case for XORPD Gx, Gx
|
||||
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VEORQ(q0, q0, q0);
|
||||
} else {
|
||||
q0 = sse_get_reg(dyn, ninst, x1, gd, 1);
|
||||
GETEX(q1, 0, 0);
|
||||
VEORQ(q0, q0, q1);
|
||||
}
|
||||
break;
|
||||
case 0x58:
|
||||
INST_NAME("ADDPD Gx, Ex");
|
||||
@@ -1440,32 +1829,25 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
} else if(u8==0x00) {
|
||||
// duplicate lower 32bits to all spot
|
||||
if(v0!=v1) {
|
||||
VMOVeS(v0, 0, v1, 0);
|
||||
}
|
||||
VMOVeS(v0, 1, v1, 0);
|
||||
VMOVeD(v0, 1, v0, 0);
|
||||
VDUPQ_32(v0, v1, 0);
|
||||
} else if(u8==0x55) {
|
||||
// duplicate slot 1 to all spot
|
||||
if(v0!=v1) {
|
||||
VMOVeS(v0, 1, v1, 1);
|
||||
}
|
||||
VMOVeS(v0, 0, v1, 1);
|
||||
VMOVeD(v0, 1, v0, 0);
|
||||
VDUPQ_32(v0, v1, 1);
|
||||
} else if(u8==0xAA) {
|
||||
// duplicate slot 2 to all spot
|
||||
if(v0!=v1) {
|
||||
VMOVeS(v0, 2, v1, 2);
|
||||
}
|
||||
VMOVeS(v0, 3, v1, 2);
|
||||
VMOVeD(v0, 0, v0, 1);
|
||||
VDUPQ_32(v0, v1, 2);
|
||||
} else if(u8==0xFF) {
|
||||
// duplicate slot 3 to all spot
|
||||
if(v0!=v1) {
|
||||
VMOVeS(v0, 3, v1, 3);
|
||||
}
|
||||
VMOVeS(v0, 2, v1, 3);
|
||||
VMOVeD(v0, 0, v0, 1);
|
||||
VDUPQ_32(v0, v1, 3);
|
||||
} else if(u8==0x44) {
|
||||
// duplicate slot 0/1 to all spot
|
||||
VDUPQ_64(v0, v1, 0);
|
||||
} else if(u8==0xEE) {
|
||||
// duplicate slot 2/3 to all spot
|
||||
VDUPQ_64(v0, v1, 1);
|
||||
} else if(u8==0xB1) {
|
||||
// invert 0/1 and 2/3
|
||||
VREV64Q_32(v0, v1);
|
||||
} else if(v0!=v1) {
|
||||
VMOVeS(v0, 0, v1, (u8>>(0*2))&3);
|
||||
VMOVeS(v0, 1, v1, (u8>>(1*2))&3);
|
||||
@@ -1706,7 +2088,16 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VORRQ(q1, q1, v1); // NAN -> -NAN
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x7D:
|
||||
INST_NAME("HSUBPD Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0, 0);
|
||||
GETGX(q0, 1);
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
VUZP1Q_64(v0, q0, q1);
|
||||
VUZP2Q_64(q0, q0, q1);
|
||||
VFSUBQD(q0, v0, q0);
|
||||
break;
|
||||
case 0x7E:
|
||||
INST_NAME("MOVD Ed,Gx");
|
||||
nextop = F8;
|
||||
@@ -1756,7 +2147,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<2, (1<<2)-1, rex, NULL, 0, 0);
|
||||
SBFXw(x1, gd, 4, 12); // r1 = (gw>>4)
|
||||
SBFXx(x1, gd, 4, 12); // r1 = (gw>>4)
|
||||
ADDx_REG_LSL(x3, wback, x1, 1); //(&ed)+=r1*2;
|
||||
LDH(x1, x3, fixedaddress);
|
||||
ed = x1;
|
||||
@@ -1766,24 +2157,31 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
BFIw(xFlags, x1, F_CF, 1);
|
||||
break;
|
||||
case 0xA4:
|
||||
INST_NAME("SHLD Ew, Gw, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETEW(x1, 1);
|
||||
GETGW(x2);
|
||||
u8 = F8;
|
||||
emit_shld16c(dyn, ninst, ed, gd, u8, x4, x5);
|
||||
EWBACK;
|
||||
break;
|
||||
case 0xA5:
|
||||
nextop = F8;
|
||||
if(opcode==0xA4) {
|
||||
INST_NAME("SHLD Ew, Gw, Ib");
|
||||
} else {
|
||||
INST_NAME("SHLD Ew, Gw, CL");
|
||||
UXTBw(x3, xRCX);
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
GETEWW(x4, x1, (opcode==0xA4)?1:0);
|
||||
INST_NAME("SHLD Ew, Gw, CL");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
if(box64_dynarec_safeflags>1)
|
||||
MAYSETFLAGS();
|
||||
GETGW(x2);
|
||||
if(opcode==0xA4) {
|
||||
u8 = F8;
|
||||
MOV32w(x3, u8);
|
||||
GETEW(x1, 0);
|
||||
UFLAG_IF {
|
||||
ANDSw_mask(x4, xRCX, 0, 0b00100); //mask=0x00000001f
|
||||
B_NEXT(cEQ);
|
||||
} else {
|
||||
ANDw_mask(x4, xRCX, 0, 0b00100); //mask=0x00000001f
|
||||
}
|
||||
CALL_(shld16, x1, wback);
|
||||
EWBACKW(x1);
|
||||
emit_shld16(dyn, ninst, ed, gd, x4, x5, x6);
|
||||
EWBACK;
|
||||
break;
|
||||
|
||||
case 0xAB:
|
||||
@@ -1797,54 +2195,62 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<2, (1<<2)-1, rex, NULL, 0, 0);
|
||||
SBFXw(x4, gd, 4, 12); // r1 = (gw>>4)
|
||||
SBFXx(x4, gd, 4, 12); // r1 = (gw>>4)
|
||||
ADDx_REG_LSL(x3, wback, x4, 1); //(&ed)+=r1*2;
|
||||
LDH(x4, x3, fixedaddress);
|
||||
wback = x3;
|
||||
ed = x4;
|
||||
}
|
||||
ANDw_mask(x2, gd, 0, 0b000011); // mask=0x0f
|
||||
LSRw_REG(x1, ed, x2);
|
||||
BFIw(xFlags, x1, F_CF, 1);
|
||||
ANDSw_mask(x1, x1, 0, 0); //mask=1
|
||||
B_NEXT(cNE);
|
||||
IFX(X_CF) {
|
||||
LSRw_REG(x1, ed, x2);
|
||||
BFIw(xFlags, x1, F_CF, 1);
|
||||
}
|
||||
MOV32w(x1, 1);
|
||||
LSLxw_REG(x1, x1, x2);
|
||||
EORx_REG(ed, ed, x1);
|
||||
LSLw_REG(x1, x1, x2);
|
||||
ORRx_REG(ed, ed, x1);
|
||||
if(wback) {
|
||||
STRH_U12(ed, wback, fixedaddress);
|
||||
}
|
||||
break;
|
||||
case 0xAC:
|
||||
nextop = F8;
|
||||
INST_NAME("SHRD Ew, Gw, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1, 1);
|
||||
GETGW(x2);
|
||||
u8 = F8;
|
||||
emit_shrd16c(dyn, ninst, ed, gd, u8, x4, x5);
|
||||
EWBACK;
|
||||
break;
|
||||
case 0xAD:
|
||||
nextop = F8;
|
||||
if(opcode==0xAC) {
|
||||
INST_NAME("SHRD Ew, Gw, Ib");
|
||||
} else {
|
||||
INST_NAME("SHRD Ew, Gw, CL");
|
||||
UXTBw(x3, xRCX);
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
GETEWW(x4, x1, (opcode==0xAC)?1:0);
|
||||
INST_NAME("SHRD Ew, Gw, CL");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
if(box64_dynarec_safeflags>1)
|
||||
MAYSETFLAGS();
|
||||
GETGW(x2);
|
||||
if(opcode==0xAC) {
|
||||
u8 = F8;
|
||||
MOV32w(x3, u8);
|
||||
GETEW(x1, 0);
|
||||
UFLAG_IF {
|
||||
ANDSw_mask(x4, xRCX, 0, 0b00100); //mask=0x00000001f
|
||||
B_NEXT(cEQ);
|
||||
} else {
|
||||
ANDw_mask(x4, xRCX, 0, 0b00100); //mask=0x00000001f
|
||||
}
|
||||
CALL_(shrd16, x1, wback);
|
||||
EWBACKW(x1);
|
||||
emit_shrd16(dyn, ninst, ed, gd, x4, x5, x6);
|
||||
EWBACK;
|
||||
break;
|
||||
|
||||
case 0xAF:
|
||||
INST_NAME("IMUL Gw,Ew");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
nextop = F8;
|
||||
UFLAG_DF(x1, d_imul16);
|
||||
GETSEW(x1, 0);
|
||||
GETSGW(x2);
|
||||
MULw(x2, x2, x1);
|
||||
UFLAG_RES(x2);
|
||||
GWBACK;
|
||||
UFLAG_DF(x1, d_imul16);
|
||||
break;
|
||||
|
||||
case 0xB3:
|
||||
@@ -1859,7 +2265,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<2, (1<<2)-1, rex, NULL, 0, 0);
|
||||
SBFXw(x4, gd, 4, 12); // r1 = (gw>>4)
|
||||
SBFXx(x4, gd, 4, 12); // r1 = (gw>>4)
|
||||
ADDx_REG_LSL(x3, wback, x4, 1); //(&ed)+=r1*2;
|
||||
LDH(x4, x3, fixedaddress);
|
||||
wback = x3;
|
||||
@@ -1868,11 +2274,9 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
ANDw_mask(x2, gd, 0, 0b000011); // mask=0x0f
|
||||
LSRw_REG(x1, ed, x2);
|
||||
BFIw(xFlags, x1, F_CF, 1);
|
||||
ANDSw_mask(x1, x1, 0, 0); //mask=1
|
||||
B_NEXT(cEQ);
|
||||
MOV32w(x1, 1);
|
||||
LSLxw_REG(x1, x1, x2);
|
||||
EORx_REG(ed, ed, x1);
|
||||
BICx_REG(ed, ed, x1);
|
||||
if(wback) {
|
||||
STH(ed, wback, fixedaddress);
|
||||
SMWRITE();
|
||||
@@ -1885,7 +2289,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
if(MODREG) {
|
||||
if(rex.rex) {
|
||||
eb1 = xRAX+(nextop&7)+(rex.b<<3);
|
||||
eb2 = 0; \
|
||||
eb2 = 0;
|
||||
} else {
|
||||
ed = (nextop&7);
|
||||
eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx
|
||||
@@ -1936,12 +2340,12 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GETEW(x1, 1);
|
||||
u8 = F8;
|
||||
u8&=(rex.w?0x3f:0x0f);
|
||||
BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
|
||||
TBNZ_MARK3(xFlags, 0); // bit already set, jump to next instruction
|
||||
IFX(X_CF) {
|
||||
BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
|
||||
}
|
||||
MOV32w(x4, 1);
|
||||
EORxw_REG_LSL(ed, ed, x4, u8);
|
||||
BFIxw(ed, x4, u8, 1);
|
||||
EWBACK(x1);
|
||||
MARK3;
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("BTR Ew, Ib");
|
||||
@@ -1950,12 +2354,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GETEW(x1, 1);
|
||||
u8 = F8;
|
||||
u8&=(rex.w?0x3f:0x0f);
|
||||
BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
|
||||
TBZ_MARK3(xFlags, 0); // bit already clear, jump to next instruction
|
||||
MOV32w(x4, 1);
|
||||
EORxw_REG_LSL(ed, ed, x4, u8);
|
||||
IFX(X_CF) {
|
||||
BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
|
||||
}
|
||||
BFCxw(ed, u8, 1);
|
||||
EWBACK(x1);
|
||||
MARK3;
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("BTC Ew, Ib");
|
||||
@@ -1964,7 +2367,9 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GETEW(x1, 1);
|
||||
u8 = F8;
|
||||
u8&=(rex.w?0x3f:0x0f);
|
||||
BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
|
||||
IFX(X_CF) {
|
||||
BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
|
||||
}
|
||||
MOV32w(x4, 1);
|
||||
EORxw_REG_LSL(ed, ed, x4, u8);
|
||||
EWBACK(x1);
|
||||
@@ -1985,16 +2390,17 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<2, (1<<2)-1, rex, NULL, 0, 0);
|
||||
SBFXw(x4, gd, 4, 12); // r1 = (gw>>4)
|
||||
SBFXx(x4, gd, 4, 12); // r1 = (gw>>4)
|
||||
ADDx_REG_LSL(x3, wback, x4, 1); //(&ed)+=r1*2;
|
||||
LDH(x4, x3, fixedaddress);
|
||||
wback = x3;
|
||||
ed = x4;
|
||||
}
|
||||
ANDw_mask(x2, gd, 0, 0b000011); // mask=0x0f
|
||||
LSRw_REG(x1, ed, x2);
|
||||
BFIw(xFlags, x1, F_CF, 1);
|
||||
ANDw_mask(x1, x1, 0, 0); //mask=1
|
||||
IFX(X_CF) {
|
||||
LSRw_REG(x1, ed, x2);
|
||||
BFIw(xFlags, x1, F_CF, 1);
|
||||
}
|
||||
MOV32w(x1, 1);
|
||||
LSLxw_REG(x1, x1, x2);
|
||||
EORx_REG(ed, ed, x1);
|
||||
@@ -2060,6 +2466,16 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
BFIx(gd, x1, 0, 16);
|
||||
break;
|
||||
|
||||
case 0xC1:
|
||||
INST_NAME("XADD Gw, Ew");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2, 0);
|
||||
BFIx(xRAX+((nextop&0x38)>>3)+(rex.r<<3), ed, 0, 16);
|
||||
emit_add16(dyn, ninst, ed, gd, x4, x5);
|
||||
EWBACK;
|
||||
break;
|
||||
case 0xC2:
|
||||
INST_NAME("CMPPD Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
@@ -2071,21 +2487,21 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
case 0: VFCMEQQD(v0, v0, v1); break; // Equal
|
||||
case 1: VFCMGTQD(v0, v1, v0); break; // Less than
|
||||
case 2: VFCMGEQD(v0, v1, v0); break; // Less or equal
|
||||
case 3: VFCMEQQD(v0, v0, v0);
|
||||
case 3: VFCMEQQD(v0, v0, v0);
|
||||
if(v0!=v1) {
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
VFCMEQQD(q0, v1, v1);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
VFCMEQQD(q0, v1, v1);
|
||||
VANDQ(v0, v0, q0);
|
||||
}
|
||||
VMVNQ(v0, v0);
|
||||
VMVNQ(v0, v0);
|
||||
break; // NaN (NaN is not equal to himself)
|
||||
case 4: VFCMEQQD(v0, v0, v1); VMVNQ(v0, v0); break; // Not Equal (or unordered on ARM, not on X86...)
|
||||
case 5: VFCMGTQD(v0, v1, v0); VMVNQ(v0, v0); break; // Greater or equal or unordered
|
||||
case 6: VFCMGEQD(v0, v1, v0); VMVNQ(v0, v0); break; // Greater or unordered
|
||||
case 7: VFCMEQQD(v0, v0, v0);
|
||||
case 7: VFCMEQQD(v0, v0, v0);
|
||||
if(v0!=v1) {
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
VFCMEQQD(q0, v1, v1);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
VFCMEQQD(q0, v1, v1);
|
||||
VANDQ(v0, v0, q0);
|
||||
}
|
||||
break; // not NaN
|
||||
@@ -2175,6 +2591,16 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VDUPQ_16(v0, v0, 0); // only the low 8bits will be used anyway
|
||||
USHLQ_16(q0, q0, v0); // SHR x8
|
||||
break;
|
||||
case 0xD0:
|
||||
INST_NAME("ADDSUBPD Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0, 1);
|
||||
GETEX(q1, 0, 0);
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
VFSUBQD(v0, q0, q1);
|
||||
VFADDQD(q0, q0, q1);
|
||||
VMOVeD(q0, 0, v0, 0);
|
||||
break;
|
||||
case 0xD2:
|
||||
INST_NAME("PSRLD Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -2252,7 +2678,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
UADDLV_8(q1, q1); // accumalte
|
||||
VMOVBto(x1, q1, 0);
|
||||
BFIx(gd, x1, 8, 8);
|
||||
break;
|
||||
break;
|
||||
case 0xD8:
|
||||
INST_NAME("PSUBUSB Gx, Ex");
|
||||
nextop = F8;
|
||||
|
||||
@@ -53,7 +53,6 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x5);
|
||||
SMDMB();
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
UXTHw(x6, ed);
|
||||
@@ -61,13 +60,22 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
BFIx(ed, x6, 0, 16);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_or16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
if(arm64_atomics) {
|
||||
UFLAG_IF {
|
||||
LDSETALH(x5, x1, wback);
|
||||
emit_or16(dyn, ninst, x1, x5, x3, x4);
|
||||
} else {
|
||||
STSETLH(x5, wback);
|
||||
}
|
||||
} else {
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_or16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
SMDMB();
|
||||
}
|
||||
SMDMB();
|
||||
break;
|
||||
|
||||
case 0x0F:
|
||||
@@ -79,7 +87,6 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
SMDMB();
|
||||
UXTHw(x6, xRAX);
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
@@ -90,34 +97,43 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
BFIx(ed, gd, 0, 16);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
TSTx_mask(wback, 1, 0, 0); // mask=1
|
||||
B_MARK3(cNE);
|
||||
if(!ALIGNED_ATOMICH) {
|
||||
TSTx_mask(wback, 1, 0, 0); // mask=1
|
||||
B_MARK3(cNE);
|
||||
}
|
||||
// Aligned version
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
CMPSw_REG(x6, x1);
|
||||
B_MARK(cNE);
|
||||
// EAX == Ed
|
||||
STLXRH(x4, gd, wback);
|
||||
CBNZx_MARKLOCK(x4);
|
||||
// done
|
||||
B_MARK_nocond;
|
||||
// Unaligned version
|
||||
MARK3;
|
||||
LDRH_U12(x1, wback, 0);
|
||||
LDAXRB(x3, wback); // dummy read, to arm the write...
|
||||
CMPSw_REG(x6, x1);
|
||||
B_MARK(cNE);
|
||||
// EAX == Ed
|
||||
STLXRB(x4, gd, wback);
|
||||
CBNZx_MARK3(x4);
|
||||
STRH_U12(gd, wback, 0);
|
||||
if(arm64_atomics) {
|
||||
MOVw_REG(x1, x6);
|
||||
CASALH(x1, gd, wback);
|
||||
} else {
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
CMPSw_REG(x6, x1);
|
||||
B_MARK(cNE);
|
||||
// EAX == Ed
|
||||
STLXRH(x4, gd, wback);
|
||||
CBNZx_MARKLOCK(x4);
|
||||
// done
|
||||
}
|
||||
if(!ALIGNED_ATOMICH) {
|
||||
B_MARK_nocond;
|
||||
// Unaligned version
|
||||
MARK3;
|
||||
LDRH_U12(x1, wback, 0);
|
||||
LDAXRB(x3, wback); // dummy read, to arm the write...
|
||||
CMPSw_REG(x6, x1);
|
||||
B_MARK(cNE);
|
||||
// EAX == Ed
|
||||
STLXRB(x4, gd, wback);
|
||||
CBNZx_MARK3(x4);
|
||||
STRH_U12(gd, wback, 0);
|
||||
}
|
||||
}
|
||||
SMDMB();
|
||||
MARK;
|
||||
// Common part (and fallback for EAX != Ed)
|
||||
UFLAG_IF {emit_cmp16(dyn, ninst, x6, x1, x3, x4, x5);}
|
||||
BFIx(xRAX, x1, 0, 16);
|
||||
SMDMB();
|
||||
break;
|
||||
|
||||
case 0xC1:
|
||||
@@ -126,7 +142,6 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
nextop = F8;
|
||||
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3);
|
||||
UXTHx(x5, gd);
|
||||
SMDMB();
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
BFIx(gd, ed, 0, 16);
|
||||
@@ -134,29 +149,52 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
BFIx(ed, x5, 0, 16);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
ADDxw_REG(x4, x1, x5);
|
||||
STLXRH(x3, x4, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
if(arm64_atomics) {
|
||||
LDADDALH(x5, x1, wback);
|
||||
} else {
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
ADDxw_REG(x4, x1, x5);
|
||||
STLXRH(x3, x4, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
SMDMB();
|
||||
IFX(X_ALL|X_PEND) {
|
||||
MOVxw_REG(x2, x1);
|
||||
emit_add16(dyn, ninst, x2, x5, x3, x4);
|
||||
}
|
||||
BFIx(gd, x1, 0, 16);
|
||||
}
|
||||
SMDMB();
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x11:
|
||||
INST_NAME("LOCK ADC Ew, Gw");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x5);
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
UXTHw(x6, ed);
|
||||
emit_adc16(dyn, ninst, x6, x5, x3, x4);
|
||||
BFIx(ed, x6, 0, 16);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_adc16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
SMDMB();
|
||||
}
|
||||
break;
|
||||
case 0x81:
|
||||
case 0x83:
|
||||
nextop = F8;
|
||||
SMDMB();
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: //ADD
|
||||
if(opcode==0x81) {
|
||||
@@ -176,22 +214,35 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
MOV32w(x5, i32);
|
||||
TSTx_mask(wback, 1, 0, 0); // mask=1
|
||||
B_MARK(cNE);
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_add16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
B_NEXT_nocond;
|
||||
MARK; // unaligned! also, not enough
|
||||
LDRH_U12(x1, wback, 0);
|
||||
LDAXRB(x4, wback);
|
||||
BFIw(x1, x4, 0, 8); // re-inject
|
||||
emit_add16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZx_MARK(x3);
|
||||
STRH_U12(x1, wback, 0); // put the whole value
|
||||
if(!ALIGNED_ATOMICH) {
|
||||
TSTx_mask(wback, 1, 0, 0); // mask=1
|
||||
B_MARK(cNE);
|
||||
}
|
||||
if(arm64_atomics) {
|
||||
LDADDALH(x5, x1, wback);
|
||||
UFLAG_IF {
|
||||
emit_add16(dyn, ninst, x1, x5, x3, x4);
|
||||
}
|
||||
} else {
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_add16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
SMDMB();
|
||||
if(!ALIGNED_ATOMICH) {
|
||||
B_NEXT_nocond;
|
||||
MARK; // unaligned! also, not enough
|
||||
LDRH_U12(x1, wback, 0);
|
||||
LDAXRB(x4, wback);
|
||||
BFIw(x1, x4, 0, 8); // re-inject
|
||||
emit_add16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZx_MARK(x3);
|
||||
STRH_U12(x1, wback, 0); // put the whole value
|
||||
SMDMB();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1: //OR
|
||||
@@ -208,11 +259,21 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
MOV32w(x5, i32);
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_or16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
if(arm64_atomics) {
|
||||
UFLAG_IF {
|
||||
LDSETALH(x5, x1, wback);
|
||||
emit_or16(dyn, ninst, x1, x5, x3, x4);
|
||||
} else {
|
||||
STSETLH(x5, wback);
|
||||
}
|
||||
} else {
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_or16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
SMDMB();
|
||||
}
|
||||
break;
|
||||
case 2: //ADC
|
||||
@@ -235,6 +296,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
emit_adc16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
SMDMB();
|
||||
}
|
||||
break;
|
||||
case 3: //SBB
|
||||
@@ -257,6 +319,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
emit_sbb16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
SMDMB();
|
||||
}
|
||||
break;
|
||||
case 4: //AND
|
||||
@@ -272,12 +335,24 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
MOV32w(x5, i32);
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_and16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
if(arm64_atomics) {
|
||||
MOV32w(x5, ~i32);
|
||||
UFLAG_IF {
|
||||
LDCLRALH(x5, x1, wback);
|
||||
MVNw_REG(x5, x5);
|
||||
emit_and16(dyn, ninst, x1, x5, x3, x4);
|
||||
} else {
|
||||
STCLRLH(x5, wback);
|
||||
}
|
||||
} else {
|
||||
MOV32w(x5, i32);
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_and16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
SMDMB();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 5: //SUB
|
||||
@@ -294,22 +369,38 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
MOV32w(x5, i32);
|
||||
TSTx_mask(wback, 1, 0, 0); // mask=1
|
||||
B_MARK(cNE);
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_sub16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
B_NEXT_nocond;
|
||||
MARK; // unaligned! also, not enough
|
||||
LDRH_U12(x1, wback, 0);
|
||||
LDAXRB(x4, wback);
|
||||
BFIw(x1, x4, 0, 8); // re-inject
|
||||
emit_sub16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZx_MARK(x3);
|
||||
STRH_U12(x1, wback, 0); // put the whole value
|
||||
if(!ALIGNED_ATOMICH) {
|
||||
TSTx_mask(wback, 1, 0, 0); // mask=1
|
||||
B_MARK(cNE);
|
||||
}
|
||||
if(arm64_atomics) {
|
||||
NEGw_REG(x4, x5);
|
||||
UFLAG_IF {
|
||||
LDADDALH(x4, x1, wback);
|
||||
emit_sub16(dyn, ninst, x1, x5, x3, x4);
|
||||
} else {
|
||||
STADDLH(x4, wback);
|
||||
}
|
||||
} else {
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_sub16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
SMDMB();
|
||||
if(!ALIGNED_ATOMICH) {
|
||||
B_NEXT_nocond;
|
||||
MARK; // unaligned! also, not enough
|
||||
LDRH_U12(x1, wback, 0);
|
||||
LDAXRB(x4, wback);
|
||||
BFIw(x1, x4, 0, 8); // re-inject
|
||||
emit_sub16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZx_MARK(x3);
|
||||
STRH_U12(x1, wback, 0); // put the whole value
|
||||
SMDMB();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 6: //XOR
|
||||
@@ -326,11 +417,21 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
MOV32w(x5, i32);
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_xor16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
if(arm64_atomics) {
|
||||
UFLAG_IF {
|
||||
LDEORALH(x5, x1, wback);
|
||||
emit_xor16(dyn, ninst, x1, x5, x3, x4);
|
||||
} else {
|
||||
STEORLH(x5, wback);
|
||||
}
|
||||
} else {
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_xor16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
SMDMB();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 7: //CMP
|
||||
@@ -348,7 +449,6 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
break;
|
||||
}
|
||||
SMDMB();
|
||||
break;
|
||||
|
||||
case 0xFF:
|
||||
@@ -358,7 +458,6 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
case 0: // INC Ew
|
||||
INST_NAME("LOCK INC Ew");
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
|
||||
SMDMB();
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
UXTHw(x6, ed);
|
||||
@@ -366,18 +465,27 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
BFIx(ed, x6, 0, 16);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_inc16(dyn, ninst, x1, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
if(arm64_atomics) {
|
||||
MOV32w(x3, 1);
|
||||
UFLAG_IF {
|
||||
LDADDALH(x3, x1, wback);
|
||||
emit_inc16(dyn, ninst, x1, x3, x4);
|
||||
} else {
|
||||
STADDLH(x3, wback);
|
||||
}
|
||||
} else {
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_inc16(dyn, ninst, x1, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
SMDMB();
|
||||
}
|
||||
SMDMB();
|
||||
break;
|
||||
case 1: //DEC Ew
|
||||
INST_NAME("LOCK DEC Ew");
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
|
||||
SMDMB();
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
UXTHw(x6, ed);
|
||||
@@ -385,13 +493,23 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
BFIx(ed, x6, 0, 16);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_dec16(dyn, ninst, x1, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
if(arm64_atomics) {
|
||||
MOV32w(x3, -1);
|
||||
UFLAG_IF {
|
||||
LDADDALH(x3, x1, wback);
|
||||
emit_dec16(dyn, ninst, x1, x3, x4);
|
||||
} else {
|
||||
STADDLH(x3, wback);
|
||||
}
|
||||
} else {
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_dec16(dyn, ninst, x1, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
SMDMB();
|
||||
}
|
||||
SMDMB();
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box64context.h"
|
||||
#include "dynarec.h"
|
||||
#include "emu/x64emu_private.h"
|
||||
#include "emu/x64run_private.h"
|
||||
#include "x64run.h"
|
||||
#include "x64emu.h"
|
||||
#include "box64stack.h"
|
||||
#include "callback.h"
|
||||
#include "emu/x64run_private.h"
|
||||
#include "x64trace.h"
|
||||
#include "dynarec_native.h"
|
||||
|
||||
#include "arm64_printer.h"
|
||||
#include "dynarec_arm64_private.h"
|
||||
#include "dynarec_arm64_functions.h"
|
||||
#include "dynarec_arm64_helper.h"
|
||||
#include "emu/x64compstrings.h"
|
||||
|
||||
uintptr_t dynarec64_66F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)need_epilog;
|
||||
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop, u8;
|
||||
int32_t i32;
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback, wb1, wb2;
|
||||
uint8_t eb1, eb2;
|
||||
int64_t j64;
|
||||
uint64_t tmp64u, tmp64u2;
|
||||
int v0, v1;
|
||||
int q0, q1;
|
||||
int d0, d1;
|
||||
int64_t fixedaddress;
|
||||
int unscaled;
|
||||
|
||||
MAYUSE(d0);
|
||||
MAYUSE(d1);
|
||||
MAYUSE(q0);
|
||||
MAYUSE(q1);
|
||||
MAYUSE(eb1);
|
||||
MAYUSE(eb2);
|
||||
MAYUSE(j64);
|
||||
#if STEP > 1
|
||||
static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
|
||||
static const int8_t mask_string8[] = { 7, 6, 5, 4, 3, 2, 1, 0 };
|
||||
static const int8_t mask_string16[] = { 15, 14, 13, 12, 11, 10, 9, 8 };
|
||||
static const int8_t round_round[] = { 0, 2, 1, 3};
|
||||
#endif
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x38: // SSE 4.x
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
|
||||
case 0xF1:
|
||||
INST_NAME("CRC32 Gd, Ew");
|
||||
nextop = F8;
|
||||
GETEW(x1, 0);
|
||||
GETGD;
|
||||
if(arm64_crc32) {
|
||||
CRC32CH(gd, gd, ed);
|
||||
} else {
|
||||
MOV32w(x2, 0x82f63b78);
|
||||
for(int j=0; j<2; ++j) {
|
||||
UBFXxw(x3, ed, 8*j, 8);
|
||||
EORw_REG(gd, gd, x3);
|
||||
for(int i=0; i<8; ++i) {
|
||||
LSRw_IMM((i&1)?gd:x4, (i&1)?x4:gd, 1);
|
||||
TBZ((i&1)?x4:gd, 0, 4+4);
|
||||
EORw_REG((i&1)?gd:x4, (i&1)?gd:x4, x2);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box64context.h"
|
||||
#include "dynarec.h"
|
||||
#include "emu/x64emu_private.h"
|
||||
#include "emu/x64run_private.h"
|
||||
#include "x64run.h"
|
||||
#include "x64emu.h"
|
||||
#include "box64stack.h"
|
||||
#include "callback.h"
|
||||
#include "emu/x64run_private.h"
|
||||
#include "x64trace.h"
|
||||
#include "dynarec_native.h"
|
||||
|
||||
#include "arm64_printer.h"
|
||||
#include "dynarec_arm64_private.h"
|
||||
#include "dynarec_arm64_functions.h"
|
||||
#include "dynarec_arm64_helper.h"
|
||||
#include "emu/x64compstrings.h"
|
||||
|
||||
uintptr_t dynarec64_66F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)need_epilog;
|
||||
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop, u8;
|
||||
int32_t i32;
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback, wb1, wb2;
|
||||
uint8_t eb1, eb2;
|
||||
int64_t j64;
|
||||
uint64_t tmp64u, tmp64u2;
|
||||
int v0, v1;
|
||||
int q0, q1;
|
||||
int d0, d1;
|
||||
int64_t fixedaddress;
|
||||
int unscaled;
|
||||
|
||||
MAYUSE(d0);
|
||||
MAYUSE(d1);
|
||||
MAYUSE(q0);
|
||||
MAYUSE(q1);
|
||||
MAYUSE(eb1);
|
||||
MAYUSE(eb2);
|
||||
MAYUSE(j64);
|
||||
#if STEP > 1
|
||||
static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
|
||||
static const int8_t mask_string8[] = { 7, 6, 5, 4, 3, 2, 1, 0 };
|
||||
static const int8_t mask_string16[] = { 15, 14, 13, 12, 11, 10, 9, 8 };
|
||||
static const int8_t round_round[] = { 0, 2, 1, 3};
|
||||
#endif
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
Executable → Regular
+76
-7
@@ -166,6 +166,28 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
opcode=F8;
|
||||
switch(opcode) {
|
||||
|
||||
case 0x11:
|
||||
switch(rep) {
|
||||
case 0:
|
||||
INST_NAME("MOVUPS Ex,Gx");
|
||||
nextop = F8;
|
||||
GETG;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
|
||||
if(MODREG) {
|
||||
ed = (nextop&7)+(rex.b<<3);
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, ed);
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
|
||||
VST128(v0, ed, fixedaddress);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x2E:
|
||||
// no special check...
|
||||
case 0x2F:
|
||||
@@ -208,6 +230,20 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
VLD64(v0, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("MOVDQU Gx,Ex");
|
||||
nextop = F8;
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
|
||||
GETGX_empty(v0);
|
||||
VMOVQ(v0, v1);
|
||||
} else {
|
||||
GETGX_empty(v0);
|
||||
SMREAD();
|
||||
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
|
||||
VLD128(v0, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
@@ -240,7 +276,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
if(MODREG) {
|
||||
if(rex.rex) {
|
||||
eb1 = xRAX+(nextop&7)+(rex.b<<3);
|
||||
eb2 = 0; \
|
||||
eb2 = 0;
|
||||
} else {
|
||||
ed = (nextop&7);
|
||||
eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx
|
||||
@@ -725,12 +761,12 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
gb2 = 0;
|
||||
gb1 = xRAX + gd;
|
||||
} else {
|
||||
gb2 = ((gd&4)>>2);
|
||||
gb2 = ((gd&4)<<1);
|
||||
gb1 = xRAX+(gd&3);
|
||||
}
|
||||
if(gb2) {
|
||||
gd = x4;
|
||||
UBFXw(gd, gb1, gb2*8, 8);
|
||||
UBFXw(gd, gb1, gb2, 8);
|
||||
} else {
|
||||
gd = gb1; // no need to extract
|
||||
}
|
||||
@@ -762,7 +798,40 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SMWRITELOCK(lock);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x8A:
|
||||
INST_NAME("MOV Gb, Eb");
|
||||
nextop = F8;
|
||||
if(rex.rex) {
|
||||
gb1 = gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3);
|
||||
gb2=0;
|
||||
} else {
|
||||
gd = (nextop&0x38)>>3;
|
||||
gb1 = xRAX+(gd&3);
|
||||
gb2 = ((gd&4)<<1);
|
||||
}
|
||||
if(MODREG) {
|
||||
if(rex.rex) {
|
||||
wback = xRAX+(nextop&7)+(rex.b<<3);
|
||||
wb2 = 0;
|
||||
} else {
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2);
|
||||
wback = xRAX+(wback&3);
|
||||
}
|
||||
if(wb2) {
|
||||
UBFXw(x4, wback, wb2*8, 8);
|
||||
ed = x4;
|
||||
} else {
|
||||
ed = wback;
|
||||
}
|
||||
} else {
|
||||
addr = geted32(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff, 0, rex, &lock, 0, 0);
|
||||
SMREADLOCK(lock);
|
||||
LDB(x4, wback, fixedaddress);
|
||||
ed = x4;
|
||||
}
|
||||
BFIx(gb1, ed, gb2, 8);
|
||||
break;
|
||||
case 0x8B:
|
||||
INST_NAME("MOV Gd, Ed");
|
||||
nextop=F8;
|
||||
@@ -954,7 +1023,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
GETED32H(x1, 4);
|
||||
i64 = F32S;
|
||||
MOV64xw(x2, i64);
|
||||
emit_test32(dyn, ninst, rex, ed, x2, x3, x4);
|
||||
emit_test32(dyn, ninst, rex, ed, x2, x3, x4, x5);
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("NOT Ed");
|
||||
@@ -972,7 +1041,6 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 4:
|
||||
INST_NAME("MUL EAX, Ed");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
UFLAG_DF(x2, rex.w?d_mul64:d_mul32);
|
||||
GETED32(0);
|
||||
if(rex.w) {
|
||||
if(ed==xRDX) gd=x3; else gd=xRDX;
|
||||
@@ -986,11 +1054,11 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
UFLAG_RES(xRAX);
|
||||
UFLAG_OP1(xRDX);
|
||||
UFLAG_DF(x2, rex.w?d_mul64:d_mul32);
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("IMUL EAX, Ed");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
UFLAG_DF(x2, rex.w?d_imul64:d_imul32);
|
||||
GETED32(0);
|
||||
if(rex.w) {
|
||||
if(ed==xRDX) gd=x3; else gd=xRDX;
|
||||
@@ -1004,6 +1072,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
UFLAG_RES(xRAX);
|
||||
UFLAG_OP1(xRDX);
|
||||
UFLAG_DF(x2, rex.w?d_imul64:d_imul32);
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("DIV Ed");
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box64context.h"
|
||||
#include "dynarec.h"
|
||||
#include "emu/x64emu_private.h"
|
||||
#include "emu/x64run_private.h"
|
||||
#include "x64run.h"
|
||||
#include "x64emu.h"
|
||||
#include "box64stack.h"
|
||||
#include "callback.h"
|
||||
#include "emu/x64run_private.h"
|
||||
#include "x64trace.h"
|
||||
#include "dynarec_native.h"
|
||||
|
||||
#include "arm64_printer.h"
|
||||
#include "dynarec_arm64_private.h"
|
||||
#include "dynarec_arm64_helper.h"
|
||||
#include "dynarec_arm64_functions.h"
|
||||
|
||||
#define GETGm gd = ((nextop&0x38)>>3)
|
||||
|
||||
uintptr_t dynarec64_6764_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)need_epilog;
|
||||
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
uint8_t gd, ed, wback, wb, wb1, wb2, gb1, gb2, eb1, eb2;
|
||||
int64_t fixedaddress;
|
||||
int unscaled;
|
||||
int8_t i8;
|
||||
uint8_t u8;
|
||||
int32_t i32;
|
||||
int64_t j64, i64;
|
||||
int cacheupd = 0;
|
||||
int lock;
|
||||
int v0, v1, s0;
|
||||
MAYUSE(i32);
|
||||
MAYUSE(j64);
|
||||
MAYUSE(v0);
|
||||
MAYUSE(v1);
|
||||
MAYUSE(s0);
|
||||
MAYUSE(lock);
|
||||
MAYUSE(cacheupd);
|
||||
|
||||
if(!rex.is32bits) {
|
||||
// should do a different file
|
||||
DEFAULT;
|
||||
return addr;
|
||||
}
|
||||
|
||||
rep = 0;
|
||||
while((opcode==0xF2) || (opcode==0xF3)) {
|
||||
rep = opcode-0xF1;
|
||||
opcode = F8;
|
||||
}
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0xA3:
|
||||
INST_NAME("MOV Seg:[Od], EAX");
|
||||
i32 = F16;
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
if(i32<4096 && !(i32&3)) {
|
||||
STRw_U12(xRAX, x4, i32);
|
||||
} else if(i32<256) {
|
||||
STURw_I9(xRAX, x4, i32);
|
||||
} else {
|
||||
MOV32w(x1, i32);
|
||||
STRw_REG(xRAX, x4, x1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFF:
|
||||
nextop = F8;
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
switch((nextop>>3)&7) {
|
||||
case 6: // Push Ed
|
||||
INST_NAME("PUSH FS:Ew");
|
||||
if((nextop&0xC0)==0xC0) { // reg
|
||||
DEFAULT;
|
||||
} else { // mem <= i32
|
||||
SMREAD();
|
||||
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0, 0, 0);
|
||||
LDRw_REG(x3, ed, x4);
|
||||
PUSH1_32(x3);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box64context.h"
|
||||
#include "dynarec.h"
|
||||
#include "emu/x64emu_private.h"
|
||||
#include "emu/x64run_private.h"
|
||||
#include "x64run.h"
|
||||
#include "x64emu.h"
|
||||
#include "box64stack.h"
|
||||
#include "callback.h"
|
||||
#include "emu/x64run_private.h"
|
||||
#include "x64trace.h"
|
||||
#include "dynarec_native.h"
|
||||
|
||||
#include "arm64_printer.h"
|
||||
#include "dynarec_arm64_private.h"
|
||||
#include "dynarec_arm64_helper.h"
|
||||
#include "dynarec_arm64_functions.h"
|
||||
|
||||
#define GETGm gd = ((nextop&0x38)>>3)
|
||||
|
||||
uintptr_t dynarec64_67_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)need_epilog;
|
||||
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
uint8_t gd, ed, wback, wb, wb1, wb2, gb1, gb2, eb1, eb2;
|
||||
int64_t fixedaddress;
|
||||
int unscaled;
|
||||
int8_t i8;
|
||||
uint8_t u8;
|
||||
int32_t i32;
|
||||
int64_t j64, i64;
|
||||
int cacheupd = 0;
|
||||
int lock;
|
||||
int v0, v1, s0;
|
||||
MAYUSE(i32);
|
||||
MAYUSE(j64);
|
||||
MAYUSE(v0);
|
||||
MAYUSE(v1);
|
||||
MAYUSE(s0);
|
||||
MAYUSE(lock);
|
||||
MAYUSE(cacheupd);
|
||||
|
||||
if(!rex.is32bits) {
|
||||
// should do a different file
|
||||
DEFAULT;
|
||||
return addr;
|
||||
}
|
||||
|
||||
rep = 0;
|
||||
while((opcode==0xF2) || (opcode==0xF3)) {
|
||||
rep = opcode-0xF1;
|
||||
opcode = F8;
|
||||
}
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 64:
|
||||
addr = dynarec64_6764_32(dyn, addr, ip, ninst, rex, rep, _FS, ok, need_epilog);
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
@@ -108,7 +108,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
FCMPD(v1, v2);
|
||||
}
|
||||
FCOM(x1, x2, x3);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xE0:
|
||||
case 0xE1:
|
||||
@@ -178,7 +178,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
FDIVD(v1, v2, v1);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
@@ -234,7 +234,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
FCMPD(v1, s0);
|
||||
}
|
||||
FCOM(x1, x2, x3);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FSUB ST0, float[ED]");
|
||||
|
||||
@@ -51,7 +51,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
INST_NAME("FLD STx");
|
||||
v2 = x87_do_push(dyn, ninst, x1, X87_ST(nextop&7));
|
||||
X87_PUSH_OR_FAIL(v2, dyn, ninst, x1, X87_ST(nextop&7));
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, (nextop&7)+1, X87_COMBINE(0, (nextop&7)+1));
|
||||
if(ST_IS_F(0)) {
|
||||
FMOVS(v2, v1);
|
||||
@@ -84,7 +84,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0xD8:
|
||||
INST_NAME("FSTPNCE ST0, ST0");
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xD9:
|
||||
case 0xDA:
|
||||
@@ -98,7 +98,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
x87_get_st_empty(dyn, ninst, x1, x2, nextop&7, X87_ST(nextop&7));
|
||||
x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
|
||||
x87_swapreg(dyn, ninst, x1, x2, 0, nextop&7);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xE0:
|
||||
INST_NAME("FCHS");
|
||||
@@ -138,7 +138,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0xE8:
|
||||
INST_NAME("FLD1");
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_F);
|
||||
if(ST_IS_F(0)) {
|
||||
FMOVS_8(v1, 0b01110000);
|
||||
} else {
|
||||
@@ -147,82 +147,123 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0xE9:
|
||||
INST_NAME("FLDL2T");
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
FTABLE64(v1, L2T);
|
||||
break;
|
||||
case 0xEA:
|
||||
case 0xEA:
|
||||
INST_NAME("FLDL2E");
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
FTABLE64(v1, L2E);
|
||||
break;
|
||||
case 0xEB:
|
||||
INST_NAME("FLDPI");
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
FTABLE64(v1, PI);
|
||||
break;
|
||||
case 0xEC:
|
||||
INST_NAME("FLDLG2");
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
FTABLE64(v1, LG2);
|
||||
break;
|
||||
case 0xED:
|
||||
INST_NAME("FLDLN2");
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
FTABLE64(v1, LN2);
|
||||
break;
|
||||
case 0xEE:
|
||||
INST_NAME("FLDZ");
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_F);
|
||||
VEOR(v1, v1, v1);
|
||||
break;
|
||||
|
||||
case 0xF0:
|
||||
INST_NAME("F2XM1");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
i1 = x87_stackcount(dyn, ninst, x1);
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
CALL(native_f2xm1, -1);
|
||||
x87_unstackcount(dyn, ninst, x1, i1);
|
||||
break;
|
||||
case 0xF1:
|
||||
INST_NAME("FYL2X");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
i1 = x87_stackcount(dyn, ninst, x1);
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(native_fyl2x, -1);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
x87_unstackcount(dyn, ninst, x1, i1);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xF2:
|
||||
INST_NAME("FPTAN");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
i1 = x87_stackcount(dyn, ninst, x1);
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
CALL(native_ftan, -1);
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
|
||||
if(ST_IS_F(0)) {
|
||||
FMOVS_8(v1, 0b01110000);
|
||||
x87_unstackcount(dyn, ninst, x1, i1);
|
||||
if(PK(0)==0xdd && PK(1)==0xd8) {
|
||||
MESSAGE(LOG_DUMP, "Optimized next DD D8 fstp st0, st0, not emiting 1\n");
|
||||
u8 = F8;
|
||||
u8 = F8;
|
||||
} else {
|
||||
FMOVD_8(v1, 0b01110000);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_F);
|
||||
if(ST_IS_F(0)) {
|
||||
FMOVS_8(v1, 0b01110000);
|
||||
} else {
|
||||
FMOVD_8(v1, 0b01110000);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xF3:
|
||||
INST_NAME("FPATAN");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
i1 = x87_stackcount(dyn, ninst, x1);
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(native_fpatan, -1);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
x87_unstackcount(dyn, ninst, x1, i1);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xF4:
|
||||
INST_NAME("FXTRACT");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_do_push_empty(dyn, ninst, 0);
|
||||
X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, 0);
|
||||
i1 = x87_stackcount(dyn, ninst, x1);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(native_fxtract, -1);
|
||||
x87_unstackcount(dyn, ninst, x1, i1);
|
||||
break;
|
||||
case 0xF5:
|
||||
INST_NAME("FPREM1");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
#if 0
|
||||
i1 = x87_stackcount(dyn, ninst, x1);
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(native_fprem1, -1);
|
||||
x87_unstackcount(dyn, ninst, x1, i1);
|
||||
#else
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
FDIVD(s0, v1, v2);
|
||||
FRINTRRD(s0, s0, 0b00); // Nearest == TieToEven?
|
||||
FCVTZSxD(x4, s0);
|
||||
FMULD(s0, s0, v2);
|
||||
FSUBD(v1, v1, s0);
|
||||
LDRw_U12(x1, xEmu, offsetof(x64emu_t, sw));
|
||||
// set C2 = 0
|
||||
BFCw(x1, 10, 1);
|
||||
// set C1 = Q0
|
||||
BFIw(x1, x4, 9, 1);
|
||||
// set C3 = Q1
|
||||
LSRx_IMM(x4, x4, 1);
|
||||
BFIw(x1, x4, 14, 1);
|
||||
// Set C0 = Q2
|
||||
LSRx(x4, x4, 1);
|
||||
BFIw(x1, x4, 8, 1);
|
||||
STRw_U12(x1, xEmu, offsetof(x64emu_t, sw));
|
||||
#endif
|
||||
break;
|
||||
case 0xF6:
|
||||
INST_NAME("FDECSTP");
|
||||
@@ -242,18 +283,45 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0xF8:
|
||||
INST_NAME("FPREM");
|
||||
#if 0
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
i1 = x87_stackcount(dyn, ninst, x1);
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(native_fprem, -1);
|
||||
x87_unstackcount(dyn, ninst, x1, i1);
|
||||
#else
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
FDIVD(s0, v1, v2);
|
||||
FRINTZD(s0, s0);
|
||||
FCVTZSxD(x4, s0);
|
||||
FMULD(s0, s0, v2);
|
||||
FSUBD(v1, v1, s0);
|
||||
LDRw_U12(x1, xEmu, offsetof(x64emu_t, sw));
|
||||
// set C2 = 0
|
||||
BFCw(x1, 10, 1);
|
||||
// set C1 = Q0
|
||||
BFIw(x1, x4, 9, 1);
|
||||
// set C3 = Q1
|
||||
LSRx_IMM(x4, x4, 1);
|
||||
BFIw(x1, x4, 14, 1);
|
||||
// Set C0 = Q2
|
||||
LSRx(x4, x4, 1);
|
||||
BFIw(x1, x4, 8, 1);
|
||||
STRw_U12(x1, xEmu, offsetof(x64emu_t, sw));
|
||||
#endif
|
||||
break;
|
||||
case 0xF9:
|
||||
INST_NAME("FYL2XP1");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
i1 = x87_stackcount(dyn, ninst, x1);
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(native_fyl2xp1, -1);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
x87_unstackcount(dyn, ninst, x1, i1);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xFA:
|
||||
INST_NAME("FSQRT");
|
||||
@@ -267,9 +335,11 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0xFB:
|
||||
INST_NAME("FSINCOS");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_do_push_empty(dyn, ninst, 0);
|
||||
X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, 0);
|
||||
i1 = x87_stackcount(dyn, ninst, x1);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(native_fsincos, -1);
|
||||
x87_unstackcount(dyn, ninst, x1, i1);
|
||||
break;
|
||||
case 0xFC:
|
||||
INST_NAME("FRNDINT");
|
||||
@@ -292,21 +362,27 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0xFD:
|
||||
INST_NAME("FSCALE");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
i1 = x87_stackcount(dyn, ninst, x1);
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(native_fscale, -1);
|
||||
x87_unstackcount(dyn, ninst, x1, i1);
|
||||
break;
|
||||
case 0xFE:
|
||||
INST_NAME("FSIN");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
i1 = x87_stackcount(dyn, ninst, x1);
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
CALL(native_fsin, -1);
|
||||
x87_unstackcount(dyn, ninst, x1, i1);
|
||||
break;
|
||||
case 0xFF:
|
||||
INST_NAME("FCOS");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
i1 = x87_stackcount(dyn, ninst, x1);
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
CALL(native_fcos, -1);
|
||||
x87_unstackcount(dyn, ninst, x1, i1);
|
||||
break;
|
||||
|
||||
|
||||
@@ -322,12 +398,12 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0xEF:
|
||||
DEFAULT;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FLD ST0, float[ED]");
|
||||
v1 = x87_do_push(dyn, ninst, x1, box64_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, box64_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
|
||||
VLD32(v1, ed, fixedaddress);
|
||||
if(!ST_IS_F(0)) {
|
||||
@@ -354,7 +430,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
FCVT_S_D(v1, v1);
|
||||
}
|
||||
VST32(v1, ed, fixedaddress);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FLDENV Ed");
|
||||
|
||||
@@ -0,0 +1,239 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box64context.h"
|
||||
#include "dynarec.h"
|
||||
#include "emu/x64emu_private.h"
|
||||
#include "emu/x64run_private.h"
|
||||
#include "x64run.h"
|
||||
#include "x64emu.h"
|
||||
#include "box64stack.h"
|
||||
#include "callback.h"
|
||||
#include "emu/x64run_private.h"
|
||||
#include "x64trace.h"
|
||||
#include "emu/x87emu_private.h"
|
||||
#include "dynarec_native.h"
|
||||
|
||||
#include "arm64_printer.h"
|
||||
#include "dynarec_arm64_private.h"
|
||||
#include "dynarec_arm64_helper.h"
|
||||
#include "dynarec_arm64_functions.h"
|
||||
|
||||
|
||||
uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
uint8_t nextop = F8;
|
||||
int64_t j64;
|
||||
uint8_t ed;
|
||||
uint8_t wback;
|
||||
int v1, v2;
|
||||
int d0;
|
||||
int s0;
|
||||
int64_t fixedaddress;
|
||||
int unscaled;
|
||||
|
||||
MAYUSE(s0);
|
||||
MAYUSE(d0);
|
||||
MAYUSE(v2);
|
||||
MAYUSE(v1);
|
||||
MAYUSE(ed);
|
||||
MAYUSE(j64);
|
||||
|
||||
switch(nextop) {
|
||||
case 0xC0:
|
||||
case 0xC1:
|
||||
case 0xC2:
|
||||
case 0xC3:
|
||||
case 0xC4:
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
INST_NAME("FCMOVB ST0, STx");
|
||||
READFLAGS(X_CF);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
TSTw_mask(xFlags, 0, 0); //mask=1<<F_CF
|
||||
if(ST_IS_F(0)) {
|
||||
FCSELS(v1, v2, v1, cNE); // F_CF==1
|
||||
} else {
|
||||
FCSELD(v1, v2, v1, cNE); // F_CF==1
|
||||
}
|
||||
break;
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
case 0xCA:
|
||||
case 0xCB:
|
||||
case 0xCC:
|
||||
case 0xCD:
|
||||
case 0xCE:
|
||||
case 0xCF:
|
||||
INST_NAME("FCMOVE ST0, STx");
|
||||
READFLAGS(X_ZF);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
TSTw_mask(xFlags, 0b011010, 0); //mask=1<<F_ZF
|
||||
if(ST_IS_F(0)) {
|
||||
FCSELS(v1, v2, v1, cNE);
|
||||
} else {
|
||||
FCSELD(v1, v2, v1, cNE); // F_ZF==0
|
||||
}
|
||||
break;
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
case 0xD2:
|
||||
case 0xD3:
|
||||
case 0xD4:
|
||||
case 0xD5:
|
||||
case 0xD6:
|
||||
case 0xD7:
|
||||
INST_NAME("FCMOVBE ST0, STx");
|
||||
READFLAGS(X_CF|X_ZF);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
MOV32w(x1, (1<<F_CF)|(1<<F_ZF));
|
||||
TSTw_REG(xFlags, x1);
|
||||
if(ST_IS_F(0)) {
|
||||
FCSELS(v1, v2, v1, cNE);
|
||||
} else {
|
||||
FCSELD(v1, v2, v1, cNE); // F_CF==0 & F_ZF==0
|
||||
}
|
||||
break;
|
||||
case 0xD8:
|
||||
case 0xD9:
|
||||
case 0xDA:
|
||||
case 0xDB:
|
||||
case 0xDC:
|
||||
case 0xDD:
|
||||
case 0xDE:
|
||||
case 0xDF:
|
||||
INST_NAME("FCMOVU ST0, STx");
|
||||
READFLAGS(X_PF);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
TSTw_mask(xFlags, 0b011110, 0); //mask=1<<F_PF
|
||||
if(ST_IS_F(0)) {
|
||||
FCSELS(v1, v2, v1, cNE);
|
||||
} else {
|
||||
FCSELD(v1, v2, v1, cNE); // F_PF==0
|
||||
}
|
||||
break;
|
||||
case 0xE9:
|
||||
INST_NAME("FUCOMPP ST0, ST1");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 1, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
FCMPS(v1, v2);
|
||||
} else {
|
||||
FCMPD(v1, v2);
|
||||
}
|
||||
FCOM(x1, x2, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
|
||||
case 0xE4:
|
||||
case 0xF0:
|
||||
case 0xF1:
|
||||
case 0xF4:
|
||||
case 0xF5:
|
||||
case 0xF6:
|
||||
case 0xF7:
|
||||
case 0xF8:
|
||||
case 0xF9:
|
||||
case 0xFD:
|
||||
DEFAULT;
|
||||
break;
|
||||
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FIADD ST0, Ed");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
|
||||
VLD32(v2, ed, fixedaddress);
|
||||
SXTL_32(v2, v2); // i32 -> i64
|
||||
SCVTFDD(v2, v2); // i64 -> double
|
||||
FADDD(v1, v1, v2);
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("FIMUL ST0, Ed");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
|
||||
VLD32(v2, ed, fixedaddress);
|
||||
SXTL_32(v2, v2); // i32 -> i64
|
||||
SCVTFDD(v2, v2); // i64 -> double
|
||||
FMULD(v1, v1, v2);
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("FICOM ST0, Ed");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
|
||||
VLD32(v2, ed, fixedaddress);
|
||||
SXTL_32(v2, v2); // i32 -> i64
|
||||
SCVTFDD(v2, v2); // i64 -> double
|
||||
FCMPD(v1, v2);
|
||||
FCOM(x1, x2, x3);
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("FICOMP ST0, Ed");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
|
||||
VLD32(v2, ed, fixedaddress);
|
||||
SXTL_32(v2, v2); // i32 -> i64
|
||||
SCVTFDD(v2, v2); // i64 -> double
|
||||
FCMPD(v1, v2);
|
||||
FCOM(x1, x2, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FISUB ST0, Ed");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
|
||||
VLD32(v2, ed, fixedaddress);
|
||||
SXTL_32(v2, v2); // i32 -> i64
|
||||
SCVTFDD(v2, v2); // i64 -> double
|
||||
FSUBD(v1, v1, v2);
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("FISUBR ST0, Ed");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
|
||||
VLD32(v2, ed, fixedaddress);
|
||||
SXTL_32(v2, v2); // i32 -> i64
|
||||
SCVTFDD(v2, v2); // i64 -> double
|
||||
FSUBD(v1, v2, v1);
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("FIDIV ST0, Ed");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
|
||||
VLD32(v2, ed, fixedaddress);
|
||||
SXTL_32(v2, v2); // i32 -> i64
|
||||
SCVTFDD(v2, v2); // i64 -> double
|
||||
FDIVD(v1, v1, v2);
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FIDIVR ST0, Ed");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
|
||||
VLD32(v2, ed, fixedaddress);
|
||||
SXTL_32(v2, v2); // i32 -> i64
|
||||
SCVTFDD(v2, v2); // i64 -> double
|
||||
FDIVD(v1, v2, v1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
FCOMI(x1, x2);
|
||||
break;
|
||||
case 0xF0:
|
||||
case 0xF0:
|
||||
case 0xF1:
|
||||
case 0xF2:
|
||||
case 0xF3:
|
||||
@@ -188,7 +188,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FILD ST0, Ed");
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
|
||||
VLD32(v1, ed, fixedaddress);
|
||||
SXTL_32(v1, v1); // i32 -> i64
|
||||
@@ -218,7 +218,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
STW(x5, wback, fixedaddress);
|
||||
MARK3;
|
||||
#endif
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("FIST Ed, ST0");
|
||||
@@ -273,7 +273,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
MARK3;
|
||||
#endif
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("FLD tbyte");
|
||||
@@ -296,13 +296,13 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
STRH_U12(x6, ed, 8);
|
||||
} else {
|
||||
if(box64_x87_no80bits) {
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
VLDR64_U12(v1, ed, fixedaddress);
|
||||
} else {
|
||||
if(ed!=x1) {
|
||||
MOVx_REG(x1, ed);
|
||||
}
|
||||
x87_do_push_empty(dyn, ninst, x3);
|
||||
X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, x3);
|
||||
CALL(native_fld, -1);
|
||||
}
|
||||
}
|
||||
@@ -344,7 +344,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
CMPSw_REG(x3, x4);
|
||||
B_MARK2(cNE);
|
||||
// NaN and Infinite
|
||||
ORRw_mask(x3, x5, 0, 0b1110); //x3 = sign | 0x7fff
|
||||
ORRw_mask(x3, x5, 0, 0b1110); //x3 = sign | 0x7fff
|
||||
TSTx_mask(x1, 1, 0, 0b110011); //0x000fffffffffffffL
|
||||
ORRx_mask(x5, xZR, 1, 1, 0); //0x8000000000000000
|
||||
ORRx_mask(x4, xZR, 1, 0b10, 0b01); //0xc000000000000000
|
||||
@@ -372,7 +372,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
STRH_U12(x3, wback, 8);
|
||||
#endif
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
|
||||
@@ -106,7 +106,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
FCMPD(v1, v2);
|
||||
}
|
||||
FCOM(x1, x2, x3);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xE0:
|
||||
case 0xE1:
|
||||
@@ -158,7 +158,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
FDIVD(v1, v2, v1);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case 0xF8:
|
||||
case 0xF9:
|
||||
case 0xFA:
|
||||
@@ -211,7 +211,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
VLD64(v2, wback, fixedaddress);
|
||||
FCMPD(v1, v2);
|
||||
FCOM(x1, x2, x3);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FSUB ST0, double[ED]");
|
||||
|
||||
@@ -74,7 +74,7 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0xD8:
|
||||
INST_NAME("FSTP ST0, ST0");
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xD9:
|
||||
case 0xDA:
|
||||
@@ -88,7 +88,7 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
x87_get_st_empty(dyn, ninst, x1, x2, nextop&7, X87_ST(nextop&7));
|
||||
x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
|
||||
x87_swapreg(dyn, ninst, x1, x2, 0, nextop&7);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
|
||||
case 0xE0:
|
||||
@@ -126,7 +126,7 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
FCMPD(v1, v2);
|
||||
}
|
||||
FCOM(x1, x2, x3);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
|
||||
case 0xC8:
|
||||
@@ -160,34 +160,38 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FLD double");
|
||||
v1 = x87_do_push(dyn, ninst, x3, NEON_CACHE_ST_D);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x3, NEON_CACHE_ST_D);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
VLD64(v1, ed, fixedaddress);
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("FISTTP i64, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_I64);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
#if 0
|
||||
// those are ARM 8.5 opcode!
|
||||
FRINT64ZD(s0, v1);
|
||||
FCVTZSxD(x2, s0);
|
||||
STRx_U12(x2, ed, fixedaddress);
|
||||
#else
|
||||
MRS_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
FRINTRRD(s0, v1, 3);
|
||||
FCVTZSxD(x2, s0);
|
||||
STx(x2, ed, fixedaddress);
|
||||
MRS_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_MARK3(x5, FPSR_IOC);
|
||||
ORRx_mask(x5, xZR, 1, 1, 0); //0x8000000000000000
|
||||
STx(x5, ed, fixedaddress);
|
||||
MARK3;
|
||||
#endif
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
if(ST_IS_I64(0)) {
|
||||
VST64(v1, ed, fixedaddress);
|
||||
} else {
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
#if 0
|
||||
// those are ARM 8.5 opcode!
|
||||
FRINT64ZD(s0, v1);
|
||||
FCVTZSxD(x2, s0);
|
||||
STRx_U12(x2, ed, fixedaddress);
|
||||
#else
|
||||
MRS_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
FRINTRRD(s0, v1, 3);
|
||||
FCVTZSxD(x2, s0);
|
||||
STx(x2, ed, fixedaddress);
|
||||
MRS_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_MARK3(x5, FPSR_IOC);
|
||||
ORRx_mask(x5, xZR, 1, 1, 0); //0x8000000000000000
|
||||
STx(x5, ed, fixedaddress);
|
||||
MARK3;
|
||||
#endif
|
||||
}
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("FST double");
|
||||
@@ -200,9 +204,9 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
VST64(v1, ed, fixedaddress);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 4:
|
||||
case 4:
|
||||
INST_NAME("FRSTOR m108byte");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
|
||||
@@ -210,7 +214,7 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
if(ed!=x1) {MOVx_REG(x1, ed);}
|
||||
CALL(native_frstor, -1);
|
||||
break;
|
||||
case 6:
|
||||
case 6:
|
||||
INST_NAME("FSAVE m108byte");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
|
||||
@@ -220,7 +224,7 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FNSTSW m2byte");
|
||||
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
|
||||
//fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x4, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
|
||||
LDRw_U12(x2, xEmu, offsetof(x64emu_t, top));
|
||||
LDRH_U12(x3, xEmu, offsetof(x64emu_t, sw));
|
||||
@@ -234,6 +238,7 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
ANDw_mask(x2, x2, 0, 2);
|
||||
}
|
||||
BFIw(x3, x2, 11, 3); // inject TOP at bit 11 (3 bits)
|
||||
STRH_U12(x3, xEmu, offsetof(x64emu_t, sw));
|
||||
STH(x3, ed, fixedaddress); // store whole sw flags
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -53,7 +53,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
FADDD(v1, v1, v2);
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
@@ -71,7 +71,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
FMULD(v1, v1, v2);
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
@@ -90,7 +90,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
FCMPD(v1, v2);
|
||||
}
|
||||
FCOM(x1, x2, x3);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xD9:
|
||||
INST_NAME("FCOMPP ST0, STx");
|
||||
@@ -102,8 +102,8 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
FCMPD(v1, v2);
|
||||
}
|
||||
FCOM(x1, x2, x3);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xE0:
|
||||
case 0xE1:
|
||||
@@ -121,7 +121,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
FSUBD(v1, v2, v1);
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xE8:
|
||||
case 0xE9:
|
||||
@@ -139,7 +139,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
FSUBD(v1, v1, v2);
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xF0:
|
||||
case 0xF1:
|
||||
@@ -157,8 +157,8 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
FDIVD(v1, v2, v1);
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
break;
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xF8:
|
||||
case 0xF9:
|
||||
case 0xFA:
|
||||
@@ -175,7 +175,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
FDIVD(v1, v1, v2);
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xD8:
|
||||
case 0xDA:
|
||||
@@ -184,7 +184,8 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0xDD:
|
||||
case 0xDE:
|
||||
case 0xDF:
|
||||
return 0;
|
||||
DEFAULT;
|
||||
break;
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
@@ -232,7 +233,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SCVTFDD(v2, v2);
|
||||
FCMPD(v1, v2);
|
||||
FCOM(x1, x2, x3);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FISUB ST0, word[ED]");
|
||||
|
||||
@@ -34,6 +34,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
int64_t j64;
|
||||
int64_t fixedaddress;
|
||||
int unscaled;
|
||||
int i1;
|
||||
|
||||
MAYUSE(s0);
|
||||
MAYUSE(v2);
|
||||
@@ -51,12 +52,20 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0xC7:
|
||||
INST_NAME("FFREEP STx");
|
||||
// not handling Tag...
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
|
||||
case 0xE0:
|
||||
INST_NAME("FNSTSW AX");
|
||||
LDRw_U12(x2, xEmu, offsetof(x64emu_t, top));
|
||||
if(dyn->n.x87stack) {
|
||||
if(dyn->n.x87stack>0) {
|
||||
SUBw_U12(x2, x2, dyn->n.x87stack);
|
||||
} else {
|
||||
ADDw_U12(x2, x2, -dyn->n.x87stack);
|
||||
}
|
||||
ANDw_mask(x2, x2, 0, 2); //mask=7
|
||||
}
|
||||
LDRH_U12(x1, xEmu, offsetof(x64emu_t, sw));
|
||||
BFIw(x1, x2, 11, 3); // inject top
|
||||
STRH_U12(x1, xEmu, offsetof(x64emu_t, sw));
|
||||
@@ -81,7 +90,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
FCMPD(v1, v2);
|
||||
}
|
||||
FCOMI(x1, x2);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xF0:
|
||||
case 0xF1:
|
||||
@@ -102,7 +111,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
FCMPD(v1, v2);
|
||||
}
|
||||
FCOMI(x1, x2);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
|
||||
case 0xC8:
|
||||
@@ -151,7 +160,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FILD ST0, Ew");
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_F);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
|
||||
LDSHw(x1, wback, fixedaddress);
|
||||
if(ST_IS_F(0)) {
|
||||
@@ -196,7 +205,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
MARK3;
|
||||
STH(x3, wback, fixedaddress);
|
||||
#endif
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("FIST Ew, ST0");
|
||||
@@ -275,19 +284,19 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
MARK3;
|
||||
STH(x3, wback, fixedaddress);
|
||||
#endif
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FBLD ST0, tbytes");
|
||||
x87_do_push_empty(dyn, ninst, x1);
|
||||
X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, x1);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
|
||||
if(ed!=x1) {MOVx_REG(x1, ed);}
|
||||
CALL(fpu_fbld, -1);
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("FILD ST0, i64");
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_I64);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_I64);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
VLD64(v1, wback, fixedaddress);
|
||||
if(!ST_IS_I64(0)) {
|
||||
@@ -315,11 +324,13 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("FBSTP tbytes, ST0");
|
||||
i1 = x87_stackcount(dyn, ninst, x1);
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
|
||||
if(ed!=x1) {MOVx_REG(x1, ed);}
|
||||
CALL(fpu_fbst, -1);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
x87_unstackcount(dyn, ninst, x1, i1);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FISTP i64, ST0");
|
||||
@@ -375,7 +386,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
#endif
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
|
||||
Executable → Regular
+6
-54
@@ -230,15 +230,7 @@ void emit_or8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
|
||||
BICw(xFlags, xFlags, s3);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTw_REG(s1, s1);
|
||||
CSETw(s3, cEQ);
|
||||
BFIw(xFlags, s3, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRw(s3, s1, 7);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
COMP_ZFSF(s1, 8)
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
@@ -261,15 +253,7 @@ void emit_or8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
|
||||
BICw(xFlags, xFlags, s3);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTw_REG(s1, s1);
|
||||
CSETw(s3, cEQ);
|
||||
BFIw(xFlags, s3, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRw(s3, s1, 7);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
COMP_ZFSF(s1, 8)
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
@@ -292,15 +276,7 @@ void emit_xor8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
|
||||
BICw(xFlags, xFlags, s3);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTw_REG(s1, s1);
|
||||
CSETw(s3, cEQ);
|
||||
BFIw(xFlags, s3, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRw(s3, s1, 7);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
COMP_ZFSF(s1, 8)
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
@@ -323,15 +299,7 @@ void emit_xor8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
|
||||
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
|
||||
BICw(xFlags, xFlags, s3);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTw_REG(s1, s1);
|
||||
CSETw(s3, cEQ);
|
||||
BFIw(xFlags, s3, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRw(s3, s1, 7);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
COMP_ZFSF(s1, 8)
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
@@ -423,15 +391,7 @@ void emit_or16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
|
||||
BICw(xFlags, xFlags, s3);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
ANDSw_mask(s1, s1, 0, 15); //mask=0xffff
|
||||
CSETw(s3, cEQ);
|
||||
BFIw(xFlags, s3, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRw(s3, s1, 15);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
COMP_ZFSF(s1, 16)
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
@@ -500,15 +460,7 @@ void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
|
||||
BICw(xFlags, xFlags, s3);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
ANDSw_mask(s1, s1, 0, 15); //mask=0xffff
|
||||
CSETw(s3, cEQ);
|
||||
BFIw(xFlags, s3, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRw(s3, s1, 15);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
COMP_ZFSF(s1, 16)
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
|
||||
Executable → Regular
+16
-114
@@ -303,15 +303,7 @@ void emit_add8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
IFX(X_PEND) {
|
||||
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
ANDSw_mask(s1, s1, 0, 7); //mask=0xff
|
||||
CSETw(s3, cEQ);
|
||||
BFIw(xFlags, s3, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRw(s3, s1, 7);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
COMP_ZFSF(s1, 8)
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
@@ -329,7 +321,7 @@ void emit_add8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
SET_DFNONE(s3);
|
||||
}
|
||||
IFX(X_AF | X_OF) {
|
||||
if(X_PEND) {} else {MOV32w(s4, c&0xff);}
|
||||
IFX(X_PEND) {} else {MOV32w(s4, c&0xff);}
|
||||
ORRw_REG(s3, s1, s4); // s3 = op1 | op2
|
||||
ANDw_REG(s4, s1, s4); // s4 = op1 & op2
|
||||
}
|
||||
@@ -355,15 +347,7 @@ void emit_add8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
IFX(X_PEND) {
|
||||
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
ANDSw_mask(s1, s1, 0, 0b000111); //mask=000000ff
|
||||
CSETw(s3, cEQ);
|
||||
BFIw(xFlags, s3, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRw(s3, s1, 7);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
COMP_ZFSF(s1, 8)
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
@@ -407,15 +391,7 @@ void emit_sub8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
BFIw(xFlags, s4, F_OF, 1); // OF: ((bc >> 6) ^ ((bc>>6)>>1)) & 1
|
||||
}
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
ANDSw_mask(s1, s1, 0, 7); //mask=0xff
|
||||
CSETw(s3, cEQ);
|
||||
BFIw(xFlags, s3, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRw(s3, s1, 7);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
COMP_ZFSF(s1, 8)
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
@@ -465,15 +441,7 @@ void emit_sub8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4, in
|
||||
BFIw(xFlags, s4, F_OF, 1); // OF: ((bc >> 6) ^ ((bc>>6)>>1)) & 1
|
||||
}
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
ANDSw_mask(s1, s1, 0, 0b000111); //mask=000000ff
|
||||
CSETw(s3, cEQ);
|
||||
BFIw(xFlags, s3, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRw(s3, s1, 7);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
COMP_ZFSF(s1, 8)
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
@@ -516,15 +484,7 @@ void emit_add16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
IFX(X_PEND) {
|
||||
STRw_U12(s1, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
ANDSw_mask(s1, s1, 0, 15); //mask=0xffff
|
||||
CSETw(s3, cEQ);
|
||||
BFIw(xFlags, s3, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRw(s3, s1, 15);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
COMP_ZFSF(s1, 16)
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
@@ -634,15 +594,7 @@ void emit_sub16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
BFIw(xFlags, s4, F_OF, 1); // OF: ((bc >> 14) ^ ((bc>>14)>>1)) & 1
|
||||
}
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
ANDSw_mask(s1, s1, 0, 15); //mask=0xffff
|
||||
CSETw(s3, cEQ);
|
||||
BFIw(xFlags, s3, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRw(s3, s1, 15);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
COMP_ZFSF(s1, 16)
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
@@ -792,16 +744,7 @@ void emit_inc8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
BFIw(xFlags, s4, F_OF, 1); // OF: ((bc >> 6) ^ ((bc>>6)>>1)) & 1
|
||||
}
|
||||
}
|
||||
|
||||
IFX(X_ZF) {
|
||||
ANDSw_mask(s1, s1, 0, 7); //mask=0xff
|
||||
CSETw(s3, cEQ);
|
||||
BFIw(xFlags, s3, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRw(s3, s1, 7);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
COMP_ZFSF(s1, 8)
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
@@ -838,15 +781,7 @@ void emit_inc16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
BFIw(xFlags, s4, F_OF, 1); // OF: ((bc >> 14) ^ ((bc>>14)>>1)) & 1
|
||||
}
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTw_mask(s1, 0, 0b001111); // mask=0xffff
|
||||
CSETw(s3, cEQ);
|
||||
BFIw(xFlags, s3, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRw(s3, s1, 15);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
COMP_ZFSF(s1, 16)
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
@@ -906,7 +841,7 @@ void emit_dec32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4
|
||||
void emit_dec8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
STRB_U12(s3, xEmu, offsetof(x64emu_t, op2));
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
SET_DF(s3, d_dec8);
|
||||
} else IFX(X_ZF|X_OF|X_AF|X_SF|X_PF) {
|
||||
SET_DFNONE(s3);
|
||||
@@ -1162,15 +1097,7 @@ void emit_adc8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
LSRw(s3, s1, 8);
|
||||
BFIw(xFlags, s3, F_CF, 1);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
ANDSw_mask(s1, s1, 0, 7); //mask=0xff
|
||||
CSETw(s3, cEQ);
|
||||
BFIw(xFlags, s3, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRw(s3, s1, 7);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
COMP_ZFSF(s1, 8)
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
@@ -1224,15 +1151,7 @@ void emit_adc16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
LSRw(s3, s1, 16);
|
||||
BFIw(xFlags, s3, F_CF, 1);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
ANDSw_mask(s1, s1, 0, 15); //mask=0xffff
|
||||
CSETw(s3, cEQ);
|
||||
BFIw(xFlags, s3, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRw(s3, s1, 15);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
COMP_ZFSF(s1, 16)
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
@@ -1474,15 +1393,7 @@ void emit_sbb8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
BFIw(xFlags, s4, F_OF, 1); // OF: ((bc >> 6) ^ ((bc>>6)>>1)) & 1
|
||||
}
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
ANDSw_mask(s1, s1, 0, 7); //mask=0xff
|
||||
CSETw(s3, cEQ);
|
||||
BFIw(xFlags, s3, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRw(s3, s1, 7);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
COMP_ZFSF(s1, 8)
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
@@ -1537,15 +1448,7 @@ void emit_sbb16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
BFIw(xFlags, s4, F_OF, 1); // OF: ((bc >> 14) ^ ((bc>>14)>>1)) & 1
|
||||
}
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
ANDSw_mask(s1, s1, 0, 15); //mask=0xffff
|
||||
CSETw(s3, cEQ);
|
||||
BFIw(xFlags, s3, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRw(s3, s1, 15);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
COMP_ZFSF(s1, 16)
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
@@ -1732,10 +1635,9 @@ void emit_neg8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
IFX(X_AF|X_OF) {
|
||||
MOVw_REG(s3, s1);
|
||||
}
|
||||
NEGw_REG(s1, s1);
|
||||
IFX(X_ZF) {
|
||||
NEGSw_REG(s1, s1);
|
||||
} else {
|
||||
NEGw_REG(s1, s1);
|
||||
ANDSw_mask(s1, s1, 0, 7); // mask 0xff
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
|
||||
|
||||
Executable → Regular
+970
-41
File diff suppressed because it is too large.
Load diff
Executable → Regular
+11
-56
@@ -111,22 +111,11 @@ void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
|
||||
} else {
|
||||
SET_DFNONE(s3);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
SUBSw_REG(s5, s1, s2); // res = s1 - s2
|
||||
} else {
|
||||
SUBw_REG(s5, s1, s2); // res = s1 - s2
|
||||
}
|
||||
SUBw_REG(s5, s1, s2); // res = s1 - s2
|
||||
IFX_PENDOR0 {
|
||||
STRH_U12(s5, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
CSETw(s3, cEQ);
|
||||
BFIw(xFlags, s3, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRw(s4, s5, 15);
|
||||
BFIw(xFlags, s4, F_SF, 1);
|
||||
}
|
||||
COMP_ZFSF(s5, 16)
|
||||
// bc = (res & (~d | s)) | (~d & s)
|
||||
IFX(X_CF|X_AF|X_OF) {
|
||||
MVNw_REG(s4, s1); // s4 = ~d
|
||||
@@ -170,15 +159,7 @@ void emit_cmp16_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
|
||||
BICw(xFlags, xFlags, s3);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
ANDSw_mask(s1, s1, 0, 15); //mask=0xffff
|
||||
CSETw(s3, cEQ);
|
||||
BFIw(xFlags, s3, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRw(s4, s1, 15);
|
||||
BFIw(xFlags, s4, F_SF, 1);
|
||||
}
|
||||
COMP_ZFSF(s1, 16)
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
@@ -194,22 +175,11 @@ void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
|
||||
} else {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
SUBSw_REG(s5, s1, s2); // res = s1 - s2
|
||||
} else {
|
||||
SUBw_REG(s5, s1, s2); // res = s1 - s2
|
||||
}
|
||||
SUBw_REG(s5, s1, s2); // res = s1 - s2
|
||||
IFX_PENDOR0 {
|
||||
STRB_U12(s5, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
CSETw(s3, cEQ);
|
||||
BFIw(xFlags, s3, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRw(s3, s5, 7);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
COMP_ZFSF(s5, 8)
|
||||
// bc = (res & (~d | s)) | (~d & s)
|
||||
IFX(X_CF|X_AF|X_OF) {
|
||||
ORNw_REG(s4, s2, s1); // s4 = ~d | s
|
||||
@@ -251,22 +221,14 @@ void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
|
||||
BICw(xFlags, xFlags, s3);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
ANDSw_mask(s1, s1, 0, 0b000111); //mask=000000ff
|
||||
CSETw(s3, cEQ);
|
||||
BFIw(xFlags, s3, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRw(s3, s1, 7);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
COMP_ZFSF(s1, 8)
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
}
|
||||
|
||||
// emit TEST32 instruction, from test s1, s2, using s3 and s4 as scratch
|
||||
void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
|
||||
// emit TEST32 instruction, from test s1, s2, using s3, s4 and s5 as scratch
|
||||
void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5)
|
||||
{
|
||||
MAYUSE(s1); MAYUSE(s2); MAYUSE(s3); MAYUSE(s4);
|
||||
IFX_PENDOR0 {
|
||||
@@ -292,18 +254,11 @@ void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
|
||||
}
|
||||
// PF: (((emu->x64emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
|
||||
IFX(X_PF) {
|
||||
ANDw_mask(s3, s3, 0b011011, 0b000010); // 0xE0
|
||||
LSRw(s3, s3, 5);
|
||||
MOV64x(s4, (uintptr_t)GetParityTab());
|
||||
LDRw_REG_LSL2(s4, s4, s3);
|
||||
ANDw_mask(s3, s1, 0, 0b000100); // 0x1f
|
||||
LSRw_REG(s4, s4, s3);
|
||||
MVNx_REG(s4, s4);
|
||||
BFIw(xFlags, s4, F_PF, 1);
|
||||
emit_pf(dyn, ninst, s3, s4, s5);
|
||||
}
|
||||
}
|
||||
|
||||
// emit TEST16 instruction, from test s1, s2, using s3 and s4 as scratch
|
||||
// emit TEST16 instruction, from test s1, s2, using s3, s4 and s5 as scratch
|
||||
void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
|
||||
{
|
||||
MAYUSE(s1); MAYUSE(s2);
|
||||
@@ -334,7 +289,7 @@ void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4,
|
||||
}
|
||||
}
|
||||
|
||||
// emit TEST8 instruction, from test s1, s2, using s3 and s4 as scratch
|
||||
// emit TEST8 instruction, from test s1, s2, using s3, s4 and s5 as scratch
|
||||
void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
|
||||
{
|
||||
MAYUSE(s1); MAYUSE(s2);
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
Executable → Regular
+48
-22
@@ -28,7 +28,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback;
|
||||
uint8_t wback, wb1, wb2;
|
||||
uint8_t u8;
|
||||
uint64_t u64, j64;
|
||||
int v0, v1;
|
||||
@@ -159,30 +159,41 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
switch(opcode) {
|
||||
|
||||
case 0xF0:
|
||||
INST_NAME("(unsupported) CRC32 Gd, Eb)");
|
||||
INST_NAME("CRC32 Gd, Eb");
|
||||
nextop = F8;
|
||||
addr = fakeed(dyn, addr, ninst, nextop);
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
|
||||
GETIP(ip);
|
||||
STORE_XEMU_CALL(xRIP);
|
||||
CALL(native_ud, -1);
|
||||
LOAD_XEMU_CALL(xRIP);
|
||||
jump_to_epilog(dyn, 0, xRIP, ninst);
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
GETEB(x1, 0);
|
||||
GETGD;
|
||||
if(arm64_crc32) {
|
||||
CRC32CB(gd, gd, ed);
|
||||
} else {
|
||||
EORw_REG(gd, gd, ed);
|
||||
MOV32w(x2, 0x82f63b78);
|
||||
for(int i=0; i<8; ++i) {
|
||||
LSRw_IMM((i&1)?gd:x4, (i&1)?x4:gd, 1);
|
||||
TBZ((i&1)?x4:gd, 0, 4+4);
|
||||
EORw_REG((i&1)?gd:x4, (i&1)?gd:x4, x2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xF1:
|
||||
INST_NAME("(unsupported) CRC32 Gd, Ed)");
|
||||
INST_NAME("CRC32 Gd, Ed");
|
||||
nextop = F8;
|
||||
addr = fakeed(dyn, addr, ninst, nextop);
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
|
||||
GETIP(ip);
|
||||
STORE_XEMU_CALL(xRIP);
|
||||
CALL(native_ud, -1);
|
||||
LOAD_XEMU_CALL(xRIP);
|
||||
jump_to_epilog(dyn, 0, xRIP, ninst);
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
if(arm64_crc32) {
|
||||
CRC32Cxw(gd, gd, ed);
|
||||
} else {
|
||||
MOV32w(x2, 0x82f63b78);
|
||||
for(int j=0; j<4*(1+rex.w); ++j) {
|
||||
UBFXxw(x3, ed, 8*j, 8);
|
||||
EORw_REG(gd, gd, x3);
|
||||
for(int i=0; i<8; ++i) {
|
||||
LSRw_IMM((i&1)?gd:x4, (i&1)?x4:gd, 1);
|
||||
TBZ((i&1)?x4:gd, 0, 4+4);
|
||||
EORw_REG((i&1)?gd:x4, (i&1)?gd:x4, x2);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -376,7 +387,22 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
VFADDPQS(v0, v0, v1);
|
||||
break;
|
||||
|
||||
case 0x7D:
|
||||
INST_NAME("HSUBPS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
VLD128(v1, ed, fixedaddress);
|
||||
}
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
VUZP1Q_32(d0, v0, v1);
|
||||
VUZP2Q_32(v0, v0, v1);
|
||||
VFSUBQS(v0, d0, v0);
|
||||
break;
|
||||
case 0xC2:
|
||||
INST_NAME("CMPSD Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
|
||||
Executable → Regular
File mode changed.
Executable → Regular
+20
-12
@@ -30,7 +30,6 @@
|
||||
#define XMM8 16
|
||||
#define X870 8
|
||||
#define EMM0 8
|
||||
#define SCRATCH0 24
|
||||
|
||||
// Get a FPU scratch reg
|
||||
int fpu_get_scratch(dynarec_arm_t* dyn)
|
||||
@@ -96,6 +95,15 @@ void fpu_reset_reg(dynarec_arm_t* dyn)
|
||||
|
||||
}
|
||||
|
||||
int neoncache_no_i64(dynarec_arm_t* dyn, int ninst, int st, int a)
|
||||
{
|
||||
if(a==NEON_CACHE_ST_I64) {
|
||||
neoncache_promote_double(dyn, ninst, st);
|
||||
return NEON_CACHE_ST_D;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
int neoncache_get_st(dynarec_arm_t* dyn, int ninst, int a)
|
||||
{
|
||||
if (dyn->insts[ninst].n.swapped) {
|
||||
@@ -139,7 +147,7 @@ int neoncache_get_st_f(dynarec_arm_t* dyn, int ninst, int a)
|
||||
&& dyn->insts[ninst].n.neoncache[i].n==a)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
int neoncache_get_st_f_i64(dynarec_arm_t* dyn, int ninst, int a)
|
||||
{
|
||||
/*if(a+dyn->insts[ninst].n.stack_next-st<0)
|
||||
@@ -150,7 +158,7 @@ int neoncache_get_st_f_i64(dynarec_arm_t* dyn, int ninst, int a)
|
||||
&& dyn->insts[ninst].n.neoncache[i].n==a)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
int neoncache_get_st_f_noback(dynarec_arm_t* dyn, int ninst, int a)
|
||||
{
|
||||
for(int i=0; i<24; ++i)
|
||||
@@ -158,7 +166,7 @@ int neoncache_get_st_f_noback(dynarec_arm_t* dyn, int ninst, int a)
|
||||
&& dyn->insts[ninst].n.neoncache[i].n==a)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
int neoncache_get_st_f_i64_noback(dynarec_arm_t* dyn, int ninst, int a)
|
||||
{
|
||||
for(int i=0; i<24; ++i)
|
||||
@@ -166,7 +174,7 @@ int neoncache_get_st_f_i64_noback(dynarec_arm_t* dyn, int ninst, int a)
|
||||
&& dyn->insts[ninst].n.neoncache[i].n==a)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
int neoncache_get_current_st_f(dynarec_arm_t* dyn, int a)
|
||||
{
|
||||
for(int i=0; i<24; ++i)
|
||||
@@ -174,7 +182,7 @@ int neoncache_get_current_st_f(dynarec_arm_t* dyn, int a)
|
||||
&& dyn->n.neoncache[i].n==a)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
int neoncache_get_current_st_f_i64(dynarec_arm_t* dyn, int a)
|
||||
{
|
||||
for(int i=0; i<24; ++i)
|
||||
@@ -182,7 +190,7 @@ int neoncache_get_current_st_f_i64(dynarec_arm_t* dyn, int a)
|
||||
&& dyn->n.neoncache[i].n==a)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
static void neoncache_promote_double_forward(dynarec_arm_t* dyn, int ninst, int maxinst, int a);
|
||||
static void neoncache_promote_double_internal(dynarec_arm_t* dyn, int ninst, int maxinst, int a);
|
||||
static void neoncache_promote_double_combined(dynarec_arm_t* dyn, int ninst, int maxinst, int a)
|
||||
@@ -190,7 +198,7 @@ static void neoncache_promote_double_combined(dynarec_arm_t* dyn, int ninst, int
|
||||
if(a == dyn->insts[ninst].n.combined1 || a == dyn->insts[ninst].n.combined2) {
|
||||
if(a == dyn->insts[ninst].n.combined1) {
|
||||
a = dyn->insts[ninst].n.combined2;
|
||||
} else
|
||||
} else
|
||||
a = dyn->insts[ninst].n.combined1;
|
||||
int i = neoncache_get_st_f_i64_noback(dyn, ninst, a);
|
||||
//if(box64_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_combined, ninst=%d combined%c %d i=%d (stack:%d/%d)\n", ninst, (a == dyn->insts[ninst].n.combined2)?'2':'1', a ,i, dyn->insts[ninst].n.stack_push, -dyn->insts[ninst].n.stack_pop);
|
||||
@@ -314,7 +322,7 @@ static int isCacheEmpty(dynarec_native_t* dyn, int ninst) {
|
||||
for(int i=0; i<24; ++i)
|
||||
if(dyn->insts[ninst].n.neoncache[i].v) { // there is something at ninst for i
|
||||
if(!(
|
||||
(dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_F
|
||||
(dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_F
|
||||
|| dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_D
|
||||
|| dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_I64)
|
||||
&& dyn->insts[ninst].n.neoncache[i].n<dyn->insts[ninst].n.stack_pop))
|
||||
@@ -339,7 +347,7 @@ int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
|
||||
for(int i=0; i<24 && !ret; ++i)
|
||||
if(dyn->insts[ninst].n.neoncache[i].v) { // there is something at ninst for i
|
||||
if(!(
|
||||
(dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_F
|
||||
(dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_F
|
||||
|| dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_D
|
||||
|| dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_I64)
|
||||
&& dyn->insts[ninst].n.neoncache[i].n<dyn->insts[ninst].n.stack_pop))
|
||||
@@ -377,7 +385,7 @@ void neoncacheUnwind(neoncache_t* cache)
|
||||
{
|
||||
if(cache->swapped) {
|
||||
// unswap
|
||||
int a = -1;
|
||||
int a = -1;
|
||||
int b = -1;
|
||||
for(int j=0; j<24 && ((a==-1) || (b==-1)); ++j)
|
||||
if((cache->neoncache[j].t == NEON_CACHE_ST_D || cache->neoncache[j].t == NEON_CACHE_ST_F || cache->neoncache[j].t == NEON_CACHE_ST_I64)) {
|
||||
@@ -580,4 +588,4 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r
|
||||
void print_opcode(dynarec_native_t* dyn, int ninst, uint32_t opcode)
|
||||
{
|
||||
dynarec_log(LOG_NONE, "\t%08x\t%s\n", opcode, arm64_print(opcode, (uintptr_t)dyn->block));
|
||||
}
|
||||
}
|
||||
Executable → Regular
+6
-1
@@ -3,6 +3,8 @@
|
||||
|
||||
#include "../dynarec_native_functions.h"
|
||||
|
||||
#define SCRATCH0 24
|
||||
|
||||
// Get an FPU scratch reg
|
||||
int fpu_get_scratch(dynarec_arm_t* dyn);
|
||||
// Reset scratch regs counter
|
||||
@@ -35,8 +37,11 @@ int neoncache_get_current_st_f_i64(dynarec_arm_t* dyn, int a);
|
||||
void neoncache_promote_double(dynarec_arm_t* dyn, int ninst, int a);
|
||||
// Combine and propagate if needed (pass 1 only)
|
||||
int neoncache_combine_st(dynarec_arm_t* dyn, int ninst, int a, int b); // with stack current dyn->n_stack*
|
||||
// Do not allow i64 type
|
||||
int neoncache_no_i64(dynarec_arm_t* dyn, int ninst, int st, int a);
|
||||
|
||||
// FPU Cache transformation (for loops) // Specific, need to be written par backend
|
||||
|
||||
// FPU Cache transformation (for loops) // Specific, need to be written by backend
|
||||
int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int ninst);
|
||||
|
||||
// Undo the changes of a neoncache to get the status before the instruction
|
||||
|
||||
Executable → Regular
+124
-39
@@ -32,6 +32,8 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
|
||||
{
|
||||
MAYUSE(dyn); MAYUSE(ninst); MAYUSE(delta);
|
||||
|
||||
if(l==LOCK_LOCK) { /*SMDMB();*/DMB_ISH(); }
|
||||
|
||||
if(rex.is32bits)
|
||||
return geted_32(dyn, addr, ninst, nextop, ed, hint, fixaddress, unscaled, absmax, mask, l, s);
|
||||
|
||||
@@ -69,7 +71,7 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
|
||||
}
|
||||
} else {
|
||||
switch(lock) {
|
||||
case 1: addLockAddress(tmp); break;
|
||||
case 1: addLockAddress(tmp); if(fixaddress) *fixaddress=tmp; break;
|
||||
case 2: if(isLockAddress(tmp)) *l=1; break;
|
||||
}
|
||||
MOV64x(ret, tmp);
|
||||
@@ -106,7 +108,7 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
|
||||
ADDx_REG(ret, ret, xRIP);
|
||||
}
|
||||
switch(lock) {
|
||||
case 1: addLockAddress(addr+delta+tmp); break;
|
||||
case 1: addLockAddress(addr+delta+tmp); if(fixaddress) *fixaddress=addr+delta+tmp; break;
|
||||
case 2: if(isLockAddress(addr+delta+tmp)) *l=1; break;
|
||||
}
|
||||
} else {
|
||||
@@ -126,7 +128,7 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
|
||||
i64 = F8S;
|
||||
if(i64==0 || ((i64>=absmin) && (i64<=absmax) && !(i64&mask)) || (unscaled && (i64>-256) && (i64<256))) {
|
||||
*fixaddress = i64;
|
||||
if(unscaled && (i64>-256) && (i64<256))
|
||||
if(unscaled && i64 && (i64>-256) && (i64<256))
|
||||
*unscaled = 1;
|
||||
if((nextop&7)==4) {
|
||||
if (sib_reg!=4) {
|
||||
@@ -221,7 +223,7 @@ static uintptr_t geted_32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t
|
||||
}
|
||||
} else {
|
||||
switch(lock) {
|
||||
case 1: addLockAddress((int32_t)tmp); break;
|
||||
case 1: addLockAddress((int32_t)tmp); if(fixaddress) *fixaddress=(int32_t)tmp; break;
|
||||
case 2: if(isLockAddress((int32_t)tmp)) *l=1; break;
|
||||
}
|
||||
MOV32w(ret, tmp);
|
||||
@@ -237,7 +239,7 @@ static uintptr_t geted_32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t
|
||||
uint64_t tmp = F32;
|
||||
MOV32w(ret, tmp);
|
||||
switch(lock) {
|
||||
case 1: addLockAddress(tmp); break;
|
||||
case 1: addLockAddress(tmp); if(fixaddress) *fixaddress=tmp; break;
|
||||
case 2: if(isLockAddress(tmp)) *l=1; break;
|
||||
}
|
||||
} else {
|
||||
@@ -256,11 +258,11 @@ static uintptr_t geted_32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t
|
||||
}
|
||||
if(nextop&0x80)
|
||||
i32 = F32S;
|
||||
else
|
||||
else
|
||||
i32 = F8S;
|
||||
if(i32==0 || ((i32>=absmin) && (i32<=absmax) && !(i32&mask)) || (unscaled && (i32>-256) && (i32<256))) {
|
||||
*fixaddress = i32;
|
||||
if(unscaled && (i32>-256) && (i32<256))
|
||||
if(unscaled && i32 && (i32>-256) && (i32<256))
|
||||
*unscaled = 1;
|
||||
if((nextop&7)==4) {
|
||||
if (sib_reg!=4) {
|
||||
@@ -477,8 +479,8 @@ uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
|
||||
int64_t offset = 0;
|
||||
int absmin = 0;
|
||||
if(s) absmin = -absmax;
|
||||
if(!n && m==6) {
|
||||
offset = F16;
|
||||
if(!n && (m&7)==6) {
|
||||
offset = F16S;
|
||||
MOVZw(ret, offset);
|
||||
} else {
|
||||
switch(n) {
|
||||
@@ -567,6 +569,7 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
MAYUSE(dyn); MAYUSE(ninst);
|
||||
MESSAGE(LOG_DUMP, "Jump to next\n");
|
||||
|
||||
SMEND();
|
||||
if(reg) {
|
||||
if(reg!=xRIP) {
|
||||
MOVx_REG(xRIP, reg);
|
||||
@@ -575,6 +578,10 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
uintptr_t tbl = getJumpTable64();
|
||||
MAYUSE(tbl);
|
||||
TABLE64(x3, tbl);
|
||||
#ifdef JMPTABL_SHIFT4
|
||||
UBFXx(x2, xRIP, JMPTABL_START4, JMPTABL_SHIFT4);
|
||||
LDRx_REG_LSL3(x3, x3, x2);
|
||||
#endif
|
||||
UBFXx(x2, xRIP, JMPTABL_START3, JMPTABL_SHIFT3);
|
||||
LDRx_REG_LSL3(x3, x3, x2);
|
||||
UBFXx(x2, xRIP, JMPTABL_START2, JMPTABL_SHIFT2);
|
||||
@@ -598,7 +605,6 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
#ifdef HAVE_TRACE
|
||||
//MOVx(x3, 15); no access to PC reg
|
||||
#endif
|
||||
SMEND();
|
||||
BLR(x2); // save LR...
|
||||
}
|
||||
|
||||
@@ -612,16 +618,21 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex)
|
||||
if(box64_dynarec_callret) {
|
||||
// pop the actual return address for ARM stack
|
||||
LDPx_S7_offset(x2, x6, xSP, 0);
|
||||
CBZx(x6, 5*4);
|
||||
CBZx(x6, 6*4);
|
||||
ADDx_U12(xSP, xSP, 16);
|
||||
SUBx_REG(x6, x6, xRIP); // is it the right address?
|
||||
CBNZx(x6, 2*4);
|
||||
BLR(x2);
|
||||
// not the correct return address, regular jump
|
||||
// not the correct return address, regular jump, but purge the stack first, it's unsync now...
|
||||
SUBx_U12(xSP, xSavedSP, 0);
|
||||
}
|
||||
uintptr_t tbl = getJumpTable64();
|
||||
NOTEST(x2);
|
||||
MOV64x(x2, tbl);
|
||||
#ifdef JMPTABL_SHIFT4
|
||||
UBFXx(x3, xRIP, JMPTABL_START4, JMPTABL_SHIFT4);
|
||||
LDRx_REG_LSL3(x2, x2, x3);
|
||||
#endif
|
||||
UBFXx(x3, xRIP, JMPTABL_START3, JMPTABL_SHIFT3);
|
||||
LDRx_REG_LSL3(x2, x2, x3);
|
||||
UBFXx(x3, xRIP, JMPTABL_START2, JMPTABL_SHIFT2);
|
||||
@@ -650,16 +661,21 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex, int n)
|
||||
if(box64_dynarec_callret) {
|
||||
// pop the actual return address for ARM stack
|
||||
LDPx_S7_offset(x2, x6, xSP, 0);
|
||||
CBZx(x6, 5*4);
|
||||
CBZx(x6, 6*4);
|
||||
ADDx_U12(xSP, xSP, 16);
|
||||
SUBx_REG(x6, x6, xRIP); // is it the right address?
|
||||
CBNZx(x6, 2*4);
|
||||
BLR(x2);
|
||||
// not the correct return address, regular jump
|
||||
SUBx_U12(xSP, xSavedSP, 0);
|
||||
}
|
||||
uintptr_t tbl = getJumpTable64();
|
||||
NOTEST(x2);
|
||||
MOV64x(x2, tbl);
|
||||
#ifdef JMPTABL_SHIFT4
|
||||
UBFXx(x3, xRIP, JMPTABL_START4, JMPTABL_SHIFT4);
|
||||
LDRx_REG_LSL3(x2, x2, x3);
|
||||
#endif
|
||||
UBFXx(x3, xRIP, JMPTABL_START3, JMPTABL_SHIFT3);
|
||||
LDRx_REG_LSL3(x2, x2, x3);
|
||||
UBFXx(x3, xRIP, JMPTABL_START2, JMPTABL_SHIFT2);
|
||||
@@ -677,6 +693,7 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is64bits)
|
||||
//#warning TODO: is64bits
|
||||
MAYUSE(ninst);
|
||||
MESSAGE(LOG_DUMP, "IRet to epilog\n");
|
||||
SMEND();
|
||||
// POP IP
|
||||
NOTEST(x2);
|
||||
if(is64bits) {
|
||||
@@ -711,7 +728,6 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is64bits)
|
||||
MOVx_REG(xRSP, x3);
|
||||
// Ret....
|
||||
MOV64x(x2, (uintptr_t)arm64_epilog); // epilog on purpose, CS might have changed!
|
||||
SMEND();
|
||||
BR(x2);
|
||||
CLEARIP();
|
||||
}
|
||||
@@ -852,11 +868,11 @@ static void x87_reset(dynarec_arm_t* dyn)
|
||||
dyn->n.neoncache[i].v = 0;
|
||||
}
|
||||
|
||||
void x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch)
|
||||
int x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch)
|
||||
{
|
||||
MAYUSE(scratch);
|
||||
if(!dyn->n.x87stack)
|
||||
return;
|
||||
return 0;
|
||||
if(dyn->n.mmxcount)
|
||||
mmx_purgecache(dyn, ninst, 0, scratch);
|
||||
MESSAGE(LOG_DUMP, "\tSynch x87 Stackcount (%d)\n", dyn->n.x87stack);
|
||||
@@ -879,10 +895,45 @@ void x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch)
|
||||
ANDw_mask(scratch, scratch, 0, 2); //mask=7
|
||||
STRw_U12(scratch, xEmu, offsetof(x64emu_t, top));
|
||||
// reset x87stack, but not the stack count of neoncache
|
||||
int ret = dyn->n.x87stack;
|
||||
dyn->n.x87stack = 0;
|
||||
dyn->n.stack_next -= dyn->n.stack;
|
||||
dyn->n.stack = 0;
|
||||
MESSAGE(LOG_DUMP, "\t------x87 Stackcount\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
void x87_unstackcount(dynarec_arm_t* dyn, int ninst, int scratch, int count)
|
||||
{
|
||||
MAYUSE(scratch);
|
||||
if(!count)
|
||||
return;
|
||||
if(dyn->n.mmxcount)
|
||||
mmx_purgecache(dyn, ninst, 0, scratch);
|
||||
MESSAGE(LOG_DUMP, "\tUnsynch x87 Stackcount (%d)\n", count);
|
||||
int a = -count;
|
||||
// Add x87stack to emu fpu_stack
|
||||
LDRw_U12(scratch, xEmu, offsetof(x64emu_t, fpu_stack));
|
||||
if(a>0) {
|
||||
ADDw_U12(scratch, scratch, a);
|
||||
} else {
|
||||
SUBw_U12(scratch, scratch, -a);
|
||||
}
|
||||
STRw_U12(scratch, xEmu, offsetof(x64emu_t, fpu_stack));
|
||||
// Sub x87stack to top, with and 7
|
||||
LDRw_U12(scratch, xEmu, offsetof(x64emu_t, top));
|
||||
if(a>0) {
|
||||
SUBw_U12(scratch, scratch, a);
|
||||
} else {
|
||||
ADDw_U12(scratch, scratch, -a);
|
||||
}
|
||||
ANDw_mask(scratch, scratch, 0, 2); //mask=7
|
||||
STRw_U12(scratch, xEmu, offsetof(x64emu_t, top));
|
||||
// reset x87stack, but not the stack count of neoncache
|
||||
dyn->n.x87stack = count;
|
||||
dyn->n.stack = count;
|
||||
dyn->n.stack_next += dyn->n.stack;
|
||||
MESSAGE(LOG_DUMP, "\t------x87 Unstackcount\n");
|
||||
}
|
||||
|
||||
int neoncache_st_coherency(dynarec_arm_t* dyn, int ninst, int a, int b)
|
||||
@@ -1098,7 +1149,11 @@ static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
|
||||
if(dyn->n.x87cache[i]!=-1) {
|
||||
ADDw_U12(s3, s2, dyn->n.x87cache[i]);
|
||||
ANDw_mask(s3, s3, 0, 2); // mask=7 // (emu->top + i)&7
|
||||
VSTR64_REG_LSL3(dyn->n.x87reg[i], s1, s3);
|
||||
if(neoncache_get_st_f(dyn, ninst, dyn->n.x87cache[i])>=0) {
|
||||
FCVT_D_S(SCRATCH0, dyn->n.x87reg[i]);
|
||||
VSTR64_REG_LSL3(SCRATCH0, s1, s3);
|
||||
} else
|
||||
VSTR64_REG_LSL3(dyn->n.x87reg[i], s1, s3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1135,6 +1190,8 @@ int x87_get_current_cache(dynarec_arm_t* dyn, int ninst, int st, int t)
|
||||
#if STEP == 1
|
||||
if(t==NEON_CACHE_ST_D && (dyn->n.neoncache[dyn->n.x87reg[i]].t==NEON_CACHE_ST_F || dyn->n.neoncache[dyn->n.x87reg[i]].t==NEON_CACHE_ST_I64))
|
||||
neoncache_promote_double(dyn, ninst, st);
|
||||
else if(t==NEON_CACHE_ST_I64 && (dyn->n.neoncache[dyn->n.x87reg[i]].t==NEON_CACHE_ST_F))
|
||||
neoncache_promote_double(dyn, ninst, st);
|
||||
else if(t==NEON_CACHE_ST_F && (dyn->n.neoncache[dyn->n.x87reg[i]].t==NEON_CACHE_ST_I64))
|
||||
neoncache_promote_double(dyn, ninst, st);
|
||||
#endif
|
||||
@@ -1232,7 +1289,6 @@ void x87_refresh(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
|
||||
void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
{
|
||||
x87_stackcount(dyn, ninst, s1);
|
||||
int ret = -1;
|
||||
for (int i=0; (i<8) && (ret==-1); ++i)
|
||||
if(dyn->n.x87cache[i] == st)
|
||||
@@ -1240,8 +1296,9 @@ void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
if(ret==-1) // nothing to do
|
||||
return;
|
||||
MESSAGE(LOG_DUMP, "\tForget x87 Cache for ST%d\n", st);
|
||||
const int reg = dyn->n.x87reg[ret];
|
||||
#if STEP == 1
|
||||
if(dyn->n.neoncache[dyn->n.x87reg[ret]].t==NEON_CACHE_ST_F || dyn->n.neoncache[dyn->n.x87reg[ret]].t==NEON_CACHE_ST_I64)
|
||||
if(dyn->n.neoncache[reg].t==NEON_CACHE_ST_F || dyn->n.neoncache[reg].t==NEON_CACHE_ST_I64)
|
||||
neoncache_promote_double(dyn, ninst, st);
|
||||
#endif
|
||||
// prepare offset to fpu => s1
|
||||
@@ -1249,15 +1306,28 @@ void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
// Get top
|
||||
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
|
||||
// Update
|
||||
if(st) {
|
||||
ADDw_U12(s2, s2, st);
|
||||
int ast = st - dyn->n.x87stack;
|
||||
if(ast) {
|
||||
if(ast>0) {
|
||||
ADDw_U12(s2, s2, ast);
|
||||
} else {
|
||||
SUBw_U12(s2, s2, -ast);
|
||||
}
|
||||
ANDw_mask(s2, s2, 0, 2); //mask=7 // (emu->top + i)&7
|
||||
}
|
||||
VSTR64_REG_LSL3(dyn->n.x87reg[ret], s1, s2);
|
||||
if(dyn->n.neoncache[reg].t==NEON_CACHE_ST_F) {
|
||||
FCVT_D_S(31, reg);
|
||||
VSTR64_REG_LSL3(31, s1, s2);
|
||||
} else if(dyn->n.neoncache[reg].t==NEON_CACHE_ST_I64) {
|
||||
SCVTFDD(31, reg);
|
||||
VSTR64_REG_LSL3(31, s1, s2);
|
||||
} else {
|
||||
VSTR64_REG_LSL3(reg, s1, s2);
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "\t--------x87 Cache for ST%d\n", st);
|
||||
// and forget that cache
|
||||
fpu_free_reg(dyn, dyn->n.x87reg[ret]);
|
||||
dyn->n.neoncache[dyn->n.x87reg[ret]].v = 0;
|
||||
fpu_free_reg(dyn, reg);
|
||||
dyn->n.neoncache[reg].v = 0;
|
||||
dyn->n.x87cache[ret] = -1;
|
||||
dyn->n.x87reg[ret] = -1;
|
||||
}
|
||||
@@ -1438,7 +1508,7 @@ static void mmx_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
for (int i=0; i<8; ++i)
|
||||
if(dyn->n.mmxcache[i]!=-1) {
|
||||
VLDR64_U12(dyn->n.mmxcache[i], xEmu, offsetof(x64emu_t, mmx[i]));
|
||||
VSTR64_U12(dyn->n.mmxcache[i], xEmu, offsetof(x64emu_t, mmx[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1541,6 +1611,17 @@ static void sse_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
}
|
||||
}
|
||||
|
||||
void sse_reflect_reg(dynarec_arm_t* dyn, int ninst, int a)
|
||||
{
|
||||
if(dyn->n.ssecache[a].v==-1)
|
||||
return;
|
||||
if(dyn->n.neoncache[dyn->n.ssecache[a].reg].t == NEON_CACHE_XMMW) {
|
||||
VSTR128_U12(dyn->n.ssecache[a].reg, xEmu, offsetof(x64emu_t, xmm[a]));
|
||||
/*dyn->n.neoncache[dyn->n.ssecache[a].reg].t = NEON_CACHE_XMMR;
|
||||
dyn->n.ssecache[a].write = 0;*/
|
||||
}
|
||||
}
|
||||
|
||||
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1, int not07)
|
||||
{
|
||||
int start = not07?8:0;
|
||||
@@ -1573,6 +1654,8 @@ void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1, int not07)
|
||||
for (int i=start; i<16; ++i)
|
||||
if(dyn->n.ssecache[i].v!=-1) {
|
||||
VLDR128_U12(dyn->n.ssecache[i].reg, xEmu, offsetof(x64emu_t, xmm[i]));
|
||||
/*dyn->n.ssecache[i].write = 0; // OPTIM: it's sync, so not write anymore
|
||||
dyn->n.neoncache[dyn->n.ssecache[i].reg].t = NEON_CACHE_XMMR;*/
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "\t------- Pop XMM Cache (%d)\n", n);
|
||||
}
|
||||
@@ -1697,7 +1780,7 @@ static void loadCache(dynarec_arm_t* dyn, int ninst, int stack_cnt, int s1, int
|
||||
break;
|
||||
case NEON_CACHE_MM:
|
||||
MESSAGE(LOG_DUMP, "\t - Loading %s\n", getCacheName(t, n));
|
||||
VLDR64_U12(i, xEmu, offsetof(x64emu_t, mmx[i]));
|
||||
VLDR64_U12(i, xEmu, offsetof(x64emu_t, mmx[n]));
|
||||
break;
|
||||
case NEON_CACHE_ST_D:
|
||||
case NEON_CACHE_ST_F:
|
||||
@@ -1717,9 +1800,11 @@ static void loadCache(dynarec_arm_t* dyn, int ninst, int stack_cnt, int s1, int
|
||||
ANDw_mask(s3, s3, 0, 2); //mask=7 // (emu->top + i)&7
|
||||
}
|
||||
*s3_top += a;
|
||||
*s2_val = 0;
|
||||
ADDx_REG_LSL(s2, xEmu, s3, 3);
|
||||
VLDR64_U12(i, s2, offsetof(x64emu_t, x87));
|
||||
if(*s2_val!=1) {
|
||||
*s2_val = 1;
|
||||
ADDx_U12(s2, xEmu, offsetof(x64emu_t, x87));
|
||||
}
|
||||
VLDR64_REG_LSL3(i, s2, s3);
|
||||
if(t==NEON_CACHE_ST_F) {
|
||||
FCVT_S_D(i, i);
|
||||
}
|
||||
@@ -1769,14 +1854,16 @@ static void unloadCache(dynarec_arm_t* dyn, int ninst, int stack_cnt, int s1, in
|
||||
ANDw_mask(s3, s3, 0, 2); //mask=7 // (emu->top + i)&7
|
||||
}
|
||||
*s3_top += a;
|
||||
ADDx_REG_LSL(s2, xEmu, s3, 3);
|
||||
*s2_val = 0;
|
||||
if(*s2_val!=1) {
|
||||
*s2_val = 1;
|
||||
ADDx_U12(s2, xEmu, offsetof(x64emu_t, x87));
|
||||
}
|
||||
if(t==NEON_CACHE_ST_F) {
|
||||
FCVT_D_S(i, i);
|
||||
} else if (t==NEON_CACHE_ST_I64) {
|
||||
SCVTFDD(i, i);
|
||||
}
|
||||
VSTR64_U12(i, s2, offsetof(x64emu_t, x87));
|
||||
VSTR64_REG_LSL3(i, s2, s3);
|
||||
break;
|
||||
case NEON_CACHE_NONE:
|
||||
case NEON_CACHE_SCR:
|
||||
@@ -1945,7 +2032,7 @@ static void flagsCacheTransform(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
if(dyn->f.dfnone) // flags are fully known, nothing we can do more
|
||||
return;
|
||||
MESSAGE(LOG_DUMP, "\tFlags fetch ---- ninst=%d -> %d\n", ninst, jmp);
|
||||
int go = 0;
|
||||
int go = (dyn->insts[jmp].f_entry.dfnone && !dyn->f.dfnone)?1:0;
|
||||
switch (dyn->insts[jmp].f_entry.pending) {
|
||||
case SF_UNKNOWN: break;
|
||||
case SF_SET:
|
||||
@@ -1963,12 +2050,10 @@ static void flagsCacheTransform(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
&& dyn->f.pending!=SF_SET_PENDING
|
||||
&& dyn->f.pending!=SF_PENDING)
|
||||
go = 1;
|
||||
else
|
||||
go = (dyn->insts[jmp].f_entry.dfnone == dyn->f.dfnone)?0:1;
|
||||
else if (dyn->insts[jmp].f_entry.dfnone !=dyn->f.dfnone)
|
||||
go = 1;
|
||||
break;
|
||||
}
|
||||
if(dyn->insts[jmp].f_entry.dfnone && !dyn->f.dfnone)
|
||||
go = 1;
|
||||
if(go) {
|
||||
if(dyn->f.pending!=SF_PENDING) {
|
||||
LDRw_U12(s1, xEmu, offsetof(x64emu_t, df));
|
||||
@@ -2016,7 +2101,7 @@ void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
// PF: (((emu->x64emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
|
||||
ANDw_mask(s3, s1, 0b011011, 0b000010); // mask=0xE0
|
||||
LSRw(s3, s3, 5);
|
||||
MOV64x(s4, (uintptr_t)GetParityTab());
|
||||
TABLE64(s4, (uintptr_t)GetParityTab());
|
||||
LDRw_REG_LSL2(s4, s4, s3);
|
||||
ANDw_mask(s3, s1, 0, 0b000100); //0x1f
|
||||
LSRw_REG(s4, s4, s3);
|
||||
@@ -2086,4 +2171,4 @@ void fpu_propagate_stack(dynarec_arm_t* dyn, int ninst)
|
||||
dyn->n.news = 0;
|
||||
dyn->n.stack_push = 0;
|
||||
dyn->n.swapped = 0;
|
||||
}
|
||||
}
|
||||
Executable → Regular
+169
-29
@@ -33,28 +33,31 @@
|
||||
#define PKip(a) *(uint8_t*)(ip+a)
|
||||
|
||||
// Strong mem emulation helpers
|
||||
// Sequence of Read will trigger a DMB on "first" read if strongmem is 2
|
||||
// Squence of Write will trigger a DMB on "last" write if strongmem is 1
|
||||
#define SMREAD_MIN 2
|
||||
#define SMWRITE_MIN 1
|
||||
// Sequence of Read will trigger a DMB on "first" read if strongmem is >= SMREAD_MIN
|
||||
// Sequence of Write will trigger a DMB on "last" write if strongmem is >= 1
|
||||
// All Write operation that might use a lock all have a memory barrier if strongmem is >= SMWRITE_MIN
|
||||
// Opcode will read
|
||||
#define SMREAD() if(!dyn->smread && box64_dynarec_strongmem>1) {SMDMB();}
|
||||
#define SMREAD() if((dyn->smread==0) && (box64_dynarec_strongmem>SMREAD_MIN)) {SMDMB();} else dyn->smread=1
|
||||
// Opcode will read with option forced lock
|
||||
#define SMREADLOCK(lock) if(lock || (!dyn->smread && box64_dynarec_strongmem>1)) {SMDMB();}
|
||||
// Opcode migh read (depend on nextop)
|
||||
#define SMREADLOCK(lock) if((lock) || ((dyn->smread==0) && (box64_dynarec_strongmem>SMREAD_MIN))) {SMDMB();}
|
||||
// Opcode might read (depend on nextop)
|
||||
#define SMMIGHTREAD() if(!MODREG) {SMREAD();}
|
||||
// Opcode has wrote
|
||||
#define SMWRITE() dyn->smwrite=1
|
||||
// Opcode has wrote (strongmem>1 only)
|
||||
#define SMWRITE2() if(box64_dynarec_strongmem>1) dyn->smwrite=1
|
||||
#define SMWRITE2() if(box64_dynarec_strongmem>SMREAD_MIN) dyn->smwrite=1
|
||||
// Opcode has wrote with option forced lock
|
||||
#define SMWRITELOCK(lock) if(lock) {SMDMB();} else dyn->smwrite=1
|
||||
// Opcode migh have wrote (depend on nextop)
|
||||
#define SMWRITELOCK(lock) if(lock || (box64_dynarec_strongmem>SMWRITE_MIN)) {SMDMB();} else dyn->smwrite=1
|
||||
// Opcode might have wrote (depend on nextop)
|
||||
#define SMMIGHTWRITE() if(!MODREG) {SMWRITE();}
|
||||
// Start of sequence
|
||||
#define SMSTART() SMEND()
|
||||
// End of sequence
|
||||
#define SMEND() if(dyn->smwrite && box64_dynarec_strongmem) {DMB_ISH();} dyn->smwrite=0; dyn->smread=0;
|
||||
#define SMEND() if(dyn->smwrite && box64_dynarec_strongmem) {if(box64_dynarec_strongmem){DSB_ISH();}else{DMB_ISH();}} dyn->smwrite=0; dyn->smread=0;
|
||||
// Force a Data memory barrier (for LOCK: prefix)
|
||||
#define SMDMB() DMB_ISH(); dyn->smwrite=0; dyn->smread=1
|
||||
#define SMDMB() if(box64_dynarec_strongmem){DSB_ISH();}else{DMB_ISH();} dyn->smwrite=0; dyn->smread=1
|
||||
|
||||
//LOCK_* define
|
||||
#define LOCK_LOCK (int*)1
|
||||
@@ -66,7 +69,7 @@
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
SMREAD() \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, D); \
|
||||
LDxw(x1, wback, fixedaddress); \
|
||||
ed = x1; \
|
||||
@@ -85,7 +88,7 @@
|
||||
wback = 0; \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, D); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<(3-rex.is32bits), rex.is32bits?3:7, rex, NULL, 0, D); \
|
||||
LDz(x1, wback, fixedaddress); \
|
||||
ed = x1; \
|
||||
}
|
||||
@@ -360,18 +363,18 @@
|
||||
gb2 = 0; \
|
||||
} else { \
|
||||
gd = (nextop&0x38)>>3; \
|
||||
gb2 = ((gd&4)>>2); \
|
||||
gb2 = ((gd&4)<<1); \
|
||||
gb1 = xRAX+(gd&3); \
|
||||
} \
|
||||
gd = i; \
|
||||
UBFXx(gd, gb1, gb2*8, 8);
|
||||
//GETSGB signe extend GB, will use i for gd
|
||||
UBFXx(gd, gb1, gb2, 8);
|
||||
//GETSGB sign extend GB, will use i for gd
|
||||
#define GETSGB(i) if(rex.rex) { \
|
||||
gb1 = xRAX+((nextop&0x38)>>3)+(rex.r<<3); \
|
||||
gb2 = 0; \
|
||||
} else { \
|
||||
gd = (nextop&0x38)>>3; \
|
||||
gb2 = ((gd&4)>>2); \
|
||||
gb2 = ((gd&4)<<1); \
|
||||
gb1 = xRAX+(gd&3); \
|
||||
} \
|
||||
gd = i; \
|
||||
@@ -422,6 +425,9 @@
|
||||
VLD64(a, ed, fixedaddress); \
|
||||
}
|
||||
|
||||
// Get Ex as 64bits, not a quad (warning, x1 get used)
|
||||
#define GETEX64(a, w, D) GETEXSD(a, w, D)
|
||||
|
||||
// Get Ex as a single, not a quad (warning, x1 get used)
|
||||
#define GETEXSS(a, w, D) \
|
||||
if(MODREG) { \
|
||||
@@ -433,6 +439,20 @@
|
||||
VLD32(a, ed, fixedaddress); \
|
||||
}
|
||||
|
||||
// Get Ex as 32bits, not a quad (warning, x1 get used)
|
||||
#define GETEX32(a, w, D) GETEXSS(a, w, D)
|
||||
|
||||
// Get Ex as 16bits, not a quad (warning, x1 get used)
|
||||
#define GETEX16(a, w, D) \
|
||||
if(MODREG) { \
|
||||
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), w); \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
a = fpu_get_scratch(dyn); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, D); \
|
||||
VLD16(a, ed, fixedaddress); \
|
||||
}
|
||||
|
||||
// Get GM, might use x1, x2 and x3
|
||||
#define GETGM(a) \
|
||||
gd = ((nextop&0x38)>>3); \
|
||||
@@ -464,6 +484,9 @@
|
||||
TSTw_mask(xFlags, 0b010110, 0); \
|
||||
CNEGx(r, r, cNE)
|
||||
|
||||
#define ALIGNED_ATOMICxw ((fixedaddress && !(fixedaddress&((1<<(2+rex.w)-1)))) || box64_dynarec_aligned_atomics)
|
||||
#define ALIGNED_ATOMICH ((fixedaddress && !(fixedaddress&1)) || box64_dynarec_aligned_atomics)
|
||||
|
||||
// CALL will use x7 for the call address. Return value can be put in ret (unless ret is -1)
|
||||
// R0 will not be pushed/popd if ret is -2
|
||||
#define CALL(F, ret) call_c(dyn, ninst, F, x7, ret, 1, 0)
|
||||
@@ -742,8 +765,39 @@
|
||||
LDP_REGS(R12, R13); \
|
||||
LDP_REGS(R14, R15)
|
||||
|
||||
#define X87_PUSH_OR_FAIL(var, dyn, ninst, scratch, t) \
|
||||
if (dyn->n.stack == +8) { \
|
||||
*ok = 0; \
|
||||
break; \
|
||||
} \
|
||||
var = x87_do_push(dyn, ninst, scratch, t);
|
||||
|
||||
#define X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, scratch) \
|
||||
if (dyn->n.stack == +8) { \
|
||||
*ok = 0; \
|
||||
break; \
|
||||
} \
|
||||
x87_do_push_empty(dyn, ninst, scratch);
|
||||
|
||||
#define X87_POP_OR_FAIL(dyn, ninst, scratch) \
|
||||
if (dyn->n.stack == -8) { \
|
||||
*ok = 0; \
|
||||
break; \
|
||||
} \
|
||||
x87_do_pop(dyn, ninst, scratch);
|
||||
|
||||
#define SET_DFNONE(S) if(!dyn->f.dfnone) {STRw_U12(wZR, xEmu, offsetof(x64emu_t, df)); dyn->f.dfnone=1;}
|
||||
#define SET_DF(S, N) if((N)!=d_none) {MOVZw(S, (N)); STRw_U12(S, xEmu, offsetof(x64emu_t, df)); dyn->f.dfnone=0;} else SET_DFNONE(S)
|
||||
#define SET_DF(S, N) \
|
||||
if((N)!=d_none) { \
|
||||
MOVZw(S, (N)); \
|
||||
STRw_U12(S, xEmu, offsetof(x64emu_t, df)); \
|
||||
if(dyn->f.pending==SF_PENDING && dyn->insts[ninst].x64.need_after && !(dyn->insts[ninst].x64.need_after&X_PEND)) { \
|
||||
CALL_(UpdateFlags, -1, 0); \
|
||||
dyn->f.pending = SF_SET; \
|
||||
SET_NODF(); \
|
||||
} \
|
||||
dyn->f.dfnone=0; \
|
||||
} else SET_DFNONE(S)
|
||||
#define SET_NODF() dyn->f.dfnone = 0
|
||||
#define SET_DFOK() dyn->f.dfnone = 1
|
||||
|
||||
@@ -784,7 +838,7 @@
|
||||
} else dyn->f.pending = SF_SET
|
||||
#endif
|
||||
#ifndef JUMP
|
||||
#define JUMP(A, C)
|
||||
#define JUMP(A, C) SMEND()
|
||||
#endif
|
||||
#ifndef BARRIER
|
||||
#define BARRIER(A)
|
||||
@@ -792,6 +846,9 @@
|
||||
#ifndef BARRIER_NEXT
|
||||
#define BARRIER_NEXT(A)
|
||||
#endif
|
||||
#ifndef SET_HASCALLRET
|
||||
#define SET_HASCALLRET()
|
||||
#endif
|
||||
#define UFLAG_OP1(A) if(dyn->insts[ninst].x64.gen_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, op1));}
|
||||
#define UFLAG_OP2(A) if(dyn->insts[ninst].x64.gen_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, op2));}
|
||||
#define UFLAG_OP12(A1, A2) if(dyn->insts[ninst].x64.gen_flags) {STRxw_U12(A1, xEmu, offsetof(x64emu_t, op1));STRxw_U12(A2, xEmu, offsetof(x64emu_t, op2));}
|
||||
@@ -874,6 +931,8 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
|
||||
#define dynarec64_65 STEPNAME(dynarec64_65)
|
||||
#define dynarec64_66 STEPNAME(dynarec64_66)
|
||||
#define dynarec64_67 STEPNAME(dynarec64_67)
|
||||
#define dynarec64_67_32 STEPNAME(dynarec64_67_32)
|
||||
#define dynarec64_6764_32 STEPNAME(dynarec64_6764_32)
|
||||
#define dynarec64_D8 STEPNAME(dynarec64_D8)
|
||||
#define dynarec64_D9 STEPNAME(dynarec64_D9)
|
||||
#define dynarec64_DA STEPNAME(dynarec64_DA)
|
||||
@@ -884,6 +943,8 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
|
||||
#define dynarec64_DF STEPNAME(dynarec64_DF)
|
||||
#define dynarec64_F0 STEPNAME(dynarec64_F0)
|
||||
#define dynarec64_660F STEPNAME(dynarec64_660F)
|
||||
#define dynarec64_66F20F STEPNAME(dynarec64_66F20F)
|
||||
#define dynarec64_66F30F STEPNAME(dynarec64_66F30F)
|
||||
#define dynarec64_6664 STEPNAME(dynarec64_6664)
|
||||
#define dynarec64_66F0 STEPNAME(dynarec64_66F0)
|
||||
#define dynarec64_F20F STEPNAME(dynarec64_F20F)
|
||||
@@ -965,16 +1026,38 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
|
||||
#define emit_shr32 STEPNAME(emit_shr32)
|
||||
#define emit_shr32c STEPNAME(emit_shr32c)
|
||||
#define emit_sar32c STEPNAME(emit_sar32c)
|
||||
#define emit_shl8 STEPNAME(emit_shl8)
|
||||
#define emit_shl8c STEPNAME(emit_shl8c)
|
||||
#define emit_shr8 STEPNAME(emit_shr8)
|
||||
#define emit_shr8c STEPNAME(emit_shr8c)
|
||||
#define emit_sar8 STEPNAME(emit_sar8)
|
||||
#define emit_sar8c STEPNAME(emit_sar8c)
|
||||
#define emit_shl16 STEPNAME(emit_shl16)
|
||||
#define emit_shl16c STEPNAME(emit_shl16c)
|
||||
#define emit_shr16 STEPNAME(emit_shr16)
|
||||
#define emit_shr16c STEPNAME(emit_shr16c)
|
||||
#define emit_sar16 STEPNAME(emit_sar16)
|
||||
#define emit_sar16c STEPNAME(emit_sar16c)
|
||||
#define emit_rol32c STEPNAME(emit_rol32c)
|
||||
#define emit_ror32c STEPNAME(emit_ror32c)
|
||||
#define emit_rol8c STEPNAME(emit_rol8c)
|
||||
#define emit_ror8c STEPNAME(emit_ror8c)
|
||||
#define emit_rol16c STEPNAME(emit_rol16c)
|
||||
#define emit_ror16c STEPNAME(emit_ror16c)
|
||||
#define emit_shrd32c STEPNAME(emit_shrd32c)
|
||||
#define emit_shrd32 STEPNAME(emit_shrd32)
|
||||
#define emit_shld32c STEPNAME(emit_shld32c)
|
||||
#define emit_shld32 STEPNAME(emit_shld32)
|
||||
#define emit_shrd16c STEPNAME(emit_shrd16c)
|
||||
#define emit_shrd16 STEPNAME(emit_shrd16)
|
||||
#define emit_shld16c STEPNAME(emit_shld16c)
|
||||
#define emit_shld16 STEPNAME(emit_shld16)
|
||||
|
||||
#define emit_pf STEPNAME(emit_pf)
|
||||
|
||||
#define x87_do_push STEPNAME(x87_do_push)
|
||||
#define x87_do_push_empty STEPNAME(x87_do_push_empty)
|
||||
#define x87_do_pop STEPNAME(x87_do_pop)
|
||||
#define x87_do_push STEPNAME(x87_do_push)
|
||||
#define x87_do_push_empty STEPNAME(x87_do_push_empty)
|
||||
#define x87_do_pop STEPNAME(x87_do_pop)
|
||||
#define x87_get_current_cache STEPNAME(x87_get_current_cache)
|
||||
#define x87_get_cache STEPNAME(x87_get_cache)
|
||||
#define x87_get_neoncache STEPNAME(x87_get_neoncache)
|
||||
@@ -984,6 +1067,7 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
|
||||
#define x87_forget STEPNAME(x87_forget)
|
||||
#define x87_reget_st STEPNAME(x87_reget_st)
|
||||
#define x87_stackcount STEPNAME(x87_stackcount)
|
||||
#define x87_unstackcount STEPNAME(x87_unstackcount)
|
||||
#define x87_swapreg STEPNAME(x87_swapreg)
|
||||
#define x87_setround STEPNAME(x87_setround)
|
||||
#define x87_restoreround STEPNAME(x87_restoreround)
|
||||
@@ -994,6 +1078,7 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
|
||||
#define sse_get_reg_empty STEPNAME(sse_get_reg_empty)
|
||||
#define sse_forget_reg STEPNAME(sse_forget_reg)
|
||||
#define sse_purge07cache STEPNAME(sse_purge07cache)
|
||||
#define sse_reflect_reg STEPNAME(sse_reflect_reg)
|
||||
|
||||
#define fpu_pushcache STEPNAME(fpu_pushcache)
|
||||
#define fpu_popcache STEPNAME(fpu_popcache)
|
||||
@@ -1035,7 +1120,7 @@ void emit_cmp16_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
|
||||
void emit_cmp32_0(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4);
|
||||
void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
|
||||
void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
|
||||
void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);
|
||||
void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5);
|
||||
void emit_add32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);
|
||||
void emit_add32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5);
|
||||
void emit_add8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
|
||||
@@ -1092,16 +1177,40 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i
|
||||
void emit_shr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);
|
||||
void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
|
||||
void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
|
||||
void emit_shl8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
|
||||
void emit_shl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
|
||||
void emit_shr8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
|
||||
void emit_shr8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
|
||||
void emit_sar8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
|
||||
void emit_sar8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
|
||||
void emit_shl16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
|
||||
void emit_shl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
|
||||
void emit_shr16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
|
||||
void emit_shr16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
|
||||
void emit_sar16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
|
||||
void emit_sar16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
|
||||
void emit_rol32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
|
||||
void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
|
||||
void emit_rol8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
|
||||
void emit_ror8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
|
||||
void emit_rol16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
|
||||
void emit_ror16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
|
||||
void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4);
|
||||
void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4);
|
||||
void emit_shrd32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s5, int s3, int s4);
|
||||
void emit_shld32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s5, int s3, int s4);
|
||||
void emit_shrd16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int s3, int s4);
|
||||
void emit_shrd16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s5, int s3, int s4);
|
||||
void emit_shld16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int s3, int s4);
|
||||
void emit_shld16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s5, int s3, int s4);
|
||||
|
||||
void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
|
||||
|
||||
// x87 helper
|
||||
// cache of the local stack counter, to avoid upadte at every call
|
||||
void x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch);
|
||||
// cache of the local stack counter, to avoid update at every call, return old internal stack counter
|
||||
int x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch);
|
||||
// revert local stack counter to previous version (return from x87_stackcount)
|
||||
void x87_unstackcount(dynarec_arm_t* dyn, int ninst, int scratch, int count);
|
||||
// fpu push. Return the Dd value to be used
|
||||
int x87_do_push(dynarec_arm_t* dyn, int ninst, int s1, int t);
|
||||
// fpu push. Do not allocate a cache register. Needs a scratch register to do x87stack synch (or 0 to not do it)
|
||||
@@ -1154,8 +1263,8 @@ int neoncache_st_coherency(dynarec_arm_t* dyn, int ninst, int a, int b);
|
||||
#define ST_IS_F(A) (neoncache_get_current_st(dyn, ninst, A)==NEON_CACHE_ST_F)
|
||||
#define ST_IS_I64(A) (neoncache_get_current_st(dyn, ninst, A)==NEON_CACHE_ST_I64)
|
||||
#define X87_COMBINE(A, B) neoncache_combine_st(dyn, ninst, A, B)
|
||||
#define X87_ST0 neoncache_get_current_st(dyn, ninst, 0)
|
||||
#define X87_ST(A) neoncache_get_current_st(dyn, ninst, A)
|
||||
#define X87_ST0 neoncache_no_i64(dyn, ninst, 0, neoncache_get_current_st(dyn, ninst, 0))
|
||||
#define X87_ST(A) neoncache_no_i64(dyn, ninst, A, neoncache_get_current_st(dyn, ninst, A))
|
||||
#else
|
||||
#define ST_IS_F(A) (neoncache_get_st(dyn, ninst, A)==NEON_CACHE_ST_F)
|
||||
#define ST_IS_I64(A) (neoncache_get_st(dyn, ninst, A)==NEON_CACHE_ST_I64)
|
||||
@@ -1183,7 +1292,8 @@ int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a);
|
||||
void sse_forget_reg(dynarec_arm_t* dyn, int ninst, int a);
|
||||
// purge the XMM0..XMM7 cache (before function call)
|
||||
void sse_purge07cache(dynarec_arm_t* dyn, int ninst, int s1);
|
||||
|
||||
// Push current value to the cache
|
||||
void sse_reflect_reg(dynarec_arm_t* dyn, int ninst, int a);
|
||||
// common coproc helpers
|
||||
// reset the cache
|
||||
void fpu_reset(dynarec_arm_t* dyn);
|
||||
@@ -1208,16 +1318,20 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
//uintptr_t dynarec64_65(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep,int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_67_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_6764_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
//uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_66F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_66F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int seg, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
|
||||
@@ -1354,4 +1468,30 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
opcode = F8; \
|
||||
}
|
||||
|
||||
#define COMP_ZFSF(s1, A) \
|
||||
IFX(X_ZF|X_SF) { \
|
||||
if(arm64_flagm) { \
|
||||
SETF##A(s1); \
|
||||
IFX(X_ZF) { \
|
||||
CSETw(s3, cEQ); \
|
||||
BFIw(xFlags, s3, F_ZF, 1); \
|
||||
} \
|
||||
IFX(X_SF) { \
|
||||
CSETw(s3, cMI); \
|
||||
BFIw(xFlags, s3, F_SF, 1); \
|
||||
} \
|
||||
} else { \
|
||||
IFX(X_ZF) { \
|
||||
ANDSw_mask(s1, s1, 0, (A)-1); \
|
||||
CSETw(s3, cEQ); \
|
||||
BFIw(xFlags, s3, F_ZF, 1); \
|
||||
} \
|
||||
IFX(X_SF) { \
|
||||
LSRw(s3, s1, (A)-1); \
|
||||
BFIw(xFlags, s3, F_SF, 1); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
#endif //__DYNAREC_ARM64_HELPER_H__
|
||||
Executable → Regular
+3
-2
@@ -16,9 +16,10 @@
|
||||
dyn->f.pending=(B)&SF_SET_PENDING; \
|
||||
dyn->f.dfnone=((B)&SF_SET)?1:0;
|
||||
#define EMIT(A)
|
||||
#define JUMP(A, C) add_next(dyn, (uintptr_t)A); dyn->insts[ninst].x64.jmp = A; dyn->insts[ninst].x64.jmp_cond = C
|
||||
#define JUMP(A, C) add_jump(dyn, ninst); add_next(dyn, (uintptr_t)A); SMEND(); dyn->insts[ninst].x64.jmp = A; dyn->insts[ninst].x64.jmp_cond = C
|
||||
#define BARRIER(A) if(A!=BARRIER_MAYBE) {fpu_purgecache(dyn, ninst, 0, x1, x2, x3); dyn->insts[ninst].x64.barrier = A;} else dyn->insts[ninst].barrier_maybe = 1
|
||||
#define BARRIER_NEXT(A) dyn->insts[ninst+1].x64.barrier = A
|
||||
#define BARRIER_NEXT(A) dyn->insts[ninst].x64.barrier_next = A
|
||||
#define SET_HASCALLRET() dyn->insts[ninst].x64.has_callret = 1
|
||||
#define NEW_INST \
|
||||
++dyn->size; \
|
||||
if(dyn->size+3>=dyn->cap) { \
|
||||
|
||||
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
+12
-7
@@ -77,8 +77,8 @@ typedef struct instruction_arm64_s {
|
||||
uintptr_t natcall;
|
||||
int retn;
|
||||
int barrier_maybe;
|
||||
flagcache_t f_exit; // flags status at end of intruction
|
||||
neoncache_t n; // neoncache at end of intruction (but before poping)
|
||||
flagcache_t f_exit; // flags status at end of instruction
|
||||
neoncache_t n; // neoncache at end of instruction (but before poping)
|
||||
flagcache_t f_entry; // flags status before the instruction begin
|
||||
} instruction_arm64_t;
|
||||
|
||||
@@ -87,12 +87,12 @@ typedef struct dynarec_arm_s {
|
||||
int32_t size;
|
||||
int32_t cap;
|
||||
uintptr_t start; // start of the block
|
||||
uint32_t isize; // size in byte of x64 instructions included
|
||||
uint32_t isize; // size in bytes of x64 instructions included
|
||||
void* block; // memory pointer where next instruction is emitted
|
||||
uintptr_t native_start; // start of the arm code
|
||||
size_t native_size; // size of emitted arm code
|
||||
uintptr_t last_ip; // last set IP in RIP (or NULL if unclean state) TODO: move to a cache something
|
||||
uint64_t* table64; // table of 64bits value
|
||||
uint64_t* table64; // table of 64bits values
|
||||
int table64size;// size of table (will be appended at end of executable code)
|
||||
int table64cap;
|
||||
uintptr_t tablestart;
|
||||
@@ -102,11 +102,14 @@ typedef struct dynarec_arm_s {
|
||||
uintptr_t* next; // variable array of "next" jump address
|
||||
int next_sz;
|
||||
int next_cap;
|
||||
int* jmps; // variable array of jump instructions
|
||||
int jmp_sz;
|
||||
int jmp_cap;
|
||||
int* predecessor;// single array of all predecessor
|
||||
dynablock_t* dynablock;
|
||||
instsize_t* instsize;
|
||||
size_t insts_size; // size of the instruction size array (calculated)
|
||||
uint8_t smread; // for strongmem model emulation
|
||||
uint8_t smread; // for strongmem model emulation
|
||||
uint8_t smwrite; // for strongmem model emulation
|
||||
uintptr_t forward; // address of the last end of code while testing forward
|
||||
uintptr_t forward_to; // address of the next jump to (to check if everything is ok)
|
||||
@@ -119,14 +122,16 @@ typedef struct dynarec_arm_s {
|
||||
|
||||
void add_next(dynarec_arm_t *dyn, uintptr_t addr);
|
||||
uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr);
|
||||
void add_jump(dynarec_arm_t *dyn, int ninst);
|
||||
int get_first_jump(dynarec_arm_t *dyn, int next);
|
||||
int is_nops(dynarec_arm_t *dyn, uintptr_t addr, int n);
|
||||
int is_instructions(dynarec_arm_t *dyn, uintptr_t addr, int n);
|
||||
|
||||
int Table64(dynarec_arm_t *dyn, uint64_t val, int pass); // add a value to etable64 (if needed) and gives back the imm19 to use in LDR_literal
|
||||
int Table64(dynarec_arm_t *dyn, uint64_t val, int pass); // add a value to table64 (if needed) and gives back the imm19 to use in LDR_literal
|
||||
|
||||
void CreateJmpNext(void* addr, void* next);
|
||||
|
||||
#define GO_TRACE(A, B) \
|
||||
#define GO_TRACE(A, B, s0) \
|
||||
GETIP(addr); \
|
||||
MOVx_REG(x1, xRIP); \
|
||||
STORE_XEMU_CALL(xRIP); \
|
||||
|
||||
Executable → Regular
+13
-8
@@ -41,10 +41,10 @@ dynablock_t* InvalidDynablock(dynablock_t* db, int need_lock)
|
||||
if(db->gone)
|
||||
return NULL; // already in the process of deletion!
|
||||
dynarec_log(LOG_DEBUG, "InvalidDynablock(%p), db->block=%p x64=%p:%p already gone=%d\n", db, db->block, db->x64_addr, db->x64_addr+db->x64_size-1, db->gone);
|
||||
// remove jumptable without waiting
|
||||
setJumpTableDefault64(db->x64_addr);
|
||||
if(need_lock)
|
||||
mutex_lock(&my_context->mutex_dyndump);
|
||||
// remove jumptable
|
||||
setJumpTableDefault64(db->x64_addr);
|
||||
db->done = 0;
|
||||
db->gone = 1;
|
||||
if(need_lock)
|
||||
@@ -74,10 +74,10 @@ void FreeDynablock(dynablock_t* db, int need_lock)
|
||||
if(db->gone)
|
||||
return; // already in the process of deletion!
|
||||
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x64=%p:%p already gone=%d\n", db, db->block, db->x64_addr, db->x64_addr+db->x64_size-1, db->gone);
|
||||
// remove jumptable without waiting
|
||||
setJumpTableDefault64(db->x64_addr);
|
||||
if(need_lock)
|
||||
mutex_lock(&my_context->mutex_dyndump);
|
||||
// remove jumptable
|
||||
setJumpTableDefault64(db->x64_addr);
|
||||
dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->actual_block, db->size);
|
||||
db->done = 0;
|
||||
db->gone = 1;
|
||||
@@ -171,11 +171,16 @@ dynablock_t *AddNewDynablock(uintptr_t addr)
|
||||
}
|
||||
|
||||
//TODO: move this to dynrec_arm.c and track allocated structure to avoid memory leak
|
||||
static __thread struct __jmp_buf_tag dynarec_jmpbuf;
|
||||
static __thread JUMPBUFF dynarec_jmpbuf;
|
||||
#ifdef ANDROID
|
||||
#define DYN_JMPBUF dynarec_jmpbuf
|
||||
#else
|
||||
#define DYN_JMPBUF &dynarec_jmpbuf
|
||||
#endif
|
||||
|
||||
void cancelFillBlock()
|
||||
{
|
||||
longjmp(&dynarec_jmpbuf, 1);
|
||||
longjmp(DYN_JMPBUF, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -208,8 +213,8 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
|
||||
|
||||
// fill the block
|
||||
block->x64_addr = (void*)addr;
|
||||
if(sigsetjmp(&dynarec_jmpbuf, 1)) {
|
||||
printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, cancelling\n", (void*)addr);
|
||||
if(sigsetjmp(DYN_JMPBUF, 1)) {
|
||||
printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, canceling\n", (void*)addr);
|
||||
FreeDynablock(block, 0);
|
||||
if(need_lock)
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
|
||||
Executable → Regular
File mode changed.
Executable → Regular
+80
-99
@@ -73,117 +73,96 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
// Disable "clobbered" warnings
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wclobbered"
|
||||
#endif
|
||||
void DynaCall(x64emu_t* emu, uintptr_t addr)
|
||||
{
|
||||
// prepare setjump for signal handling
|
||||
struct __jmp_buf_tag jmpbuf[1] = {0};
|
||||
int skip = 0;
|
||||
struct __jmp_buf_tag *old_jmpbuf = emu->jmpbuf;
|
||||
emu->jmpbuf = jmpbuf;
|
||||
uint64_t old_rsp = R_RSP;
|
||||
uint64_t old_rbx = R_RBX;
|
||||
uint64_t old_rdi = R_RDI;
|
||||
uint64_t old_rsi = R_RSI;
|
||||
uint64_t old_rbp = R_RBP;
|
||||
uint64_t old_rip = R_RIP;
|
||||
// save defered flags
|
||||
deferred_flags_t old_df = emu->df;
|
||||
multiuint_t old_op1 = emu->op1;
|
||||
multiuint_t old_op2 = emu->op2;
|
||||
multiuint_t old_res = emu->res;
|
||||
multiuint_t old_op1_sav= emu->op1_sav;
|
||||
multiuint_t old_res_sav= emu->res_sav;
|
||||
deferred_flags_t old_df_sav= emu->df_sav;
|
||||
// uc_link
|
||||
x64_ucontext_t* old_uc_link = emu->uc_link;
|
||||
emu->uc_link = NULL;
|
||||
|
||||
if((skip = sigsetjmp(emu->jmpbuf, 1))) {
|
||||
printf_log(LOG_DEBUG, "Setjmp DynaCall, fs=0x%x\n", emu->segs[_FS]);
|
||||
addr = R_RIP; // not sure if it should still be inside DynaCall!
|
||||
#ifdef DYNAREC
|
||||
if(box64_dynarec_test) {
|
||||
if(emu->test.clean)
|
||||
x64test_check(emu, R_RIP);
|
||||
emu->test.clean = 0;
|
||||
}
|
||||
#endif
|
||||
PushExit(emu);
|
||||
R_RIP = addr;
|
||||
emu->df = d_none;
|
||||
DynaRun(emu);
|
||||
emu->quit = 0; // reset Quit flags...
|
||||
emu->df = d_none;
|
||||
emu->uc_link = old_uc_link;
|
||||
if(emu->flags.quitonlongjmp && emu->flags.longjmp) {
|
||||
if(emu->flags.quitonlongjmp==1)
|
||||
emu->flags.longjmp = 0; // don't change anything because of the longjmp
|
||||
} else {
|
||||
// restore defered flags
|
||||
emu->df = old_df;
|
||||
emu->op1 = old_op1;
|
||||
emu->op2 = old_op2;
|
||||
emu->res = old_res;
|
||||
emu->op1_sav = old_op1_sav;
|
||||
emu->res_sav = old_res_sav;
|
||||
emu->df_sav = old_df_sav;
|
||||
// and the old registers
|
||||
R_RBX = old_rbx;
|
||||
R_RDI = old_rdi;
|
||||
R_RSI = old_rsi;
|
||||
R_RBP = old_rbp;
|
||||
R_RSP = old_rsp;
|
||||
R_RIP = old_rip; // and set back instruction pointer
|
||||
}
|
||||
#ifdef DYNAREC
|
||||
if(!box64_dynarec)
|
||||
#endif
|
||||
EmuCall(emu, addr);
|
||||
#ifdef DYNAREC
|
||||
else {
|
||||
uint64_t old_rsp = R_RSP;
|
||||
uint64_t old_rbx = R_RBX;
|
||||
uint64_t old_rdi = R_RDI;
|
||||
uint64_t old_rsi = R_RSI;
|
||||
uint64_t old_rbp = R_RBP;
|
||||
uint64_t old_rip = R_RIP;
|
||||
PushExit(emu);
|
||||
R_RIP = addr;
|
||||
emu->df = d_none;
|
||||
while(!emu->quit) {
|
||||
int is32bits = (emu->segs[_CS]==0x23);
|
||||
dynablock_t* block = (skip)?NULL:DBGetBlock(emu, R_RIP, 1, is32bits);
|
||||
if(!block || !block->block || !block->done) {
|
||||
skip = 0;
|
||||
// no block, of block doesn't have DynaRec content (yet, temp is not null)
|
||||
// Use interpreter (should use single instruction step...)
|
||||
dynarec_log(LOG_DEBUG, "%04d|Calling Interpreter @%p, emu=%p\n", GetTID(), (void*)R_RIP, emu);
|
||||
if(box64_dynarec_test)
|
||||
emu->test.clean = 0;
|
||||
Run(emu, 1);
|
||||
} else {
|
||||
dynarec_log(LOG_DEBUG, "%04d|Calling DynaRec Block @%p (%p) of %d x64 instructions (hash=0x%x) emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize ,block->hash, emu);
|
||||
CHECK_FLAGS(emu);
|
||||
// block is here, let's run it!
|
||||
native_prolog(emu, block->block);
|
||||
}
|
||||
if(emu->fork) {
|
||||
int forktype = emu->fork;
|
||||
emu->quit = 0;
|
||||
emu->fork = 0;
|
||||
emu = x64emu_fork(emu, forktype);
|
||||
}
|
||||
}
|
||||
emu->quit = 0; // reset Quit flags...
|
||||
emu->df = d_none;
|
||||
if(emu->quitonlongjmp && emu->longjmp) {
|
||||
if(emu->quitonlongjmp==1)
|
||||
emu->longjmp = 0; // don't change anything because of the longjmp
|
||||
} else {
|
||||
R_RBX = old_rbx;
|
||||
R_RDI = old_rdi;
|
||||
R_RSI = old_rsi;
|
||||
R_RBP = old_rbp;
|
||||
R_RSP = old_rsp;
|
||||
R_RIP = old_rip; // and set back instruction pointer
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// clear the setjmp
|
||||
emu->jmpbuf = old_jmpbuf;
|
||||
}
|
||||
|
||||
int DynaRun(x64emu_t* emu)
|
||||
int my_setcontext(x64emu_t* emu, void* ucp);
|
||||
void DynaRun(x64emu_t* emu)
|
||||
{
|
||||
// prepare setjump for signal handling
|
||||
struct __jmp_buf_tag jmpbuf[1] = {0};
|
||||
JUMPBUFF jmpbuf[1] = {0};
|
||||
int skip = 0;
|
||||
struct __jmp_buf_tag *old_jmpbuf = emu->jmpbuf;
|
||||
emu->jmpbuf = jmpbuf;
|
||||
JUMPBUFF *old_jmpbuf = emu->jmpbuf;
|
||||
emu->flags.jmpbuf_ready = 0;
|
||||
|
||||
if((skip=sigsetjmp(emu->jmpbuf, 1))) {
|
||||
printf_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x\n", emu->segs[_FS]);
|
||||
#ifdef DYNAREC
|
||||
if(box64_dynarec_test) {
|
||||
if(emu->test.clean)
|
||||
x64test_check(emu, R_RIP);
|
||||
emu->test.clean = 0;
|
||||
while(!(emu->quit)) {
|
||||
if(!emu->jmpbuf || (emu->flags.need_jmpbuf && emu->jmpbuf!=jmpbuf)) {
|
||||
emu->jmpbuf = jmpbuf;
|
||||
emu->flags.jmpbuf_ready = 1;
|
||||
#ifdef ANDROID
|
||||
if((skip=sigsetjmp(*(JUMPBUFF*)emu->jmpbuf, 1)))
|
||||
#else
|
||||
if((skip=sigsetjmp(emu->jmpbuf, 1)))
|
||||
#endif
|
||||
{
|
||||
printf_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x\n", emu->segs[_FS]);
|
||||
#ifdef DYNAREC
|
||||
if(box64_dynarec_test) {
|
||||
if(emu->test.clean)
|
||||
x64test_check(emu, R_RIP);
|
||||
emu->test.clean = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if(emu->flags.need_jmpbuf)
|
||||
emu->flags.need_jmpbuf = 0;
|
||||
|
||||
#ifdef DYNAREC
|
||||
if(!box64_dynarec)
|
||||
if(!box64_dynarec)
|
||||
#endif
|
||||
return Run(emu, 0);
|
||||
Run(emu, 0);
|
||||
#ifdef DYNAREC
|
||||
else {
|
||||
while(!emu->quit) {
|
||||
else {
|
||||
int is32bits = (emu->segs[_CS]==0x23);
|
||||
dynablock_t* block = (skip)?NULL:DBGetBlock(emu, R_RIP, 1, is32bits);
|
||||
if(!block || !block->block || !block->done) {
|
||||
if(!block || !block->block || !block->done || ACCESS_FLAG(F_TF)) {
|
||||
skip = 0;
|
||||
// no block, of block doesn't have DynaRec content (yet, temp is not null)
|
||||
// Use interpreter (should use single instruction step...)
|
||||
@@ -202,13 +181,15 @@ int DynaRun(x64emu_t* emu)
|
||||
emu->fork = 0;
|
||||
emu = x64emu_fork(emu, forktype);
|
||||
}
|
||||
if(emu->quit && emu->uc_link) {
|
||||
emu->quit = 0;
|
||||
my_setcontext(emu, emu->uc_link);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(emu->flags.need_jmpbuf)
|
||||
emu->quit = 0;
|
||||
}
|
||||
// clear the setjmp
|
||||
emu->jmpbuf = old_jmpbuf;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
Executable → Regular
+89
-39
@@ -78,7 +78,7 @@ void add_next(dynarec_native_t *dyn, uintptr_t addr) {
|
||||
dyn->next[dyn->next_sz++] = addr;
|
||||
}
|
||||
uintptr_t get_closest_next(dynarec_native_t *dyn, uintptr_t addr) {
|
||||
// get closest, but no addresses befores
|
||||
// get closest, but no addresses before
|
||||
uintptr_t best = 0;
|
||||
int i = 0;
|
||||
while((i<dyn->next_sz) && (best!=addr)) {
|
||||
@@ -94,6 +94,21 @@ uintptr_t get_closest_next(dynarec_native_t *dyn, uintptr_t addr) {
|
||||
}
|
||||
return best;
|
||||
}
|
||||
void add_jump(dynarec_native_t *dyn, int ninst) {
|
||||
// add slots
|
||||
if(dyn->jmp_sz == dyn->jmp_cap) {
|
||||
dyn->jmp_cap += 64;
|
||||
dyn->jmps = (int*)dynaRealloc(dyn->jmps, dyn->jmp_cap*sizeof(int));
|
||||
}
|
||||
dyn->jmps[dyn->jmp_sz++] = ninst;
|
||||
}
|
||||
int get_first_jump(dynarec_native_t *dyn, int next) {
|
||||
for(int i=0; i<dyn->jmp_sz; ++i)
|
||||
if(dyn->insts[dyn->jmps[i]].x64.jmp == next)
|
||||
return i;
|
||||
return -2;
|
||||
}
|
||||
|
||||
#define PK(A) (*((uint8_t*)(addr+(A))))
|
||||
int is_nops(dynarec_native_t *dyn, uintptr_t addr, int n)
|
||||
{
|
||||
@@ -124,8 +139,8 @@ int is_nops(dynarec_native_t *dyn, uintptr_t addr, int n)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// return size of next instuciton, -1 is unknown
|
||||
// not all instrction are setup
|
||||
// return size of next instruction, -1 is unknown
|
||||
// not all instructions are setup
|
||||
int next_instruction(dynarec_native_t *dyn, uintptr_t addr)
|
||||
{
|
||||
uint8_t opcode = PK(0);
|
||||
@@ -293,7 +308,7 @@ int Table64(dynarec_native_t *dyn, uint64_t val, int pass)
|
||||
static void fillPredecessors(dynarec_native_t* dyn)
|
||||
{
|
||||
int pred_sz = 1; // to be safe
|
||||
// compute total size of predecessor to alocate the array
|
||||
// compute total size of predecessor to allocate the array
|
||||
// first compute the jumps
|
||||
for(int i=0; i<dyn->size; ++i) {
|
||||
if(dyn->insts[i].x64.jmp && (dyn->insts[i].x64.jmp_insts!=-1)) {
|
||||
@@ -301,6 +316,13 @@ static void fillPredecessors(dynarec_native_t* dyn)
|
||||
dyn->insts[dyn->insts[i].x64.jmp_insts].pred_sz++;
|
||||
}
|
||||
}
|
||||
// remove "has_next" from orphan branch
|
||||
for(int i=0; i<dyn->size-1; ++i) {
|
||||
if(!dyn->insts[i].x64.has_next) {
|
||||
if(dyn->insts[i+1].x64.has_next && !dyn->insts[i+1].pred_sz)
|
||||
dyn->insts[i+1].x64.has_next = 0;
|
||||
}
|
||||
}
|
||||
// second the "has_next"
|
||||
for(int i=0; i<dyn->size-1; ++i) {
|
||||
if(dyn->insts[i].x64.has_next) {
|
||||
@@ -328,7 +350,7 @@ static void fillPredecessors(dynarec_native_t* dyn)
|
||||
}
|
||||
}
|
||||
|
||||
// updateNeed goes backward, from last intruction to top
|
||||
// updateNeed goes backward, from last instruction to top
|
||||
static int updateNeed(dynarec_native_t* dyn, int ninst, uint8_t need) {
|
||||
while (ninst>=0) {
|
||||
// need pending but instruction is only a subset: remove pend and use an X_ALL instead
|
||||
@@ -349,11 +371,11 @@ static int updateNeed(dynarec_native_t* dyn, int ninst, uint8_t need) {
|
||||
dyn->insts[ninst].x64.gen_flags |= X_PEND;
|
||||
dyn->insts[ninst].x64.need_after = need;
|
||||
need = dyn->insts[ninst].x64.need_after&~dyn->insts[ninst].x64.gen_flags;
|
||||
|
||||
if(dyn->insts[ninst].x64.may_set)
|
||||
need |= dyn->insts[ninst].x64.gen_flags; // forward the flags
|
||||
// Consume X_PEND if relevant
|
||||
if((need&X_PEND) && (dyn->insts[ninst].x64.set_flags&SF_PENDING))
|
||||
need &=~X_PEND;
|
||||
else if((need&X_PEND) && (dyn->insts[ninst].x64.set_flags&SF_PENDING))
|
||||
need &=~X_PEND; // Consume X_PEND if relevant
|
||||
need |= dyn->insts[ninst].x64.use_flags;
|
||||
if(dyn->insts[ninst].x64.need_before == need)
|
||||
return ninst - 1;
|
||||
@@ -368,9 +390,9 @@ static int updateNeed(dynarec_native_t* dyn, int ninst, uint8_t need) {
|
||||
else
|
||||
updateNeed(dyn, dyn->insts[ninst].pred[i], need);
|
||||
}
|
||||
if(!ok)
|
||||
return ninst - 1;
|
||||
--ninst;
|
||||
if(!ok)
|
||||
return ninst;
|
||||
}
|
||||
return ninst;
|
||||
}
|
||||
@@ -385,6 +407,7 @@ void CancelBlock64(int need_lock)
|
||||
current_helper = NULL;
|
||||
if(helper) {
|
||||
dynaFree(helper->next);
|
||||
dynaFree(helper->jmps);
|
||||
dynaFree(helper->insts);
|
||||
dynaFree(helper->predecessor);
|
||||
if(helper->table64 && (helper->table64!=(uint64_t*)helper->tablestart))
|
||||
@@ -410,7 +433,7 @@ void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr) {
|
||||
void* actual_p = (void*)AllocDynarecMap(sz);
|
||||
void* p = actual_p + sizeof(void*);
|
||||
if(actual_p==NULL) {
|
||||
dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz);
|
||||
dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, canceling block\n", block, sz);
|
||||
CancelBlock64(0);
|
||||
return NULL;
|
||||
}
|
||||
@@ -437,11 +460,11 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
|
||||
B+8 .. B+15 : 2 Native code for jmpnext (or jmp epilog in case of empty block)
|
||||
B+16 .. B+23 : jmpnext (or jmp_epilog) address
|
||||
B+24 .. B+31 : empty (in case an architecture needs more than 2 opcodes)
|
||||
B+32 .. B+32+sz : instsize (compressed array with each instruction lenght on x64 and native side)
|
||||
B+32 .. B+32+sz : instsize (compressed array with each instruction length on x64 and native side)
|
||||
|
||||
*/
|
||||
if(IsInHotPage(addr)) {
|
||||
dynarec_log(LOG_DEBUG, "Cancelling dynarec FillBlock on hotpage for %p\n", (void*)addr);
|
||||
dynarec_log(LOG_DEBUG, "Canceling dynarec FillBlock on hotpage for %p\n", (void*)addr);
|
||||
return NULL;
|
||||
}
|
||||
if(addr>=box64_nodynarec_start && addr<box64_nodynarec_end) {
|
||||
@@ -449,7 +472,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
|
||||
return CreateEmptyBlock(block, addr);
|
||||
}
|
||||
if(current_helper) {
|
||||
dynarec_log(LOG_DEBUG, "Cancelling dynarec FillBlock at %p as anothor one is going on\n", (void*)addr);
|
||||
dynarec_log(LOG_DEBUG, "Canceling dynarec FillBlock at %p as another one is going on\n", (void*)addr);
|
||||
return NULL;
|
||||
}
|
||||
// protect the 1st page
|
||||
@@ -464,10 +487,6 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
|
||||
helper.insts = (instruction_native_t*)dynaCalloc(helper.cap, sizeof(instruction_native_t));
|
||||
// pass 0, addresses, x64 jump addresses, overall size of the block
|
||||
uintptr_t end = native_pass0(&helper, addr, alternate, is32bits);
|
||||
// no need for next anymore
|
||||
dynaFree(helper.next);
|
||||
helper.next_sz = helper.next_cap = 0;
|
||||
helper.next = NULL;
|
||||
// basic checks
|
||||
if(!helper.size) {
|
||||
dynarec_log(LOG_INFO, "Warning, null-sized dynarec block (%p)\n", (void*)addr);
|
||||
@@ -486,26 +505,57 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
|
||||
// compute hash signature
|
||||
uint32_t hash = X31_hash_code((void*)addr, end-addr);
|
||||
// calculate barriers
|
||||
for(int i=0; i<helper.size; ++i)
|
||||
if(helper.insts[i].x64.jmp) {
|
||||
uintptr_t j = helper.insts[i].x64.jmp;
|
||||
if(j<start || j>=end || j==helper.insts[i].x64.addr) {
|
||||
if(j==helper.insts[i].x64.addr) // if there is a loop on some opcode, make the block "always to tested"
|
||||
helper.always_test = 1;
|
||||
helper.insts[i].x64.jmp_insts = -1;
|
||||
helper.insts[i].x64.need_after |= X_PEND;
|
||||
} else {
|
||||
// find jump address instruction
|
||||
int k=-1;
|
||||
for(int i2=0; i2<helper.size && k==-1; ++i2) {
|
||||
if(helper.insts[i2].x64.addr==j)
|
||||
k=i2;
|
||||
for(int ii=0; ii<helper.jmp_sz; ++ii) {
|
||||
int i = helper.jmps[ii];
|
||||
uintptr_t j = helper.insts[i].x64.jmp;
|
||||
if(j<start || j>=end || j==helper.insts[i].x64.addr) {
|
||||
if(j==helper.insts[i].x64.addr) // if there is a loop on some opcode, make the block "always to tested"
|
||||
helper.always_test = 1;
|
||||
helper.insts[i].x64.jmp_insts = -1;
|
||||
helper.insts[i].x64.need_after |= X_PEND;
|
||||
} else {
|
||||
// find jump address instruction
|
||||
int k=-1;
|
||||
int search = ((j>=helper.insts[0].x64.addr) && j<helper.insts[0].x64.addr+helper.isize)?1:0;
|
||||
int imin = 0;
|
||||
int imax = helper.size-1;
|
||||
int i2 = helper.size/2;
|
||||
// dichotomy search
|
||||
while(search) {
|
||||
if(helper.insts[i2].x64.addr == j) {
|
||||
k = i2;
|
||||
search = 0;
|
||||
} else if(helper.insts[i2].x64.addr>j) {
|
||||
imax = i2;
|
||||
i2 = (imax+imin)/2;
|
||||
} else {
|
||||
imin = i2;
|
||||
i2 = (imax+imin)/2;
|
||||
}
|
||||
if(search && (imax-imin)<2) {
|
||||
search = 0;
|
||||
if(helper.insts[imin].x64.addr==j)
|
||||
k = imin;
|
||||
else if(helper.insts[imax].x64.addr==j)
|
||||
k = imax;
|
||||
}
|
||||
if(k!=-1 && !helper.insts[i].barrier_maybe)
|
||||
helper.insts[k].x64.barrier |= BARRIER_FULL;
|
||||
helper.insts[i].x64.jmp_insts = k;
|
||||
}
|
||||
/*for(int i2=0; i2<helper.size && k==-1; ++i2) {
|
||||
if(helper.insts[i2].x64.addr==j)
|
||||
k=i2;
|
||||
}*/
|
||||
if(k!=-1 && !helper.insts[i].barrier_maybe)
|
||||
helper.insts[k].x64.barrier |= BARRIER_FULL;
|
||||
helper.insts[i].x64.jmp_insts = k;
|
||||
}
|
||||
}
|
||||
// no need for next and jmps anymore
|
||||
dynaFree(helper.next);
|
||||
helper.next_sz = helper.next_cap = 0;
|
||||
helper.next = NULL;
|
||||
dynaFree(helper.jmps);
|
||||
helper.jmp_sz = helper.jmp_cap = 0;
|
||||
helper.jmps = NULL;
|
||||
// fill predecessors with the jump address
|
||||
fillPredecessors(&helper);
|
||||
|
||||
@@ -513,7 +563,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
|
||||
while (pos>=0)
|
||||
pos = updateNeed(&helper, pos, 0);
|
||||
|
||||
// pass 1, float optimisations, first pass for flags
|
||||
// pass 1, float optimizations, first pass for flags
|
||||
native_pass1(&helper, addr, alternate, is32bits);
|
||||
|
||||
// pass 2, instruction size
|
||||
@@ -531,7 +581,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
|
||||
void* next = tablestart + helper.table64size*sizeof(uint64_t);
|
||||
void* instsize = next + 4*sizeof(void*);
|
||||
if(actual_p==NULL) {
|
||||
dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz);
|
||||
dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, canceling block\n", block, sz);
|
||||
CancelBlock64(0);
|
||||
return NULL;
|
||||
}
|
||||
@@ -581,7 +631,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
|
||||
// all done...
|
||||
__clear_cache(actual_p, actual_p+sz); // need to clear the cache before execution...
|
||||
block->hash = X31_hash_code(block->x64_addr, block->x64_size);
|
||||
// Check if something changed, to abbort if it as
|
||||
// Check if something changed, to abort if it is
|
||||
if((block->hash != hash)) {
|
||||
dynarec_log(LOG_DEBUG, "Warning, a block changed while being processed hash(%p:%ld)=%x/%x\n", block->x64_addr, block->x64_size, block->hash, hash);
|
||||
AddHotPage(addr);
|
||||
@@ -604,7 +654,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
|
||||
return NULL;
|
||||
}
|
||||
if(insts_rsize/sizeof(instsize_t)<helper.insts_size) {
|
||||
printf_log(LOG_NONE, "BOX64: Warning, ists_size difference in block between pass2 (%zu) and pass3 (%zu), allocated: %zu\n", oldinstsize, helper.insts_size, insts_rsize/sizeof(instsize_t));
|
||||
printf_log(LOG_NONE, "BOX64: Warning, insts_size difference in block between pass2 (%zu) and pass3 (%zu), allocated: %zu\n", oldinstsize, helper.insts_size, insts_rsize/sizeof(instsize_t));
|
||||
}
|
||||
if(!isprotectedDB(addr, end-addr)) {
|
||||
dynarec_log(LOG_DEBUG, "Warning, block unprotected while being processed %p:%ld, marking as need_test\n", block->x64_addr, block->x64_size);
|
||||
|
||||
@@ -66,12 +66,24 @@ void native_fxtract(x64emu_t* emu)
|
||||
}
|
||||
void native_fprem(x64emu_t* emu)
|
||||
{
|
||||
int32_t tmp32s = ST0.d / ST1.d;
|
||||
ST0.d -= ST1.d * tmp32s;
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
emu->sw.f.F87_C1 = (tmp32s&1);
|
||||
emu->sw.f.F87_C3 = ((tmp32s>>1)&1);
|
||||
emu->sw.f.F87_C0 = ((tmp32s>>2)&1);
|
||||
int e0, e1;
|
||||
int64_t ll;
|
||||
frexp(ST0.d, &e0);
|
||||
frexp(ST1.d, &e1);
|
||||
int32_t tmp32s = e0 - e1;
|
||||
if(tmp32s<64)
|
||||
{
|
||||
ll = (int64_t)floor(ST0.d/ST1.d);
|
||||
ST0.d = ST0.d - (ST1.d*ll);
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
emu->sw.f.F87_C1 = (ll&1)?1:0;
|
||||
emu->sw.f.F87_C3 = (ll&2)?1:0;
|
||||
emu->sw.f.F87_C0 = (ll&4)?1:0;
|
||||
} else {
|
||||
ll = (int64_t)(floor((ST0.d/ST1.d))/exp2(tmp32s - 32));
|
||||
ST0.d = ST0.d - ST1.d*ll*exp2(tmp32s - 32);
|
||||
emu->sw.f.F87_C2 = 1;
|
||||
}
|
||||
}
|
||||
void native_fyl2xp1(x64emu_t* emu)
|
||||
{
|
||||
@@ -138,7 +150,7 @@ void native_fistp64(x64emu_t* emu, int64_t* ed)
|
||||
|
||||
void native_fistt64(x64emu_t* emu, int64_t* ed)
|
||||
{
|
||||
// used of memcpy to avoid aligments issues
|
||||
// used of memcpy to avoid alignments issues
|
||||
int64_t tmp = ST0.d;
|
||||
memcpy(ed, &tmp, sizeof(tmp));
|
||||
}
|
||||
@@ -163,11 +175,28 @@ void native_priv(x64emu_t* emu)
|
||||
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
|
||||
}
|
||||
|
||||
void native_int(x64emu_t* emu, int num)
|
||||
{
|
||||
emu->test.test = 0;
|
||||
emit_interruption(emu, num, (void*)R_RIP);
|
||||
}
|
||||
|
||||
void native_singlestep(x64emu_t* emu)
|
||||
{
|
||||
emit_signal(emu, SIGTRAP, (void*)R_RIP, 1);
|
||||
}
|
||||
|
||||
void native_int3(x64emu_t* emu)
|
||||
{
|
||||
emit_signal(emu, SIGTRAP, (void*)R_RIP, 128);
|
||||
}
|
||||
|
||||
void native_div0(x64emu_t* emu)
|
||||
{
|
||||
emu->test.test = 0;
|
||||
emit_div0(emu, (void*)R_RIP, 0);
|
||||
}
|
||||
|
||||
void native_fsave(x64emu_t* emu, uint8_t* ed)
|
||||
{
|
||||
fpu_savenv(emu, (char*)ed, 0);
|
||||
@@ -194,13 +223,24 @@ void native_frstor(x64emu_t* emu, uint8_t* ed)
|
||||
|
||||
void native_fprem1(x64emu_t* emu)
|
||||
{
|
||||
// simplified version
|
||||
int32_t tmp32s = round(ST0.d / ST1.d);
|
||||
ST0.d -= ST1.d*tmp32s;
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
emu->sw.f.F87_C1 = (tmp32s&1);
|
||||
emu->sw.f.F87_C3 = ((tmp32s>>1)&1);
|
||||
emu->sw.f.F87_C0 = ((tmp32s>>2)&1);
|
||||
int e0, e1;
|
||||
int64_t ll;
|
||||
frexp(ST0.d, &e0);
|
||||
frexp(ST1.d, &e1);
|
||||
int32_t tmp32s = e0 - e1;
|
||||
if(tmp32s<64)
|
||||
{
|
||||
ll = (int64_t)round(ST0.d/ST1.d);
|
||||
ST0.d = ST0.d - (ST1.d*ll);
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
emu->sw.f.F87_C1 = (ll&1)?1:0;
|
||||
emu->sw.f.F87_C3 = (ll&2)?1:0;
|
||||
emu->sw.f.F87_C0 = (ll&4)?1:0;
|
||||
} else {
|
||||
ll = (int64_t)(trunc((ST0.d/ST1.d))/exp2(tmp32s - 32));
|
||||
ST0.d = ST0.d - ST1.d*ll*exp2(tmp32s - 32);
|
||||
emu->sw.f.F87_C2 = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t ff_mult(uint8_t a, uint8_t b)
|
||||
@@ -365,9 +405,8 @@ static int flagsCacheNeedsTransform(dynarec_native_t* dyn, int ninst) {
|
||||
return 0;
|
||||
if(dyn->insts[ninst].f_exit.dfnone) // flags are fully known, nothing we can do more
|
||||
return 0;
|
||||
/* if((dyn->f.pending!=SF_SET)
|
||||
&& (dyn->f.pending!=SF_SET_PENDING)) {
|
||||
if(dyn->f.pending!=SF_PENDING) {*/
|
||||
if(dyn->insts[jmp].f_entry.dfnone && !dyn->insts[ninst].f_exit.dfnone)
|
||||
return 1;
|
||||
switch (dyn->insts[jmp].f_entry.pending) {
|
||||
case SF_UNKNOWN: return 0;
|
||||
case SF_SET:
|
||||
@@ -376,22 +415,14 @@ static int flagsCacheNeedsTransform(dynarec_native_t* dyn, int ninst) {
|
||||
else
|
||||
return 0;
|
||||
case SF_SET_PENDING:
|
||||
if(dyn->insts[ninst].f_exit.pending!=SF_SET
|
||||
&& dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING
|
||||
&& dyn->insts[ninst].f_exit.pending!=SF_PENDING)
|
||||
return 1;
|
||||
else
|
||||
if(dyn->insts[ninst].f_exit.pending==SF_SET_PENDING)
|
||||
return 0;
|
||||
return 1;
|
||||
case SF_PENDING:
|
||||
if(dyn->insts[ninst].f_exit.pending!=SF_SET
|
||||
&& dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING
|
||||
&& dyn->insts[ninst].f_exit.pending!=SF_PENDING)
|
||||
return 1;
|
||||
else
|
||||
return (dyn->insts[jmp].f_entry.dfnone == dyn->insts[ninst].f_exit.dfnone)?0:1;
|
||||
if(dyn->insts[ninst].f_exit.pending==SF_PENDING || dyn->insts[ninst].f_exit.pending==SF_SET_PENDING)
|
||||
return 0;
|
||||
return (dyn->insts[jmp].f_entry.dfnone == dyn->insts[ninst].f_exit.dfnone)?0:1;
|
||||
}
|
||||
if(dyn->insts[jmp].f_entry.dfnone && !dyn->insts[ninst].f_exit.dfnone)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -445,6 +476,12 @@ uintptr_t fakeed(dynarec_native_t* dyn, uintptr_t addr, int ninst, uint8_t nexto
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
// return Ib on a mod/rm opcode without emiting anything
|
||||
uint8_t geted_ib(dynarec_native_t* dyn, uintptr_t addr, int ninst, uint8_t nextop)
|
||||
{
|
||||
addr = fakeed(dyn, addr, ninst, nextop);
|
||||
return F8;
|
||||
}
|
||||
#undef F8
|
||||
|
||||
int isNativeCall(dynarec_native_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn)
|
||||
|
||||
@@ -46,6 +46,9 @@ void native_clflush(x64emu_t* emu, void* p);
|
||||
void native_ud(x64emu_t* emu);
|
||||
void native_priv(x64emu_t* emu);
|
||||
void native_singlestep(x64emu_t* emu);
|
||||
void native_int3(x64emu_t* emu);
|
||||
void native_int(x64emu_t* emu, int num);
|
||||
void native_div0(x64emu_t* emu);
|
||||
|
||||
// Caches transformation (for loops) // Specific, need to be written par backend
|
||||
int CacheNeedsTransform(dynarec_native_t* dyn, int i1);
|
||||
@@ -56,6 +59,8 @@ int getNominalPred(dynarec_native_t* dyn, int ninst);
|
||||
|
||||
// Do the GETED, but don't emit anything...
|
||||
uintptr_t fakeed(dynarec_native_t* dyn, uintptr_t addr, int ninst, uint8_t nextop);
|
||||
// return Ib on a mod/rm opcode without emiting anything
|
||||
uint8_t geted_ib(dynarec_native_t* dyn, uintptr_t addr, int ninst, uint8_t nextop);
|
||||
|
||||
// Is what pointed at addr a native call? And if yes, to what function?
|
||||
int isNativeCall(dynarec_native_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn);
|
||||
|
||||
Executable → Regular
+57
-32
@@ -47,7 +47,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
|
||||
ARCH_INIT();
|
||||
int reset_n = -1;
|
||||
dyn->last_ip = (alternate || (dyn->insts && dyn->insts[0].pred_sz))?0:ip; // RIP is always set at start of block unless there is a predecessor!
|
||||
int stopblock = 2+(FindElfAddress(my_context, addr)?0:1); // if block is in elf_memory, it can be extended with bligblocks==2, else it needs 3
|
||||
int stopblock = 2+(FindElfAddress(my_context, addr)?0:1); // if block is in elf_memory, it can be extended with box64_dynarec_bigblock==2, else it needs 3
|
||||
// ok, go now
|
||||
INIT;
|
||||
while(ok) {
|
||||
@@ -74,9 +74,14 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
|
||||
}
|
||||
reset_n = -1;
|
||||
} else if(ninst && (dyn->insts[ninst].pred_sz>1 || (dyn->insts[ninst].pred_sz==1 && dyn->insts[ninst].pred[0]!=ninst-1)))
|
||||
dyn->last_ip = 0; // reset IP if some jump are comming here
|
||||
dyn->last_ip = 0; // reset IP if some jump are coming here
|
||||
fpu_propagate_stack(dyn, ninst);
|
||||
NEW_INST;
|
||||
#if STEP == 0
|
||||
if(ninst && dyn->insts[ninst-1].x64.barrier_next) {
|
||||
BARRIER(dyn->insts[ninst-1].x64.barrier_next);
|
||||
}
|
||||
#endif
|
||||
if(!ninst) {
|
||||
GOTEST(x1, x2);
|
||||
}
|
||||
@@ -88,17 +93,17 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
|
||||
if(box64_dynarec_test) {
|
||||
MESSAGE(LOG_DUMP, "TEST INIT ----\n");
|
||||
fpu_reflectcache(dyn, ninst, x1, x2, x3);
|
||||
GO_TRACE(x64test_init, 1);
|
||||
GO_TRACE(x64test_init, 1, x5);
|
||||
fpu_unreflectcache(dyn, ninst, x1, x2, x3);
|
||||
MESSAGE(LOG_DUMP, "----------\n");
|
||||
}
|
||||
#ifdef HAVE_TRACE
|
||||
else if(my_context->dec && box64_dynarec_trace) {
|
||||
if((trace_end == 0)
|
||||
if((trace_end == 0)
|
||||
|| ((ip >= trace_start) && (ip < trace_end))) {
|
||||
MESSAGE(LOG_DUMP, "TRACE ----\n");
|
||||
fpu_reflectcache(dyn, ninst, x1, x2, x3);
|
||||
GO_TRACE(PrintTrace, 1);
|
||||
GO_TRACE(PrintTrace, 1, x5);
|
||||
fpu_unreflectcache(dyn, ninst, x1, x2, x3);
|
||||
MESSAGE(LOG_DUMP, "----------\n");
|
||||
}
|
||||
@@ -107,12 +112,13 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
|
||||
|
||||
rep = 0;
|
||||
uint8_t pk = PK(0);
|
||||
while((pk==0xF2) || (pk==0xF3)) {
|
||||
rep = pk-0xF1;
|
||||
++addr;
|
||||
pk = PK(0);
|
||||
}
|
||||
while(pk==0x3E || pk==0x26) { //Branch Taken Hint ignored, same for ES: prefix
|
||||
while((pk==0xF2) || (pk==0xF3) || (pk==0x3E) || (pk==0x26)) {
|
||||
switch(pk) {
|
||||
case 0xF2: rep = 1; break;
|
||||
case 0xF3: rep = 2; break;
|
||||
case 0x3E:
|
||||
case 0x26: /* ignored */ break;
|
||||
}
|
||||
++addr;
|
||||
pk = PK(0);
|
||||
}
|
||||
@@ -166,7 +172,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
|
||||
if((dyn->insts[ii].x64.barrier&BARRIER_FULL)==BARRIER_FULL)
|
||||
reset_n = -2; // hack to say Barrier!
|
||||
else {
|
||||
reset_n = getNominalPred(dyn, ii); // may get -1 if no predecessor are availble
|
||||
reset_n = getNominalPred(dyn, ii); // may get -1 if no predecessor are available
|
||||
if(reset_n==-1) {
|
||||
reset_n = -2;
|
||||
MESSAGE(LOG_DEBUG, "Warning, Reset Caches mark not found\n");
|
||||
@@ -177,13 +183,15 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
|
||||
if(dyn->forward) {
|
||||
if(dyn->forward_to == addr && !need_epilog) {
|
||||
// we made it!
|
||||
if(box64_dynarec_dump) dynarec_log(LOG_NONE, "Forward extend block for %d bytes %p -> %p\n", dyn->forward_to-dyn->forward, (void*)dyn->forward, (void*)dyn->forward_to);
|
||||
if(box64_dynarec_dump) dynarec_log(LOG_NONE, "Forward extend block for %d bytes %s%p -> %p\n", dyn->forward_to-dyn->forward, dyn->insts[dyn->forward_ninst].x64.has_callret?"(opt. call) ":"", (void*)dyn->forward, (void*)dyn->forward_to);
|
||||
if(dyn->insts[dyn->forward_ninst].x64.has_callret && !dyn->insts[dyn->forward_ninst].x64.has_next)
|
||||
dyn->insts[dyn->forward_ninst].x64.has_next = 1; // this block actually continue
|
||||
dyn->forward = 0;
|
||||
dyn->forward_to = 0;
|
||||
dyn->forward_size = 0;
|
||||
dyn->forward_ninst = 0;
|
||||
ok = 1; // in case it was 0
|
||||
} else if ((dyn->forward_to < addr) || !ok) {
|
||||
} else if ((dyn->forward_to < addr) || ok<=0) {
|
||||
// something when wrong! rollback
|
||||
if(box64_dynarec_dump) dynarec_log(LOG_NONE, "Could not forward extend block for %d bytes %p -> %p\n", dyn->forward_to-dyn->forward, (void*)dyn->forward, (void*)dyn->forward_to);
|
||||
ok = 0;
|
||||
@@ -200,32 +208,39 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
|
||||
if(*(uint32_t*)addr!=0) { // check if need to continue (but is next 4 bytes are 0, stop)
|
||||
uintptr_t next = get_closest_next(dyn, addr);
|
||||
if(next && (
|
||||
(((next-addr)<15) && is_nops(dyn, addr, next-addr))
|
||||
(((next-addr)<15) && is_nops(dyn, addr, next-addr))
|
||||
/*||(((next-addr)<30) && is_instructions(dyn, addr, next-addr))*/ ))
|
||||
{
|
||||
ok = 1;
|
||||
// need to find back that instruction to copy the caches, as previous version cannot be used anymore
|
||||
reset_n = -2;
|
||||
for(int ii=0; ii<ninst; ++ii)
|
||||
if(dyn->insts[ii].x64.jmp == next) {
|
||||
reset_n = ii;
|
||||
ii=ninst;
|
||||
}
|
||||
if(box64_dynarec_dump) dynarec_log(LOG_NONE, "Extend block %p, %p -> %p (ninst=%d, jump from %d)\n", dyn, (void*)addr, (void*)next, ninst, reset_n);
|
||||
if(dyn->insts[ninst].x64.has_callret && !dyn->insts[ninst].x64.has_next) {
|
||||
dyn->insts[ninst].x64.has_next = 1; // this block actually continue
|
||||
} else {
|
||||
// need to find back that instruction to copy the caches, as previous version cannot be used anymore
|
||||
// and pred table is not ready yet
|
||||
reset_n = get_first_jump(dyn, next);
|
||||
}
|
||||
if(box64_dynarec_dump) dynarec_log(LOG_NONE, "Extend block %p, %s%p -> %p (ninst=%d, jump from %d)\n", dyn, dyn->insts[ninst].x64.has_callret?"(opt. call) ":"", (void*)addr, (void*)next, ninst, dyn->insts[ninst].x64.has_callret?ninst:reset_n);
|
||||
} else if(next && (next-addr)<box64_dynarec_forward && (getProtection(next)&PROT_READ)/*box64_dynarec_bigblock>=stopblock*/) {
|
||||
if(!((box64_dynarec_bigblock<stopblock) && !isJumpTableDefault64((void*)next))) {
|
||||
dyn->forward = addr;
|
||||
dyn->forward_to = next;
|
||||
dyn->forward_size = dyn->size;
|
||||
dyn->forward_ninst = ninst;
|
||||
reset_n = -2;
|
||||
ok = 1;
|
||||
if(dyn->forward) {
|
||||
if(next<dyn->forward_to)
|
||||
dyn->forward_to = next;
|
||||
reset_n = -2;
|
||||
ok = 1;
|
||||
} else {
|
||||
dyn->forward = addr;
|
||||
dyn->forward_to = next;
|
||||
dyn->forward_size = dyn->size;
|
||||
dyn->forward_ninst = ninst;
|
||||
reset_n = -2;
|
||||
ok = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(ok<0) {
|
||||
ok = 0; need_epilog=1;
|
||||
ok = 0; need_epilog=1;
|
||||
#if STEP == 0
|
||||
if(ninst) {
|
||||
--ninst;
|
||||
@@ -235,11 +250,21 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
|
||||
dyn->insts[ninst].x64.need_after |= X_PEND;
|
||||
++ninst;
|
||||
}
|
||||
if(dyn->forward) {
|
||||
// stopping too soon
|
||||
dyn->size = dyn->forward_size;
|
||||
ninst = dyn->forward_ninst+1;
|
||||
addr = dyn->forward;
|
||||
dyn->forward = 0;
|
||||
dyn->forward_to = 0;
|
||||
dyn->forward_size = 0;
|
||||
dyn->forward_ninst = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
++ninst;
|
||||
#if STEP == 0
|
||||
if(ok && (((box64_dynarec_bigblock<stopblock) && !isJumpTableDefault64((void*)addr))
|
||||
if(ok && (((box64_dynarec_bigblock<stopblock) && !isJumpTableDefault64((void*)addr))
|
||||
|| (addr>=box64_nodynarec_start && addr<box64_nodynarec_end)))
|
||||
#else
|
||||
if(ok && (ninst==dyn->size))
|
||||
@@ -279,7 +304,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
|
||||
if(need_epilog) {
|
||||
NOTEST(x3);
|
||||
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
|
||||
jump_to_epilog(dyn, ip, 0, ninst); // no linker here, it's an unknow instruction
|
||||
jump_to_epilog(dyn, ip, 0, ninst); // no linker here, it's an unknown instruction
|
||||
}
|
||||
FINI;
|
||||
MESSAGE(LOG_DUMP, "---- END OF BLOCK ---- (%d)\n", dyn->size);
|
||||
|
||||
Executable → Regular
+2
@@ -33,6 +33,8 @@ typedef struct instruction_x64_s {
|
||||
uint8_t jmp_cond; // 1 of conditionnal jump
|
||||
uint8_t has_next; // does this opcode can continue to the next?
|
||||
uint8_t barrier; // next instruction is a jump point, so no optim allowed
|
||||
uint8_t barrier_next; // next instruction needs a barrier
|
||||
uint8_t has_callret; // this instruction have an optimised call setup
|
||||
uint8_t state_flags;// One of SF_XXX state
|
||||
uint8_t use_flags; // 0 or combination of X_?F
|
||||
uint8_t set_flags; // 0 or combination of X_?F
|
||||
|
||||
Executable → Regular
+8
@@ -28,6 +28,10 @@
|
||||
#define native_lock_incif0(A) arm64_lock_incif0(A)
|
||||
#define native_lock_decifnot0(A) arm64_lock_decifnot0(A)
|
||||
#define native_lock_store(A, B) arm64_lock_store(A, B)
|
||||
#define native_lock_store_dd(A, B) arm64_lock_store_dd(A, B)
|
||||
#define native_lock_get_b(A) arm64_lock_get_b(A)
|
||||
#define native_lock_get_d(A) arm64_lock_get_d(A)
|
||||
#define native_lock_get_dd(A) arm64_lock_get_dd(A)
|
||||
|
||||
#elif defined(RV64)
|
||||
#include "rv64/rv64_lock.h"
|
||||
@@ -50,6 +54,7 @@
|
||||
#define native_lock_incif0(A) rv64_lock_incif0(A)
|
||||
#define native_lock_decifnot0(A) rv64_lock_decifnot0(A)
|
||||
#define native_lock_store(A, B) rv64_lock_store(A, B)
|
||||
#define native_lock_store_dd(A, B) rv64_lock_store_dd(A, B)
|
||||
#define native_lock_cas_d(A, B, C) rv64_lock_cas_d(A, B, C)
|
||||
#define native_lock_cas_dd(A, B, C) rv64_lock_cas_dd(A, B, C)
|
||||
|
||||
@@ -68,6 +73,9 @@
|
||||
// there is no atomic move on 16bytes, so faking it
|
||||
#define native_lock_read_dq(A, B, C) *A=tmpcas=((uint64_t*)(C))[0]; *B=((uint64_t*)(C))[1];
|
||||
#define native_lock_write_dq(A, B, C) rv64_lock_cas_dq(C, A, tmpcas, B);
|
||||
#define native_lock_get_b(A) rv64_lock_get_b(A)
|
||||
#define native_lock_get_d(A) rv64_lock_get_d(A)
|
||||
#define native_lock_get_dd(A) rv64_lock_get_dd(A)
|
||||
|
||||
#else
|
||||
#error Unsupported architecture
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
#include "dynarec_rv64_functions.h"
|
||||
#include "dynarec_rv64_helper.h"
|
||||
|
||||
int isSimpleWrapper(wrapper_t fun);
|
||||
|
||||
uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
uint8_t opcode;
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
#include "dynarec_rv64_functions.h"
|
||||
#include "dynarec_rv64_helper.h"
|
||||
|
||||
int isSimpleWrapper(wrapper_t fun);
|
||||
|
||||
uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
uint8_t nextop, opcode;
|
||||
@@ -169,7 +167,16 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x10:
|
||||
INST_NAME("ADC Eb, Gb");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETEB(x1, 0);
|
||||
GETGB(x2);
|
||||
emit_adc8(dyn, ninst, x1, x2, x4, x5, x3);
|
||||
EBBACK(x5, 0);
|
||||
break;
|
||||
case 0x11:
|
||||
INST_NAME("ADC Ed, Gd");
|
||||
READFLAGS(X_CF);
|
||||
@@ -180,7 +187,43 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
emit_adc32(dyn, ninst, rex, ed, gd, x3, x4, x5, x6);
|
||||
WBACK;
|
||||
break;
|
||||
|
||||
case 0x12:
|
||||
INST_NAME("ADC Gb, Eb");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETEB(x2, 0);
|
||||
GETGB(x1);
|
||||
emit_adc8(dyn, ninst, x1, x2, x4, x3, x5);
|
||||
GBBACK(x5);
|
||||
break;
|
||||
case 0x13:
|
||||
INST_NAME("ADC Gd, Ed");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETED(0);
|
||||
emit_adc32(dyn, ninst, rex, gd, ed, x3, x4, x5, x6);
|
||||
break;
|
||||
case 0x14:
|
||||
INST_NAME("ADC AL, Ib");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
u8 = F8;
|
||||
ANDI(x1, xRAX, 0xff);
|
||||
emit_adc8c(dyn, ninst, x1, u8, x3, x4, x5, x6);
|
||||
ANDI(xRAX, xRAX, ~0xff);
|
||||
OR(xRAX, xRAX, x1);
|
||||
break;
|
||||
case 0x15:
|
||||
INST_NAME("ADC EAX, Id");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i64 = F32S;
|
||||
MOV64xw(x1, i64);
|
||||
emit_adc32(dyn, ninst, rex, xRAX, x1, x3, x4, x5, x6);
|
||||
break;
|
||||
case 0x18:
|
||||
INST_NAME("SBB Eb, Gb");
|
||||
READFLAGS(X_CF);
|
||||
|
||||
@@ -172,7 +172,10 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
addr = dynarec64_66(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
|
||||
break;
|
||||
case 0x67:
|
||||
addr = dynarec64_67(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
|
||||
if(rex.is32bits)
|
||||
addr = dynarec64_67_32(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
|
||||
else
|
||||
addr = dynarec64_67(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
|
||||
break;
|
||||
case 0x68:
|
||||
INST_NAME("PUSH Id");
|
||||
@@ -260,6 +263,31 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x6C:
|
||||
case 0x6D:
|
||||
INST_NAME(opcode == 0x6C ? "INSB" : "INSD");
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
|
||||
GETIP(ip);
|
||||
STORE_XEMU_CALL(x3);
|
||||
CALL(native_priv, -1);
|
||||
LOAD_XEMU_CALL();
|
||||
jump_to_epilog(dyn, 0, xRIP, ninst);
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
break;
|
||||
case 0x6E:
|
||||
case 0x6F:
|
||||
INST_NAME(opcode == 0x6C ? "OUTSB" : "OUTSD");
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
|
||||
GETIP(ip);
|
||||
STORE_XEMU_CALL(x3);
|
||||
CALL(native_priv, -1);
|
||||
LOAD_XEMU_CALL();
|
||||
jump_to_epilog(dyn, 0, xRIP, ninst);
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
break;
|
||||
|
||||
#define GO(GETFLAGS, NO, YES, F) \
|
||||
READFLAGS(F); \
|
||||
i8 = F8S; \
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
#include "dynarec_rv64_functions.h"
|
||||
#include "dynarec_rv64_helper.h"
|
||||
|
||||
int isSimpleWrapper(wrapper_t fun);
|
||||
|
||||
uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
uint8_t nextop, opcode;
|
||||
@@ -420,7 +418,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
LHU(x1, ed, fixedaddress);
|
||||
ed = x1;
|
||||
}
|
||||
SW(ed, xEmu, offsetof(x64emu_t, segs[(nextop&0x38)>>3]));
|
||||
SH(ed, xEmu, offsetof(x64emu_t, segs[(nextop&0x38)>>3]));
|
||||
SW(xZR, xEmu, offsetof(x64emu_t, segs_serial[(nextop&0x38)>>3]));
|
||||
break;
|
||||
case 0x8F:
|
||||
@@ -501,15 +499,24 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
if(box64_wine) { // should this be done all the time?
|
||||
ANDI(x1, xFlags, 1 << F_TF);
|
||||
CBZ_NEXT(x1);
|
||||
MOV64x(xRIP, addr);
|
||||
STORE_XEMU_CALL();
|
||||
CALL(native_singlestep, -1);
|
||||
ANDI(xFlags, xFlags, ~(1 << F_TF));
|
||||
// go to epilog, TF should trigger at end of next opcode, so using Interpretor only
|
||||
jump_to_epilog(dyn, addr, 0, ninst);
|
||||
}
|
||||
break;
|
||||
case 0x9E:
|
||||
INST_NAME("SAHF");
|
||||
SETFLAGS(X_CF | X_PF | X_AF | X_ZF | X_SF, SF_SUBSET);
|
||||
ADDI(x1, xZR, ~0b11010101);
|
||||
AND(xFlags, xFlags, x1);
|
||||
NOT(x1, x1);
|
||||
SRLI(x2, xRAX, 8);
|
||||
AND(x1, x1, x2);
|
||||
OR(xFlags, xFlags, x1);
|
||||
SET_DFNONE();
|
||||
break;
|
||||
case 0x9F:
|
||||
INST_NAME("LAHF");
|
||||
READFLAGS(X_CF|X_PF|X_AF|X_ZF|X_SF);
|
||||
READFLAGS(X_CF | X_PF | X_AF | X_ZF | X_SF);
|
||||
ANDI(x1, xFlags, 0xFF);
|
||||
SLLI(x1, x1, 8);
|
||||
MOV64x(x2, 0xffffffffffff00ffLL);
|
||||
@@ -560,7 +567,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
B_NEXT_nocond;
|
||||
MARK2; // Part with DF==1
|
||||
LBU(x1, xRSI, 0);
|
||||
LBU(x1, xRDI, 0);
|
||||
SB(x1, xRDI, 0);
|
||||
SUBI(xRSI, xRSI, 1);
|
||||
SUBI(xRDI, xRDI, 1);
|
||||
SUBI(xRCX, xRCX, 1);
|
||||
@@ -648,6 +655,48 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xA7:
|
||||
switch (rep) {
|
||||
case 1:
|
||||
case 2:
|
||||
if (rep == 1) { INST_NAME("REPNZ CMPSD"); } else { INST_NAME("REPZ CMPSD"); }
|
||||
MAYSETFLAGS();
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
CBZ_NEXT(xRCX);
|
||||
ANDI(x1, xFlags, 1 << F_DF);
|
||||
BNEZ_MARK2(x1);
|
||||
MARK; // Part with DF==0
|
||||
LDxw(x1, xRSI, 0);
|
||||
ADDI(xRSI, xRSI, rex.w ? 8 : 4);
|
||||
LDxw(x2, xRDI, 0);
|
||||
ADDI(xRDI, xRDI, rex.w ? 8 : 4);
|
||||
SUBI(xRCX, xRCX, 1);
|
||||
if (rep == 1) { BEQ_MARK3(x1, x2); } else { BNE_MARK3(x1, x2); }
|
||||
BNEZ_MARK(xRCX);
|
||||
B_MARK3_nocond;
|
||||
MARK2; // Part with DF==1
|
||||
LDxw(x1, xRSI, 0);
|
||||
SUBI(xRSI, xRSI, rex.w ? 8 : 4);
|
||||
LDxw(x2, xRDI, 0);
|
||||
SUBI(xRDI, xRDI, rex.w ? 8 : 4);
|
||||
SUBI(xRCX, xRCX, 1);
|
||||
if (rep == 1) { BEQ_MARK3(x1, x2); } else { BNE_MARK3(x1, x2); }
|
||||
BNEZ_MARK2(xRCX);
|
||||
MARK3; // end
|
||||
emit_cmp32(dyn, ninst, rex, x1, x2, x3, x4, x5, x6);
|
||||
break;
|
||||
default:
|
||||
INST_NAME("CMPSD");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETDIR(x3, x1, rex.w ? 8 : 4);
|
||||
LDxw(x1, xRSI, 0);
|
||||
LDxw(x2, xRDI, 0);
|
||||
ADD(xRSI, xRSI, x3);
|
||||
ADD(xRDI, xRDI, x3);
|
||||
emit_cmp32(dyn, ninst, rex, x1, x2, x3, x4, x5, x6);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xA8:
|
||||
INST_NAME("TEST AL, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
@@ -713,6 +762,28 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
ADD(xRDI, xRDI, x3);
|
||||
}
|
||||
break;
|
||||
case 0xAC:
|
||||
if (rep) {
|
||||
DEFAULT;
|
||||
} else {
|
||||
INST_NAME("LODSB");
|
||||
GETDIR(x1, x2, 1);
|
||||
LBU(x2, xRSI, 0);
|
||||
ADD(xRSI, xRSI, x1);
|
||||
ANDI(xRAX, xRAX, ~0xff);
|
||||
OR(xRAX, xRAX, x2);
|
||||
}
|
||||
break;
|
||||
case 0xAD:
|
||||
if (rep) {
|
||||
DEFAULT;
|
||||
} else {
|
||||
INST_NAME("LODSD");
|
||||
GETDIR(x1, x2, rex.w ? 8 : 4);
|
||||
LDxw(xRAX, xRSI, 0);
|
||||
ADD(xRSI, xRSI, x1);
|
||||
}
|
||||
break;
|
||||
case 0xAE:
|
||||
switch (rep) {
|
||||
case 1:
|
||||
@@ -782,10 +853,9 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
INST_NAME("SCASD");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETDIR(x3, x1, rex.w?8:4);
|
||||
AND(x1, xRAX, xMASK);
|
||||
LDxw(x2, xRDI, 0);
|
||||
ADD(xRDI, xRDI, x3);
|
||||
emit_cmp32(dyn, ninst, rex, x1, x2, x3, x4, x5, x6);
|
||||
emit_cmp32(dyn, ninst, rex, xRAX, x2, x3, x4, x5, x6);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "dynarec_rv64_helper.h"
|
||||
|
||||
int isSimpleWrapper(wrapper_t fun);
|
||||
int isRetX87Wrapper(wrapper_t fun);
|
||||
|
||||
uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
@@ -307,6 +308,9 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
// disabling isSimpleWrapper because all signed value less than 64bits needs to be sign extended
|
||||
// and return value needs to be cleanned up
|
||||
tmp = 0;//isSimpleWrapper(*(wrapper_t*)(addr));
|
||||
if(isRetX87Wrapper(*(wrapper_t*)(addr)))
|
||||
// return value will be on the stack, so the stack depth needs to be updated
|
||||
x87_purgecache(dyn, ninst, 0, x3, x1, x4);
|
||||
if(tmp<0 || tmp>1)
|
||||
tmp=0; //TODO: removed when FP is in place
|
||||
if((box64_log<2 && !cycle_log) && tmp) {
|
||||
@@ -315,7 +319,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
addr+=8+8;
|
||||
} else {
|
||||
GETIP(ip+1); // read the 0xCC
|
||||
STORE_XEMU_CALL();
|
||||
STORE_XEMU_CALL(x3);
|
||||
ADDI(x1, xEmu, (uint32_t)offsetof(x64emu_t, ip)); // setup addr as &emu->ip
|
||||
CALL_S(x64Int3, -1);
|
||||
LOAD_XEMU_CALL();
|
||||
@@ -356,7 +360,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
NOTEST(x1);
|
||||
SMEND();
|
||||
GETIP(addr);
|
||||
STORE_XEMU_CALL();
|
||||
STORE_XEMU_CALL(x3);
|
||||
CALL_S(x86Syscall, -1);
|
||||
LOAD_XEMU_CALL();
|
||||
TABLE64(x3, addr); // expected return address
|
||||
@@ -364,13 +368,13 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
LW(x1, xEmu, offsetof(x64emu_t, quit));
|
||||
BEQ_NEXT(x1, xZR);
|
||||
MARK;
|
||||
LOAD_XEMU_REM();
|
||||
LOAD_XEMU_REM(x3);
|
||||
jump_to_epilog(dyn, 0, xRIP, ninst);
|
||||
} else {
|
||||
INST_NAME("INT n");
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
|
||||
GETIP(ip);
|
||||
STORE_XEMU_CALL();
|
||||
STORE_XEMU_CALL(x3);
|
||||
CALL(native_priv, -1);
|
||||
LOAD_XEMU_CALL();
|
||||
jump_to_epilog(dyn, 0, xRIP, ninst);
|
||||
@@ -499,6 +503,16 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
WBACK;
|
||||
if(!wback && !rex.w) ZEROUP(ed);
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("RCL Ed, 1");
|
||||
MESSAGE("LOG_DUMP", "Need optimization\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
MOV32w(x2, 1);
|
||||
GETEDW(x4, x1, 0);
|
||||
CALL_(rex.w ? ((void*)rcl64) : ((void*)rcl32), ed, x4);
|
||||
WBACK;
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("RCR Ed, 1");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
@@ -600,7 +614,9 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
case 0xD9:
|
||||
addr = dynarec64_D9(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
|
||||
break;
|
||||
|
||||
case 0xDA:
|
||||
addr = dynarec64_DA(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
|
||||
break;
|
||||
case 0xDB:
|
||||
addr = dynarec64_DB(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
|
||||
break;
|
||||
@@ -617,6 +633,58 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
case 0xDF:
|
||||
addr = dynarec64_DF(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
|
||||
break;
|
||||
#define GO(Z) \
|
||||
BARRIER(BARRIER_MAYBE); \
|
||||
JUMP(addr+i8, 1); \
|
||||
if(dyn->insts[ninst].x64.jmp_insts==-1 || \
|
||||
CHECK_CACHE()) { \
|
||||
/* out of the block */ \
|
||||
i32 = dyn->insts[ninst].epilog-(dyn->native_size); \
|
||||
if(Z) {BNE(xRCX, xZR, i32);} else {BEQ(xRCX, xZR, i32);}; \
|
||||
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
|
||||
if(!(dyn->insts[ninst].x64.barrier&BARRIER_FLOAT)) \
|
||||
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
|
||||
jump_to_next(dyn, addr+i8, 0, ninst); \
|
||||
} else { \
|
||||
CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \
|
||||
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \
|
||||
B(i32); \
|
||||
} \
|
||||
} else { \
|
||||
/* inside the block */ \
|
||||
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \
|
||||
if(Z) {BEQ(xRCX, xZR, i32);} else {BNE(xRCX, xZR, i32);}; \
|
||||
}
|
||||
case 0xE0:
|
||||
INST_NAME("LOOPNZ");
|
||||
READFLAGS(X_ZF);
|
||||
i8 = F8S;
|
||||
SUBI(xRCX, xRCX, 1);
|
||||
ANDI(x1, xFlags, 1 << F_ZF);
|
||||
CBNZ_NEXT(x1);
|
||||
GO(0);
|
||||
break;
|
||||
case 0xE1:
|
||||
INST_NAME("LOOPZ");
|
||||
READFLAGS(X_ZF);
|
||||
i8 = F8S;
|
||||
SUBI(xRCX, xRCX, 1);
|
||||
ANDI(x1, xFlags, 1 << F_ZF);
|
||||
CBZ_NEXT(x1);
|
||||
GO(0);
|
||||
break;
|
||||
case 0xE2:
|
||||
INST_NAME("LOOP");
|
||||
i8 = F8S;
|
||||
SUBI(xRCX, xRCX, 1);
|
||||
GO(0);
|
||||
break;
|
||||
case 0xE3:
|
||||
INST_NAME("JECXZ");
|
||||
i8 = F8S;
|
||||
GO(1);
|
||||
break;
|
||||
#undef GO
|
||||
|
||||
case 0xE8:
|
||||
INST_NAME("CALL Id");
|
||||
@@ -657,6 +725,9 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
tmp=0; // float paramters not ready!
|
||||
} else
|
||||
tmp=0;
|
||||
if(dyn->insts[ninst].natcall && isRetX87Wrapper(*(wrapper_t*)(dyn->insts[ninst].natcall+2)))
|
||||
// return value will be on the stack, so the stack depth needs to be updated
|
||||
x87_purgecache(dyn, ninst, 0, x3, x1, x4);
|
||||
if((box64_log<2 && !cycle_log) && dyn->insts[ninst].natcall && tmp) {
|
||||
//GETIP(ip+3+8+8); // read the 0xCC
|
||||
call_n(dyn, ninst, *(void**)(dyn->insts[ninst].natcall+2+8), tmp);
|
||||
@@ -664,7 +735,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
dyn->last_ip = addr;
|
||||
} else {
|
||||
GETIP_(dyn->insts[ninst].natcall); // read the 0xCC already
|
||||
STORE_XEMU_CALL();
|
||||
STORE_XEMU_CALL(x3);
|
||||
ADDI(x1, xEmu, (uint32_t)offsetof(x64emu_t, ip)); // setup addr as &emu->ip
|
||||
CALL_S(x64Int3, -1);
|
||||
LOAD_XEMU_CALL();
|
||||
@@ -696,7 +767,6 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
|
||||
}
|
||||
// regular call
|
||||
//BARRIER_NEXT(1);
|
||||
if(box64_dynarec_callret && box64_dynarec_bigblock>1) {
|
||||
BARRIER(BARRIER_FULL);
|
||||
} else {
|
||||
@@ -1017,7 +1087,11 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
break;
|
||||
case 0xFC:
|
||||
INST_NAME("CLD");
|
||||
ANDI(xFlags, xFlags, ~(1<<F_CF));
|
||||
ANDI(xFlags, xFlags, ~(1 << F_DF));
|
||||
break;
|
||||
case 0xFD:
|
||||
INST_NAME("STD");
|
||||
ORI(xFlags, xFlags, 1 << F_DF);
|
||||
break;
|
||||
case 0xFE:
|
||||
nextop = F8;
|
||||
@@ -1109,12 +1183,12 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
INST_NAME("JMP FAR Ed");
|
||||
READFLAGS(X_PEND);
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
SMREAD()
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 0, 0);
|
||||
LDxw(x1, wback, 0);
|
||||
ed = x1;
|
||||
LHU(x3, wback, rex.w?8:4);
|
||||
SW(x3, xEmu, offsetof(x64emu_t, segs[_CS]));
|
||||
SH(x3, xEmu, offsetof(x64emu_t, segs[_CS]));
|
||||
SW(xZR, xEmu, offsetof(x64emu_t, segs_serial[_CS]));
|
||||
jump_to_epilog(dyn, 0, ed, ninst);
|
||||
*need_epilog = 0;
|
||||
|
||||
+796
-517
File diff suppressed because it is too large.
Load diff
@@ -393,7 +393,44 @@ uintptr_t dynarec64_64(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
LDxw(gd, x4, fixedaddress);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x8E:
|
||||
INST_NAME("MOV Seg,Ew");
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
nextop = F8;
|
||||
u8 = (nextop&0x38) >> 3;
|
||||
if ((nextop&0xC0) == 0xC0) {
|
||||
ed = xRAX+(nextop&7) + (rex.b<<3);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 0, 0);
|
||||
ADD(x4, wback, x4);
|
||||
LHU(x1, x4, 0);
|
||||
ed = x1;
|
||||
}
|
||||
SH(ed, xEmu, offsetof(x64emu_t, segs[u8]));
|
||||
SW(xZR, xEmu, offsetof(x64emu_t, segs_serial[u8]));
|
||||
break;
|
||||
case 0x8F:
|
||||
INST_NAME("POP FS:Ed");
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
nextop = F8;
|
||||
if (MODREG) {
|
||||
POP1z(xRAX + (nextop & 7) + (rex.b << 3));
|
||||
} else {
|
||||
POP1z(x3); // so this can handle POP [ESP] and maybe some variant too
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 0, 0);
|
||||
if (ed == xRSP) {
|
||||
ADD(x4, ed, x4);
|
||||
SDz(x3, x4, 0);
|
||||
} else {
|
||||
// complicated to just allow a segfault that can be recovered correctly
|
||||
ADDIz(xRSP, xRSP, rex.is32bits ? -4 : -8);
|
||||
ADD(x4, ed, x4);
|
||||
SDz(x3, x4, 0);
|
||||
ADDIz(xRSP, xRSP, rex.is32bits ? 4 : 8);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xA1:
|
||||
INST_NAME("MOV EAX,FS:Od");
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
@@ -489,6 +526,20 @@ uintptr_t dynarec64_64(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFF:
|
||||
nextop = F8;
|
||||
grab_segdata(dyn, addr, ninst, x6, seg);
|
||||
switch((nextop>>3)&7) {
|
||||
case 6: // Push Ed
|
||||
INST_NAME("PUSH Ed");
|
||||
GETEDOz(x6, 0, x3);
|
||||
PUSH1z(ed);
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "emu/x64run_private.h"
|
||||
#include "x64trace.h"
|
||||
#include "dynarec_native.h"
|
||||
#include "custommem.h"
|
||||
|
||||
#include "rv64_printer.h"
|
||||
#include "dynarec_rv64_private.h"
|
||||
@@ -115,7 +116,48 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
OR(xRAX, xRAX, x1);
|
||||
break;
|
||||
case 0x0F:
|
||||
addr = dynarec64_660F(dyn, addr, ip, ninst, rex, ok, need_epilog);
|
||||
switch(rep) {
|
||||
case 0: addr = dynarec64_660F(dyn, addr, ip, ninst, rex, ok, need_epilog); break;
|
||||
case 1: addr = dynarec64_66F20F(dyn, addr, ip, ninst, rex, ok, need_epilog); break;
|
||||
case 2: addr = dynarec64_66F30F(dyn, addr, ip, ninst, rex, ok, need_epilog); break;
|
||||
}
|
||||
break;
|
||||
case 0x11:
|
||||
INST_NAME("ADC Ew, Gw");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1, 0);
|
||||
emit_adc16(dyn, ninst, x1, x2, x4, x3, x5);
|
||||
EWBACK;
|
||||
break;
|
||||
case 0x13:
|
||||
INST_NAME("ADC Gw, Ew");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2, 0);
|
||||
emit_adc16(dyn, ninst, x1, x2, x4, x3, x5);
|
||||
GWBACK;
|
||||
break;
|
||||
case 0x15:
|
||||
INST_NAME("ADC AX, Iw");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i16 = F16;
|
||||
SRLI(x6, xMASK, 16);
|
||||
AND(x1, xRAX, x6);
|
||||
MOV32w(x2, i16);
|
||||
emit_adc16(dyn, ninst, x1, x2, x3, x4, x5);
|
||||
if (rv64_zbb) {
|
||||
ANDN(xRAX, xRAX, x6);
|
||||
} else {
|
||||
NOT(x6, x6);
|
||||
AND(xRAX, xRAX, x6);
|
||||
}
|
||||
OR(xRAX, xRAX, x1);
|
||||
break;
|
||||
case 0x19:
|
||||
INST_NAME("SBB Ew, Gw");
|
||||
@@ -427,6 +469,67 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
GETGW(x2);
|
||||
emit_test16(dyn, ninst, x1, x2, x3, x4, x5);
|
||||
break;
|
||||
case 0x87:
|
||||
INST_NAME("(LOCK)XCHG Ew, Gw");
|
||||
nextop = F8;
|
||||
if(MODREG) {
|
||||
GETGD;
|
||||
GETED(0);
|
||||
ADDI(x1, gd, 0);
|
||||
LUI(x3, 0xffff0);
|
||||
AND(gd, gd, x3);
|
||||
ZEXTH(x4, ed);
|
||||
OR(gd, gd, x4);
|
||||
AND(ed, ed, x3);
|
||||
ZEXTH(x4, x1);
|
||||
OR(ed, ed, x4);
|
||||
} else {
|
||||
GETGD;
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
|
||||
SMDMB();
|
||||
|
||||
ANDI(x3, ed, 1);
|
||||
BNEZ_MARK(x3);
|
||||
|
||||
ANDI(x3, ed, 0b10);
|
||||
LUI(x5, 0xffff0);
|
||||
ZEXTH(x6, gd);
|
||||
BNEZ_MARK3(x3);
|
||||
|
||||
MARKLOCK;
|
||||
LR_W(x1, ed, 1, 0);
|
||||
AND(x3, x1, x5);
|
||||
OR(x3, x3, x6);
|
||||
SC_W(x3, x3, ed, 0, 1);
|
||||
BNEZ_MARKLOCK(x3);
|
||||
ZEXTH(x1, x1);
|
||||
B_MARK2_nocond;
|
||||
|
||||
MARK3;
|
||||
NOT(x5, x5);
|
||||
SLLI(x5, x5, 16);
|
||||
SLLI(x6, x6, 16);
|
||||
NOT(x5, x5);
|
||||
LR_W(x1, ed, 1, 0);
|
||||
AND(x3, x1, x5);
|
||||
OR(x3, x3, x6);
|
||||
SC_W(x3, x3, ed, 0, 1);
|
||||
BNEZ(x3, -4 * 4);
|
||||
SRLI(x1, x1, 16);
|
||||
ZEXTH(x1, x1);
|
||||
B_MARK2_nocond;
|
||||
|
||||
MARK;
|
||||
LHU(x1, ed, 0);
|
||||
SH(gd, ed, 0);
|
||||
|
||||
MARK2;
|
||||
SMDMB();
|
||||
LUI(x5, 0xffff0);
|
||||
AND(gd, gd, x5);
|
||||
OR(gd, gd, x1);
|
||||
}
|
||||
break;
|
||||
case 0x89:
|
||||
INST_NAME("MOV Ew, Gw");
|
||||
nextop = F8;
|
||||
@@ -441,7 +544,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
OR(ed, ed, x2);
|
||||
}
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
|
||||
SH(gd, ed, fixedaddress);
|
||||
SMWRITELOCK(lock);
|
||||
}
|
||||
@@ -504,6 +607,29 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
AND(x1, x1, x2);
|
||||
OR(xRAX, xRAX, x1);
|
||||
break;
|
||||
case 0xA1:
|
||||
INST_NAME("MOV EAX,Od");
|
||||
if (rex.is32bits) u64 = F32; else u64 = F64;
|
||||
MOV64z(x1, u64);
|
||||
if (isLockAddress(u64)) lock = 1; else lock = 0;
|
||||
SMREADLOCK(lock);
|
||||
LHU(x2, x1, 0);
|
||||
LUI(x3, 0xffff0);
|
||||
AND(xRAX, xRAX, x3);
|
||||
OR(xRAX, xRAX, x2);
|
||||
break;
|
||||
case 0xA3:
|
||||
INST_NAME("MOV Od,EAX");
|
||||
if(rex.is32bits)
|
||||
u64 = F32;
|
||||
else
|
||||
u64 = F64;
|
||||
MOV64z(x1, u64);
|
||||
if(isLockAddress(u64)) lock=1; else lock = 0;
|
||||
SH(xRAX, x1, 0);
|
||||
SMWRITELOCK(lock);
|
||||
break;
|
||||
|
||||
case 0xA5:
|
||||
if(rep) {
|
||||
INST_NAME("REP MOVSW");
|
||||
@@ -535,6 +661,48 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
ADD(xRDI, xRDI, x3);
|
||||
}
|
||||
break;
|
||||
case 0xA7:
|
||||
switch (rep) {
|
||||
case 1:
|
||||
case 2:
|
||||
if (rep == 1) { INST_NAME("REPNZ CMPSW"); } else { INST_NAME("REPZ CMPSW"); }
|
||||
MAYSETFLAGS();
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
CBZ_NEXT(xRCX);
|
||||
ANDI(x1, xFlags, 1 << F_DF);
|
||||
BNEZ_MARK2(x1);
|
||||
MARK; // Part with DF==0
|
||||
LHU(x1, xRSI, 0);
|
||||
ADDI(xRSI, xRSI, 2);
|
||||
LHU(x2, xRDI, 0);
|
||||
ADDI(xRDI, xRDI, 2);
|
||||
SUBI(xRCX, xRCX, 1);
|
||||
if (rep == 1) { BEQ_MARK3(x1, x2); } else { BNE_MARK3(x1, x2); }
|
||||
BNEZ_MARK(xRCX);
|
||||
B_MARK3_nocond;
|
||||
MARK2; // Part with DF==1
|
||||
LHU(x1, xRSI, 0);
|
||||
SUBI(xRSI, xRSI, 2);
|
||||
LHU(x2, xRDI, 0);
|
||||
SUBI(xRDI, xRDI, 2);
|
||||
SUBI(xRCX, xRCX, 1);
|
||||
if (rep == 1) { BEQ_MARK3(x1, x2); } else { BNE_MARK3(x1, x2); }
|
||||
BNEZ_MARK2(xRCX);
|
||||
MARK3; // end
|
||||
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6);
|
||||
break;
|
||||
default:
|
||||
INST_NAME("CMPSW");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETDIR(x3, x1, 2);
|
||||
LHU(x1, xRSI, 0);
|
||||
LHU(x2, xRDI, 0);
|
||||
ADD(xRSI, xRSI, x3);
|
||||
ADD(xRDI, xRDI, x3);
|
||||
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xA9:
|
||||
INST_NAME("TEST AX,Iw");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
@@ -569,7 +737,19 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
ADD(xRDI, xRDI, x3);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xAD:
|
||||
if (rep) {
|
||||
DEFAULT;
|
||||
} else {
|
||||
INST_NAME("LODSW");
|
||||
GETDIR(x1, x2, 2);
|
||||
LHU(x2, xRSI, 0);
|
||||
ADD(xRSI, xRSI, x1);
|
||||
LUI(x1, 0xffff0);
|
||||
AND(xRAX, xRAX, x1);
|
||||
OR(xRAX, xRAX, x2);
|
||||
}
|
||||
break;
|
||||
case 0xAF:
|
||||
switch (rep) {
|
||||
case 1:
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -37,6 +37,35 @@ uintptr_t dynarec64_6664(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
GETREX();
|
||||
|
||||
switch(opcode) {
|
||||
case 0x89:
|
||||
INST_NAME("MOV FS:Ew, Gw");
|
||||
nextop = F8;
|
||||
GETGD; // don't need GETGW here
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
if(rex.w) {
|
||||
ADDI(ed, gd, 0);
|
||||
} else {
|
||||
if(ed!=gd) {
|
||||
LUI(x1, 0xffff0);
|
||||
AND(gd, gd, x1);
|
||||
ZEXTH(x1, ed);
|
||||
OR(gd, gd, x1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
|
||||
ADD(x4, ed, x4);
|
||||
if(rex.w) {
|
||||
SD(gd, x4, fixedaddress);
|
||||
} else {
|
||||
SH(gd, x4, fixedaddress);
|
||||
}
|
||||
SMWRITE();
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x8B:
|
||||
INST_NAME("MOV Gd, FS:Ed");
|
||||
nextop=F8;
|
||||
@@ -69,7 +98,6 @@ uintptr_t dynarec64_6664(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "dynarec.h"
|
||||
#include "emu/x64emu_private.h"
|
||||
#include "emu/x64run_private.h"
|
||||
#include "rv64_emitter.h"
|
||||
#include "x64run.h"
|
||||
#include "x64emu.h"
|
||||
#include "box64stack.h"
|
||||
@@ -48,6 +49,71 @@ uintptr_t dynarec64_66F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
GETREX();
|
||||
|
||||
switch(opcode) {
|
||||
case 0x11:
|
||||
INST_NAME("LOCK ADC Ew, Gw");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
SMDMB();
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
MOV32w(x6, 0xFFFF);
|
||||
AND(x2, ed, x6);
|
||||
emit_adc16(dyn, ninst, x1, x2, x3, x4, x5);
|
||||
if (rv64_zbb) {
|
||||
ANDN(ed, ed, x6);
|
||||
} else {
|
||||
NOT(x6, x6);
|
||||
AND(ed, ed, x6);
|
||||
}
|
||||
OR(ed, ed, x2);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x3, &fixedaddress, rex, LOCK_LOCK, 0, 0);
|
||||
ANDI(x3, wback, 0b10);
|
||||
MOV32w(x4, 0xffff); // x4 = mask
|
||||
BNEZ_MARK(x3);
|
||||
// lower 16bits
|
||||
MARKLOCK;
|
||||
LR_W(x5, wback, 1, 1);
|
||||
AND(x6, x5, x4); // x6 = Ed.h[0]
|
||||
SRLIW(x5, x5, 16);
|
||||
SLLIW(x5, x5, 16); // x5 = clear Ed.h[0]
|
||||
ADDW(x2, x1, x6); // x2 = Gw + Ew
|
||||
ANDI(x9, xFlags, 1 << F_CF);
|
||||
ADDW(x2, x2, x9); // x2 = adc
|
||||
AND(x2, x2, x4);
|
||||
OR(x5, x5, x2);
|
||||
SC_W(x2, x5, wback, 1, 1);
|
||||
BNEZ_MARKLOCK(x2);
|
||||
B_MARK3_nocond;
|
||||
MARK;
|
||||
// upper 16bits
|
||||
SLLIW(x3, x4, 16); // x3 = mask
|
||||
SUBI(wback, wback, 2); // aligning address
|
||||
SLLI(x1, x1, 16); // x1 = extended Gw
|
||||
MARK2;
|
||||
LR_W(x6, wback, 1, 1); // x6 = Ed
|
||||
AND(x5, x6, x3); // x5 = Ed.h[1] << 16
|
||||
ADDW(x5,x5, x1);
|
||||
ANDI(x9, xFlags, 1 << F_CF);
|
||||
SLLIW(x9, x9, 16);
|
||||
ADDW(x5, x5, x9); // x5 = adc << 16
|
||||
AND(x9, x6, x4); // x9 = Ed.h[0]
|
||||
OR(x5, x5, x9);
|
||||
SC_W(x9, x5, wback, 1, 1);
|
||||
BNEZ_MARK2(x9);
|
||||
IFX(X_ALL|X_PEND) {
|
||||
SRLIW(x6, x6, 16);
|
||||
SRLIW(x1, x1, 16);
|
||||
}
|
||||
MARK3;
|
||||
IFX(X_ALL|X_PEND) {
|
||||
emit_adc16(dyn, ninst, x1, x6, x3, x4, x5);
|
||||
}
|
||||
}
|
||||
SMDMB();
|
||||
break;
|
||||
case 0x81:
|
||||
case 0x83:
|
||||
nextop = F8;
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box64context.h"
|
||||
#include "dynarec.h"
|
||||
#include "emu/x64emu_private.h"
|
||||
#include "emu/x64run_private.h"
|
||||
#include "x64run.h"
|
||||
#include "x64emu.h"
|
||||
#include "box64stack.h"
|
||||
#include "callback.h"
|
||||
#include "emu/x64run_private.h"
|
||||
#include "x64trace.h"
|
||||
#include "dynarec_native.h"
|
||||
|
||||
#include "rv64_printer.h"
|
||||
#include "dynarec_rv64_private.h"
|
||||
#include "dynarec_rv64_functions.h"
|
||||
#include "dynarec_rv64_helper.h"
|
||||
|
||||
uintptr_t dynarec64_66F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip;
|
||||
(void)need_epilog;
|
||||
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop, u8, s8;
|
||||
int32_t i32;
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback, wb1, wb2, gback;
|
||||
uint8_t eb1, eb2;
|
||||
int64_t j64;
|
||||
uint64_t tmp64u, tmp64u2;
|
||||
int v0, v1;
|
||||
int q0, q1;
|
||||
int d0, d1;
|
||||
int64_t fixedaddress, gdoffset;
|
||||
int unscaled;
|
||||
|
||||
MAYUSE(d0);
|
||||
MAYUSE(d1);
|
||||
MAYUSE(q0);
|
||||
MAYUSE(q1);
|
||||
MAYUSE(eb1);
|
||||
MAYUSE(eb2);
|
||||
MAYUSE(j64);
|
||||
|
||||
static const int8_t round_round[] = { RD_RNE, RD_RDN, RD_RUP, RD_RTZ };
|
||||
|
||||
switch (opcode) {
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box64context.h"
|
||||
#include "dynarec.h"
|
||||
#include "emu/x64emu_private.h"
|
||||
#include "emu/x64run_private.h"
|
||||
#include "x64run.h"
|
||||
#include "x64emu.h"
|
||||
#include "box64stack.h"
|
||||
#include "callback.h"
|
||||
#include "emu/x64run_private.h"
|
||||
#include "x64trace.h"
|
||||
#include "dynarec_native.h"
|
||||
|
||||
#include "rv64_printer.h"
|
||||
#include "dynarec_rv64_private.h"
|
||||
#include "dynarec_rv64_functions.h"
|
||||
#include "dynarec_rv64_helper.h"
|
||||
|
||||
uintptr_t dynarec64_66F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip;
|
||||
(void)need_epilog;
|
||||
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop, u8, s8;
|
||||
int32_t i32;
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback, wb1, wb2, gback;
|
||||
uint8_t eb1, eb2;
|
||||
int64_t j64;
|
||||
uint64_t tmp64u, tmp64u2;
|
||||
int v0, v1;
|
||||
int q0, q1;
|
||||
int d0, d1;
|
||||
int64_t fixedaddress, gdoffset;
|
||||
int unscaled;
|
||||
|
||||
MAYUSE(d0);
|
||||
MAYUSE(d1);
|
||||
MAYUSE(q0);
|
||||
MAYUSE(q1);
|
||||
MAYUSE(eb1);
|
||||
MAYUSE(eb2);
|
||||
MAYUSE(j64);
|
||||
|
||||
static const int8_t round_round[] = { RD_RNE, RD_RDN, RD_RUP, RD_RTZ };
|
||||
|
||||
switch (opcode) {
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
@@ -180,6 +180,44 @@ uintptr_t dynarec64_67(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
case 0xB6:
|
||||
INST_NAME("MOVXZ Gd, Eb");
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if(MODREG) {
|
||||
if (rex.rex) {
|
||||
eb1 = xRAX + (nextop & 7) + (rex.b << 3);
|
||||
eb2 = 0;
|
||||
} else {
|
||||
ed = (nextop & 7);
|
||||
eb1 = xRAX + (ed & 3); // Ax, Cx, Dx or Bx
|
||||
eb2 = (ed & 4) >> 2; // L or H
|
||||
}
|
||||
if (eb2) {
|
||||
SRLI(gd, eb1, 8);
|
||||
ANDI(gd, gd, 0xff);
|
||||
} else {
|
||||
ANDI(gd, eb1, 0xff);
|
||||
}
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
|
||||
LBU(gd, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
case 0xB7:
|
||||
INST_NAME("MOVZX Gd, Ew");
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if(MODREG) {
|
||||
ed = xRAX + (nextop & 7) + (rex.b << 3);
|
||||
ZEXTH(gd, ed);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
|
||||
LHU(gd, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
@@ -410,6 +448,54 @@ uintptr_t dynarec64_67(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
} else
|
||||
emit_cmp32_0(dyn, ninst, rex, xRAX, x3, x4);
|
||||
break;
|
||||
case 0x63:
|
||||
INST_NAME("MOVSXD Gd, Ed");
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if (rex.w) {
|
||||
if (MODREG) { // reg <= reg
|
||||
ADDIW(gd, xRAX + (nextop & 7) + (rex.b << 3), 0);
|
||||
} else { // mem <= reg
|
||||
SMREAD();
|
||||
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
|
||||
LW(gd, ed, fixedaddress);
|
||||
}
|
||||
} else {
|
||||
if (MODREG) { // reg <= reg
|
||||
AND(gd, xRAX + (nextop & 7) + (rex.b << 3), xMASK);
|
||||
} else { // mem <= reg
|
||||
SMREAD();
|
||||
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
|
||||
LWU(gd, ed, fixedaddress);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x66:
|
||||
opcode = F8;
|
||||
switch (opcode) {
|
||||
case 0x89:
|
||||
INST_NAME("MOV Ew, Gw");
|
||||
nextop = F8;
|
||||
GETGD; // don't need GETGW here
|
||||
if (MODREG) {
|
||||
ed = xRAX + (nextop & 7) + (rex.b << 3);
|
||||
if (ed != gd) {
|
||||
LUI(x1, 0xffff0);
|
||||
AND(ed, ed, x1);
|
||||
ZEXTH(x2, gd);
|
||||
OR(ed, ed, x2);
|
||||
}
|
||||
} else {
|
||||
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
|
||||
SH(gd, ed, fixedaddress);
|
||||
SMWRITELOCK(lock);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x81:
|
||||
case 0x83:
|
||||
@@ -567,6 +653,80 @@ uintptr_t dynarec64_67(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC7:
|
||||
INST_NAME("MOV Ed, Id");
|
||||
nextop = F8;
|
||||
if(MODREG) { // reg <= i32
|
||||
i64 = F32S;
|
||||
ed = xRAX + (nextop & 7) + (rex.b << 3);
|
||||
MOV64xw(ed, i64);
|
||||
} else { // mem <= i32
|
||||
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
|
||||
i64 = F32S;
|
||||
MOV64xw(x3, i64);
|
||||
SDxw(x3, ed, fixedaddress);
|
||||
SMWRITELOCK(lock);
|
||||
}
|
||||
break;
|
||||
|
||||
#define GO(Z) \
|
||||
BARRIER(BARRIER_MAYBE); \
|
||||
JUMP(addr+i8, 1); \
|
||||
if(dyn->insts[ninst].x64.jmp_insts==-1 || \
|
||||
CHECK_CACHE()) { \
|
||||
/* out of the block */ \
|
||||
i32 = dyn->insts[ninst].epilog-(dyn->native_size); \
|
||||
if(Z) {BNE(x1, xZR, i32);} else {BEQ(x1, xZR, i32);}; \
|
||||
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
|
||||
if(!(dyn->insts[ninst].x64.barrier&BARRIER_FLOAT)) \
|
||||
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
|
||||
jump_to_next(dyn, addr+i8, 0, ninst); \
|
||||
} else { \
|
||||
CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \
|
||||
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \
|
||||
B(i32); \
|
||||
} \
|
||||
} else { \
|
||||
/* inside the block */ \
|
||||
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \
|
||||
if(Z) {BEQ(x1, xZR, i32);} else {BNE(x1, xZR, i32);}; \
|
||||
}
|
||||
case 0xE0:
|
||||
INST_NAME("LOOPNZ (32bits)");
|
||||
READFLAGS(X_ZF);
|
||||
i8 = F8S;
|
||||
SUBI(xRCX, xRCX, 1);
|
||||
ANDI(x1, xFlags, 1 << F_ZF);
|
||||
CBNZ_NEXT(x1);
|
||||
AND(x1, xRCX, xMASK);
|
||||
GO(0);
|
||||
break;
|
||||
case 0xE1:
|
||||
INST_NAME("LOOPZ (32bits)");
|
||||
READFLAGS(X_ZF);
|
||||
i8 = F8S;
|
||||
SUBI(xRCX, xRCX, 1);
|
||||
ANDI(x1, xFlags, 1 << F_ZF);
|
||||
CBZ_NEXT(x1);
|
||||
AND(x1, xRCX, xMASK);
|
||||
GO(0);
|
||||
break;
|
||||
case 0xE2:
|
||||
INST_NAME("LOOP (32bits)");
|
||||
i8 = F8S;
|
||||
SUBI(xRCX, xRCX, 1);
|
||||
AND(x1, xRCX, xMASK);
|
||||
GO(0);
|
||||
break;
|
||||
case 0xE3:
|
||||
INST_NAME("JECXZ (32bits)");
|
||||
i8 = F8S;
|
||||
AND(x1, xRCX, xMASK);
|
||||
GO(1);
|
||||
break;
|
||||
#undef GO
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box64context.h"
|
||||
#include "dynarec.h"
|
||||
#include "emu/x64emu_private.h"
|
||||
#include "emu/x64run_private.h"
|
||||
#include "x64run.h"
|
||||
#include "x64emu.h"
|
||||
#include "box64stack.h"
|
||||
#include "callback.h"
|
||||
#include "emu/x64run_private.h"
|
||||
#include "x64trace.h"
|
||||
#include "dynarec_native.h"
|
||||
|
||||
#include "rv64_printer.h"
|
||||
#include "dynarec_rv64_private.h"
|
||||
#include "dynarec_rv64_helper.h"
|
||||
#include "dynarec_rv64_functions.h"
|
||||
|
||||
uintptr_t dynarec64_67_32(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)need_epilog;
|
||||
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
uint8_t gd, ed, wback, wb, wb1, wb2, gb1, gb2, eb1, eb2;
|
||||
int64_t fixedaddress;
|
||||
int unscaled;
|
||||
int8_t i8;
|
||||
uint8_t u8;
|
||||
int32_t i32;
|
||||
int64_t j64, i64;
|
||||
int cacheupd = 0;
|
||||
int lock;
|
||||
int v0, v1, s0;
|
||||
|
||||
if(!rex.is32bits) {
|
||||
// should do a different file
|
||||
DEFAULT;
|
||||
return addr;
|
||||
}
|
||||
|
||||
rep = 0;
|
||||
while((opcode==0xF2) || (opcode==0xF3)) {
|
||||
rep = opcode-0xF1;
|
||||
opcode = F8;
|
||||
}
|
||||
|
||||
switch(opcode) {
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
@@ -43,56 +43,45 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
|
||||
switch(nextop) {
|
||||
case 0xC0 ... 0xC7:
|
||||
|
||||
INST_NAME("FADD ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
FADDS(v1, v1, v2);
|
||||
} else {
|
||||
FADDD(v1, v1, v2);
|
||||
}
|
||||
break;
|
||||
case 0xC8 ... 0xCF:
|
||||
|
||||
INST_NAME("FMUL ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
|
||||
if (ST_IS_F(0)) {
|
||||
FMULS(v1, v1, v2);
|
||||
} else {
|
||||
FMULD(v1, v1, v2);
|
||||
}
|
||||
break;
|
||||
case 0xD0 ... 0xD7:
|
||||
|
||||
INST_NAME("FCOM ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
|
||||
if (ST_IS_F(0)) {
|
||||
FCOMS(v1, v2, x1, x2, x3, x4, x5);
|
||||
} else {
|
||||
FCOMD(v1, v2, x1, x2, x3, x4, x5);
|
||||
}
|
||||
break;
|
||||
case 0xD8 ... 0xDF:
|
||||
INST_NAME("FCOMP ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
LHU(x3, xEmu, offsetof(x64emu_t, sw));
|
||||
MOV32w(x1, 0b1110100011111111); // mask off c0,c1,c2,c3
|
||||
AND(x3, x3, x1);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
|
||||
if(ST_IS_F(0)) {
|
||||
FEQS(x5, v1, v1);
|
||||
FEQS(x4, v2, v2);
|
||||
AND(x5, x5, x4);
|
||||
BEQZ(x5, 24); // undefined/NaN
|
||||
FEQS(x5, v1, v2);
|
||||
BNEZ(x5, 28); // equal
|
||||
FLTS(x3, v1, v2); // x3 = (v1<v2)?1:0
|
||||
SLLI(x1, x3, 8);
|
||||
J(20); // end
|
||||
// undefined/NaN
|
||||
LUI(x1, 1);
|
||||
ADDI(x1, x1, 0b010100000000);
|
||||
J(8); // end
|
||||
// equal
|
||||
LUI(x1, 1);
|
||||
// end
|
||||
FCOMS(v1, v2, x1, x2, x3, x4, x5);
|
||||
} else {
|
||||
FEQD(x5, v1, v1);
|
||||
FEQD(x4, v2, v2);
|
||||
AND(x5, x5, x4);
|
||||
BEQZ(x5, 24); // undefined/NaN
|
||||
FEQD(x5, v1, v2);
|
||||
BNEZ(x5, 28); // equal
|
||||
FLTD(x3, v1, v2); // x3 = (v1<v2)?1:0
|
||||
SLLI(x1, x3, 8);
|
||||
J(20); // end
|
||||
// undefined/NaN
|
||||
LUI(x1, 1);
|
||||
ADDI(x1, x1, 0b010100000000);
|
||||
J(8); // end
|
||||
// equal
|
||||
LUI(x1, 1);
|
||||
// end
|
||||
FCOMD(v1, v2, x1, x2, x3, x4, x5);
|
||||
}
|
||||
OR(x3, x3, x1);
|
||||
SH(x3, xEmu, offsetof(x64emu_t, sw));
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xE0 ... 0xE7:
|
||||
INST_NAME("FSUB ST0, STx");
|
||||
@@ -105,11 +94,19 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
}
|
||||
break;
|
||||
case 0xE8 ... 0xEF:
|
||||
|
||||
INST_NAME("FSUBR ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
|
||||
if (ST_IS_F(0)) {
|
||||
FSUBS(v1, v2, v1);
|
||||
} else {
|
||||
FSUBD(v1, v2, v1);
|
||||
}
|
||||
break;
|
||||
case 0xF0 ... 0xF7:
|
||||
INST_NAME("FDIV ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
|
||||
if(ST_IS_F(0)) {
|
||||
FDIVS(v1, v1, v2);
|
||||
} else {
|
||||
@@ -117,7 +114,14 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
}
|
||||
break;
|
||||
case 0xF8 ... 0xFF:
|
||||
DEFAULT;
|
||||
INST_NAME("FDIVR ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
|
||||
if (ST_IS_F(0)) {
|
||||
FDIVS(v1, v2, v1);
|
||||
} else {
|
||||
FDIVD(v1, v2, v1);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -148,6 +152,33 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
FMULD(v1, v1, s0);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("FCOM ST0, float[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
|
||||
FLW(s0, ed, fixedaddress);
|
||||
if (ST_IS_F(0)) {
|
||||
FCOMS(v1, s0, x1, x6, x3, x4, x5);
|
||||
} else {
|
||||
FCVTDS(s0, s0);
|
||||
FCOMD(v1, s0, x1, x6, x3, x4, x5);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("FCOMP ST0, float[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
|
||||
FLW(s0, ed, fixedaddress);
|
||||
if (ST_IS_F(0)) {
|
||||
FCOMS(v1, s0, x1, x6, x3, x4, x5);
|
||||
} else {
|
||||
FCVTDS(s0, s0);
|
||||
FCOMD(v1, s0, x1, x6, x3, x4, x5);
|
||||
}
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FSUB ST0, float[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
|
||||
@@ -161,6 +192,19 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
FSUBD(v1, v1, s0);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("FSUBR ST0, float[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
|
||||
FLW(s0, ed, fixedaddress);
|
||||
if (ST_IS_F(0)) {
|
||||
FSUBS(v1, s0, v1);
|
||||
} else {
|
||||
FCVTDS(s0, s0);
|
||||
FSUBD(v1, s0, v1);
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("FDIV ST0, float[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
|
||||
@@ -174,8 +218,19 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
FDIVD(v1, v1, s0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
case 7:
|
||||
INST_NAME("FDIVR ST0, float[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
|
||||
FLW(s0, ed, fixedaddress);
|
||||
if (ST_IS_F(0)) {
|
||||
FDIVS(v1, s0, v1);
|
||||
} else {
|
||||
FCVTDS(s0, s0);
|
||||
FDIVD(v1, s0, v1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return addr;
|
||||
|
||||
@@ -54,7 +54,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
INST_NAME("FLD STx");
|
||||
v2 = x87_do_push(dyn, ninst, x1, X87_ST(nextop&7));
|
||||
X87_PUSH_OR_FAIL(v2, dyn, ninst, x1, X87_ST(nextop&7));
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, (nextop&7)+1, X87_COMBINE(0, (nextop&7)+1));
|
||||
if(ST_IS_F(0)) {
|
||||
FMVS(v2, v1);
|
||||
@@ -87,7 +87,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
|
||||
case 0xD8:
|
||||
INST_NAME("FSTPNCE ST0, ST0");
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xD9:
|
||||
case 0xDA:
|
||||
@@ -101,7 +101,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
x87_get_st_empty(dyn, ninst, x1, x2, nextop&7, X87_ST(nextop&7));
|
||||
x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
|
||||
x87_swapreg(dyn, ninst, x1, x2, 0, nextop&7);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xE0:
|
||||
INST_NAME("FCHS");
|
||||
@@ -135,7 +135,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
|
||||
case 0xE8:
|
||||
INST_NAME("FLD1");
|
||||
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_F);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, EXT_CACHE_ST_F);
|
||||
if(ST_IS_F(0)) {
|
||||
MOV32w(x1, 0x3f800000);
|
||||
FMVWX(v1, x1);
|
||||
@@ -146,32 +146,32 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
break;
|
||||
case 0xE9:
|
||||
INST_NAME("FLDL2T");
|
||||
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_D);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, EXT_CACHE_ST_D);
|
||||
FTABLE64(v1, L2T);
|
||||
break;
|
||||
case 0xEA:
|
||||
case 0xEA:
|
||||
INST_NAME("FLDL2E");
|
||||
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_D);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, EXT_CACHE_ST_D);
|
||||
FTABLE64(v1, L2E);
|
||||
break;
|
||||
case 0xEB:
|
||||
INST_NAME("FLDPI");
|
||||
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_D);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, EXT_CACHE_ST_D);
|
||||
FTABLE64(v1, PI);
|
||||
break;
|
||||
case 0xEC:
|
||||
INST_NAME("FLDLG2");
|
||||
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_D);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, EXT_CACHE_ST_D);
|
||||
FTABLE64(v1, LG2);
|
||||
break;
|
||||
case 0xED:
|
||||
INST_NAME("FLDLN2");
|
||||
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_D);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, EXT_CACHE_ST_D);
|
||||
FTABLE64(v1, LN2);
|
||||
break;
|
||||
case 0xEE:
|
||||
INST_NAME("FLDZ");
|
||||
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_F);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, EXT_CACHE_ST_F);
|
||||
if(ST_IS_F(0)) {
|
||||
FMVWX(v1, xZR);
|
||||
} else {
|
||||
@@ -191,14 +191,14 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(native_fyl2x, -1);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xF2:
|
||||
INST_NAME("FPTAN");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
CALL(native_ftan, -1);
|
||||
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_F);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, EXT_CACHE_ST_F);
|
||||
if(ST_IS_F(0)) {
|
||||
MOV32w(x1, 0x3f800000);
|
||||
FMVWX(v1, x1);
|
||||
@@ -213,12 +213,12 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(native_fpatan, -1);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xF4:
|
||||
INST_NAME("FXTRACT");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_do_push_empty(dyn, ninst, 0);
|
||||
X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(native_fxtract, -1);
|
||||
break;
|
||||
@@ -258,7 +258,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(native_fyl2xp1, -1);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xFA:
|
||||
INST_NAME("FSQRT");
|
||||
@@ -272,7 +272,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
case 0xFB:
|
||||
INST_NAME("FSINCOS");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_do_push_empty(dyn, ninst, 0);
|
||||
X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(native_fsincos, -1);
|
||||
break;
|
||||
@@ -349,12 +349,12 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
case 0xEF:
|
||||
DEFAULT;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FLD ST0, float[ED]");
|
||||
v1 = x87_do_push(dyn, ninst, x1, box64_dynarec_x87double?EXT_CACHE_ST_D:EXT_CACHE_ST_F);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, box64_dynarec_x87double?EXT_CACHE_ST_D:EXT_CACHE_ST_F);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
|
||||
FLW(v1, ed, fixedaddress);
|
||||
if(!ST_IS_F(0)) {
|
||||
@@ -381,7 +381,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
FCVTSD(v1, v1);
|
||||
}
|
||||
FSW(v1, ed, fixedaddress);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FLDENV Ed");
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box64context.h"
|
||||
#include "dynarec.h"
|
||||
#include "emu/x64emu_private.h"
|
||||
#include "emu/x64run_private.h"
|
||||
#include "x64run.h"
|
||||
#include "x64emu.h"
|
||||
#include "box64stack.h"
|
||||
#include "callback.h"
|
||||
#include "emu/x64run_private.h"
|
||||
#include "x64trace.h"
|
||||
#include "emu/x87emu_private.h"
|
||||
#include "dynarec_native.h"
|
||||
|
||||
#include "rv64_printer.h"
|
||||
#include "dynarec_rv64_private.h"
|
||||
#include "dynarec_rv64_helper.h"
|
||||
#include "dynarec_rv64_functions.h"
|
||||
|
||||
|
||||
uintptr_t dynarec64_DA(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
uint8_t nextop = F8;
|
||||
int64_t j64;
|
||||
uint8_t ed;
|
||||
uint8_t wback;
|
||||
int v1, v2;
|
||||
int d0;
|
||||
int s0;
|
||||
int64_t fixedaddress;
|
||||
int unscaled;
|
||||
|
||||
MAYUSE(s0);
|
||||
MAYUSE(d0);
|
||||
MAYUSE(v2);
|
||||
MAYUSE(v1);
|
||||
MAYUSE(ed);
|
||||
MAYUSE(j64);
|
||||
|
||||
switch (nextop) {
|
||||
case 0xC0:
|
||||
case 0xC1:
|
||||
case 0xC2:
|
||||
case 0xC3:
|
||||
case 0xC4:
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
INST_NAME("FCMOVB ST0, STx");
|
||||
READFLAGS(X_CF);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
|
||||
ANDI(x1, xFlags, 1 << F_CF);
|
||||
CBZ_NEXT(x1);
|
||||
if (ST_IS_F(0))
|
||||
FMVS(v1, v2);
|
||||
else
|
||||
FMVD(v1, v2);
|
||||
break;
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
case 0xCA:
|
||||
case 0xCB:
|
||||
case 0xCC:
|
||||
case 0xCD:
|
||||
case 0xCE:
|
||||
case 0xCF:
|
||||
INST_NAME("FCMOVE ST0, STx");
|
||||
READFLAGS(X_ZF);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
|
||||
ANDI(x1, xFlags, 1 << F_ZF);
|
||||
CBZ_NEXT(x1);
|
||||
if (ST_IS_F(0))
|
||||
FMVS(v1, v2);
|
||||
else
|
||||
FMVD(v1, v2);
|
||||
break;
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
case 0xD2:
|
||||
case 0xD3:
|
||||
case 0xD4:
|
||||
case 0xD5:
|
||||
case 0xD6:
|
||||
case 0xD7:
|
||||
INST_NAME("FCMOVBE ST0, STx");
|
||||
READFLAGS(X_CF | X_ZF);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
|
||||
ANDI(x1, xFlags, (1 << F_CF) | (1 << F_ZF));
|
||||
CBZ_NEXT(x1);
|
||||
if (ST_IS_F(0))
|
||||
FMVS(v1, v2);
|
||||
else
|
||||
FMVD(v1, v2);
|
||||
break;
|
||||
case 0xD8:
|
||||
case 0xD9:
|
||||
case 0xDA:
|
||||
case 0xDB:
|
||||
case 0xDC:
|
||||
case 0xDD:
|
||||
case 0xDE:
|
||||
case 0xDF:
|
||||
INST_NAME("FCMOVU ST0, STx");
|
||||
READFLAGS(X_PF);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
|
||||
ANDI(x1, xFlags, (1 << F_PF));
|
||||
CBZ_NEXT(x1);
|
||||
if (ST_IS_F(0))
|
||||
FMVS(v1, v2);
|
||||
else
|
||||
FMVD(v1, v2);
|
||||
break;
|
||||
case 0xE9:
|
||||
INST_NAME("FUCOMPP ST0, ST1");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 1, X87_COMBINE(0, nextop & 7));
|
||||
if (ST_IS_F(0)) {
|
||||
FCOMS(v1, v2, x1, x2, x3, x4, x5);
|
||||
} else {
|
||||
FCOMD(v1, v2, x1, x2, x3, x4, x5);
|
||||
}
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xE4:
|
||||
case 0xF0:
|
||||
case 0xF1:
|
||||
case 0xF4:
|
||||
case 0xF5:
|
||||
case 0xF6:
|
||||
case 0xF7:
|
||||
case 0xF8:
|
||||
case 0xF9:
|
||||
case 0xFD:
|
||||
DEFAULT;
|
||||
break;
|
||||
|
||||
default:
|
||||
switch ((nextop >> 3) & 7) {
|
||||
case 6:
|
||||
INST_NAME("FIDIV ST0, Ed");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
|
||||
LW(x1, ed, fixedaddress);
|
||||
FCVTDW(v2, x1, RD_RNE);
|
||||
FDIVD(v1, v1, v2);
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
@@ -153,7 +153,7 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
SET_DFNONE();
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
IFX(F_ZF | F_PF | F_CF) {
|
||||
IFX(X_ZF | X_PF | X_CF) {
|
||||
if(ST_IS_F(0)) {
|
||||
FEQS(x5, v1, v1);
|
||||
FEQS(x4, v2, v2);
|
||||
@@ -189,7 +189,7 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xF0:
|
||||
case 0xF0:
|
||||
case 0xF1:
|
||||
case 0xF2:
|
||||
case 0xF3:
|
||||
@@ -213,7 +213,7 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FILD ST0, Ed");
|
||||
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_D);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, EXT_CACHE_ST_D);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
|
||||
LW(x1, ed, fixedaddress);
|
||||
FCVTDW(v1, x1, RD_RNE); // i32 -> double
|
||||
@@ -245,7 +245,7 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
}
|
||||
MARK2;
|
||||
SW(x4, wback, fixedaddress);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("FLD tbyte");
|
||||
@@ -268,13 +268,13 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
SH(x6, ed, fixedaddress+8);
|
||||
} else {
|
||||
if(box64_x87_no80bits) {
|
||||
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_D);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, EXT_CACHE_ST_D);
|
||||
FLD(v1, ed, fixedaddress);
|
||||
} else {
|
||||
if(ed!=x1) {
|
||||
MV(x1, ed);
|
||||
ADDI(x1, ed, fixedaddress);
|
||||
}
|
||||
x87_do_push_empty(dyn, ninst, x3);
|
||||
X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, x3);
|
||||
CALL(native_fld, -1);
|
||||
}
|
||||
}
|
||||
@@ -293,7 +293,7 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
}
|
||||
CALL(native_fstp, -1);
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
|
||||
@@ -39,69 +39,135 @@ uintptr_t dynarec64_DC(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
switch(nextop) {
|
||||
case 0xC0 ... 0xC7:
|
||||
INST_NAME("FADD STx, ST0");
|
||||
DEFAULT;
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
|
||||
if (ST_IS_F(0)) {
|
||||
FADDS(v1, v1, v2);
|
||||
} else {
|
||||
FADDD(v1, v1, v2);
|
||||
}
|
||||
break;
|
||||
case 0xC8 ... 0xCF:
|
||||
INST_NAME("FMUL STx, ST0");
|
||||
DEFAULT;
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
|
||||
if (ST_IS_F(0)) {
|
||||
FMULS(v1, v1, v2);
|
||||
} else {
|
||||
FMULD(v1, v1, v2);
|
||||
}
|
||||
break;
|
||||
case 0xD0 ... 0xD7:
|
||||
INST_NAME("FCOM ST0, STx"); //yep
|
||||
DEFAULT;
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
|
||||
if (ST_IS_F(0)) {
|
||||
FCOMS(v1, v2, x1, x2, x3, x4, x5);
|
||||
} else {
|
||||
FCOMD(v1, v2, x1, x2, x3, x4, x5);
|
||||
}
|
||||
break;
|
||||
case 0xD8 ... 0xDF:
|
||||
INST_NAME("FCOMP ST0, STx");
|
||||
DEFAULT;
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
|
||||
if (ST_IS_F(0)) {
|
||||
FCOMS(v1, v2, x1, x2, x3, x4, x5);
|
||||
} else {
|
||||
FCOMD(v1, v2, x1, x2, x3, x4, x5);
|
||||
}
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xE0 ... 0xE7:
|
||||
INST_NAME("FSUBR STx, ST0");
|
||||
DEFAULT;
|
||||
break;
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
|
||||
if (ST_IS_F(0)) {
|
||||
FSUBS(v1, v2, v1);
|
||||
} else {
|
||||
FSUBD(v1, v2, v1);
|
||||
}
|
||||
break;
|
||||
case 0xE8 ... 0xEF:
|
||||
INST_NAME("FSUB STx, ST0");
|
||||
DEFAULT;
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
|
||||
if (ST_IS_F(0)) {
|
||||
FSUBS(v1, v1, v2);
|
||||
} else {
|
||||
FSUBD(v1, v1, v2);
|
||||
}
|
||||
break;
|
||||
case 0xF0 ... 0xF7:
|
||||
INST_NAME("FDIVR STx, ST0");
|
||||
DEFAULT;
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
|
||||
if (ST_IS_F(0)) {
|
||||
FDIVS(v1, v2, v1);
|
||||
} else {
|
||||
FDIVD(v1, v2, v1);
|
||||
}
|
||||
break;
|
||||
case 0xF8 ... 0xFF:
|
||||
INST_NAME("FDIV STx, ST0");
|
||||
DEFAULT;
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
|
||||
if (ST_IS_F(0)) {
|
||||
FDIVS(v1, v1, v2);
|
||||
} else {
|
||||
FDIVD(v1, v1, v2);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FADD ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
|
||||
FLD(v2, wback, fixedaddress);
|
||||
FADDD(v1, v1, v2);
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("FMUL ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
|
||||
FLD(v2, wback, fixedaddress);
|
||||
FMULD(v1, v1, v2);
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("FCOM ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
|
||||
FLD(v2, wback, fixedaddress);
|
||||
FCOMD(v1, v2, x1, x6, x3, x4, x5);
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("FCOMP ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
|
||||
FLD(v2, wback, fixedaddress);
|
||||
|
||||
LHU(x3, xEmu, offsetof(x64emu_t, sw));
|
||||
MOV32w(x1, 0b1110100011111111); // mask off c0,c1,c2,c3
|
||||
AND(x3, x3, x1);
|
||||
FEQD(x5, v1, v1);
|
||||
FEQD(x4, v2, v2);
|
||||
AND(x5, x5, x4);
|
||||
BEQZ(x5, 24); // undefined/NaN
|
||||
FEQD(x5, v1, v2);
|
||||
BNEZ(x5, 28); // equal
|
||||
FLTD(x3, v1, v2); // x3 = (v1<v2)?1:0
|
||||
SLLI(x1, x3, 8);
|
||||
J(20); // end
|
||||
// undefined/NaN
|
||||
LUI(x1, 1);
|
||||
ADDI(x1, x1, 0b010100000000);
|
||||
J(8); // end
|
||||
// equal
|
||||
LUI(x1, 1);
|
||||
// end
|
||||
OR(x3, x3, x1);
|
||||
SH(x3, xEmu, offsetof(x64emu_t, sw));
|
||||
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
FCOMD(v1, v2, x1, x6, x3, x4, x5);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FSUB ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
|
||||
FLD(v2, wback, fixedaddress);
|
||||
FSUBD(v1, v1, v2);
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("FSUBR ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
|
||||
FLD(v2, wback, fixedaddress);
|
||||
FSUBD(v1, v2, v1);
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("FDIV ST0, double[ED]");
|
||||
@@ -111,8 +177,14 @@ uintptr_t dynarec64_DC(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
FLD(v2, wback, fixedaddress);
|
||||
FDIVD(v1, v1, v2);
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
case 7:
|
||||
INST_NAME("FDIVR ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
|
||||
FLD(v2, wback, fixedaddress);
|
||||
FDIVD(v1, v2, v1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return addr;
|
||||
|
||||
@@ -64,11 +64,17 @@ uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
case 0xD6:
|
||||
case 0xD7:
|
||||
INST_NAME("FST ST0, STx");
|
||||
DEFAULT;
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
|
||||
if (ST_IS_F(0)) {
|
||||
FMVS(v2, v1);
|
||||
} else {
|
||||
FMVD(v2, v1);
|
||||
}
|
||||
break;
|
||||
case 0xD8:
|
||||
INST_NAME("FSTP ST0, ST0");
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xD9:
|
||||
case 0xDA:
|
||||
@@ -82,7 +88,7 @@ uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
x87_get_st_empty(dyn, ninst, x1, x2, nextop&7, X87_ST(nextop&7));
|
||||
x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
|
||||
x87_swapreg(dyn, ninst, x1, x2, 0, nextop&7);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xE0:
|
||||
case 0xE1:
|
||||
@@ -93,7 +99,13 @@ uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
case 0xE6:
|
||||
case 0xE7:
|
||||
INST_NAME("FUCOM ST0, STx");
|
||||
DEFAULT;
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
|
||||
if (ST_IS_F(0)) {
|
||||
FCOMS(v1, v2, x1, x2, x3, x4, x5);
|
||||
} else {
|
||||
FCOMD(v1, v2, x1, x2, x3, x4, x5);
|
||||
}
|
||||
break;
|
||||
case 0xE8:
|
||||
case 0xE9:
|
||||
@@ -104,7 +116,14 @@ uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
case 0xEE:
|
||||
case 0xEF:
|
||||
INST_NAME("FUCOMP ST0, STx");
|
||||
DEFAULT;
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
|
||||
if (ST_IS_F(0)) {
|
||||
FCOMS(v1, v2, x1, x2, x3, x4, x5);
|
||||
} else {
|
||||
FCOMD(v1, v2, x1, x2, x3, x4, x5);
|
||||
}
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
@@ -137,7 +156,7 @@ uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FLD double");
|
||||
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_D);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, EXT_CACHE_ST_D);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
|
||||
FLD(v1, wback, fixedaddress);
|
||||
break;
|
||||
@@ -152,7 +171,7 @@ uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
|
||||
FSD(v1, wback, fixedaddress);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FNSTSW m2byte");
|
||||
|
||||
@@ -52,7 +52,7 @@ uintptr_t dynarec64_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
} else {
|
||||
FADDD(v1, v1, v2);
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
@@ -70,7 +70,7 @@ uintptr_t dynarec64_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
} else {
|
||||
FMULD(v1, v1, v2);
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
@@ -80,12 +80,27 @@ uintptr_t dynarec64_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
case 0xD5:
|
||||
case 0xD6:
|
||||
case 0xD7:
|
||||
// INST_NAME("FCOMP ST0, STx"); //yep
|
||||
DEFAULT;
|
||||
INST_NAME("FCOMP ST0, STx"); // yep
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
|
||||
if (ST_IS_F(0)) {
|
||||
FCOMS(v1, v2, x1, x2, x3, x4, x5);
|
||||
} else {
|
||||
FCOMD(v1, v2, x1, x2, x3, x4, x5);
|
||||
}
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xD9:
|
||||
// INST_NAME("FCOMPP ST0, STx");
|
||||
DEFAULT;
|
||||
INST_NAME("FCOMPP ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
|
||||
if (ST_IS_F(0)) {
|
||||
FCOMS(v1, v2, x1, x2, x3, x4, x5);
|
||||
} else {
|
||||
FCOMD(v1, v2, x1, x2, x3, x4, x5);
|
||||
}
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xE0:
|
||||
case 0xE1:
|
||||
@@ -103,7 +118,7 @@ uintptr_t dynarec64_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
} else {
|
||||
FSUBD(v1, v2, v1);
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xE8:
|
||||
case 0xE9:
|
||||
@@ -121,7 +136,7 @@ uintptr_t dynarec64_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
} else {
|
||||
FSUBD(v1, v1, v2);
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xF0:
|
||||
case 0xF1:
|
||||
@@ -139,8 +154,8 @@ uintptr_t dynarec64_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
} else {
|
||||
FDIVD(v1, v2, v1);
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
break;
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xF8:
|
||||
case 0xF9:
|
||||
case 0xFA:
|
||||
@@ -157,7 +172,7 @@ uintptr_t dynarec64_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
} else {
|
||||
FDIVD(v1, v1, v2);
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xD8:
|
||||
case 0xDA:
|
||||
@@ -166,7 +181,8 @@ uintptr_t dynarec64_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
case 0xDD:
|
||||
case 0xDE:
|
||||
case 0xDF:
|
||||
return 0;
|
||||
DEFAULT;
|
||||
break;
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
default:
|
||||
|
||||
@@ -46,7 +46,7 @@ uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
|
||||
case 0xE0:
|
||||
INST_NAME("FNSTSW AX");
|
||||
LHU(x2, xEmu, offsetof(x64emu_t, top));
|
||||
LWU(x2, xEmu, offsetof(x64emu_t, top));
|
||||
LHU(x1, xEmu, offsetof(x64emu_t, sw));
|
||||
MOV32w(x3, 0b1100011111111111); // mask
|
||||
AND(x1, x1, x3);
|
||||
@@ -68,7 +68,7 @@ uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
CLEAR_FLAGS();
|
||||
IFX(F_ZF | F_PF | F_CF) {
|
||||
IFX(X_ZF | X_PF | X_CF) {
|
||||
if(ST_IS_F(0)) {
|
||||
FEQS(x5, v1, v1);
|
||||
FEQS(x4, v2, v2);
|
||||
@@ -103,7 +103,7 @@ uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
// end
|
||||
}
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xC8 ... 0xDF:
|
||||
case 0xE1 ... 0xE7:
|
||||
@@ -115,7 +115,7 @@ uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FILD ST0, Ew");
|
||||
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_F);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, EXT_CACHE_ST_F);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x4, &fixedaddress, rex, NULL, 1, 0);
|
||||
LH(x1, wback, fixedaddress);
|
||||
if(ST_IS_F(0)) {
|
||||
@@ -144,7 +144,7 @@ uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
}
|
||||
MARK2;
|
||||
SH(x4, wback, fixedaddress);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("FISTP Ew, ST0");
|
||||
@@ -168,11 +168,11 @@ uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
}
|
||||
MARK2;
|
||||
SH(x4, wback, fixedaddress);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("FILD ST0, i64");
|
||||
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_D);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, EXT_CACHE_ST_D);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x3, &fixedaddress, rex, NULL, 1, 0);
|
||||
LD(x1, wback, fixedaddress);
|
||||
if (rex.is32bits) {
|
||||
@@ -193,6 +193,14 @@ uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
FSD(v1, x5, 0); // ref
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("FBSTP tbytes, ST0");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0);
|
||||
if (ed != x1) { MV(x1, ed); }
|
||||
CALL(fpu_fbst, -1);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FISTP i64, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
|
||||
@@ -233,7 +241,7 @@ uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
SD(x4, wback, fixedaddress);
|
||||
MARK3;
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
|
||||
@@ -63,7 +63,7 @@ void emit_add32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
|
||||
}
|
||||
IFX(X_AF | X_OF) {
|
||||
if(rv64_zbb) {
|
||||
ANDN(s3, s1, s3); // s3 = ~res & (op1 | op2)
|
||||
ANDN(s3, s3, s1); // s3 = ~res & (op1 | op2)
|
||||
} else {
|
||||
NOT(s5, s1); // s5 = ~res
|
||||
AND(s3, s5, s3); // s3 = ~res & (op1 | op2)
|
||||
@@ -160,7 +160,7 @@ void emit_add32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
|
||||
}
|
||||
IFX(X_AF | X_OF) {
|
||||
if(rv64_zbb) {
|
||||
ANDN(s3, s1, s3); // s3 = ~res & (op1 | op2)
|
||||
ANDN(s3, s3, s1); // s3 = ~res & (op1 | op2)
|
||||
} else {
|
||||
NOT(s2, s1); // s2 = ~res
|
||||
AND(s3, s2, s3); // s3 = ~res & (op1 | op2)
|
||||
@@ -218,7 +218,7 @@ void emit_add16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
|
||||
}
|
||||
IFX(X_AF | X_OF) {
|
||||
if(rv64_zbb) {
|
||||
ANDN(s3, s1, s3); // s3 = ~res & (op1 | op2)
|
||||
ANDN(s3, s3, s1); // s3 = ~res & (op1 | op2)
|
||||
} else {
|
||||
NOT(s5, s1); // s5 = ~res
|
||||
AND(s3, s5, s3); // s3 = ~res & (op1 | op2)
|
||||
@@ -280,7 +280,7 @@ void emit_add8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
|
||||
IFX(X_AF|X_OF) {
|
||||
if(rv64_zbb) {
|
||||
ANDN(s3, s1, s3); // s3 = ~res & (op1 | op2)
|
||||
ANDN(s3, s3, s1); // s3 = ~res & (op1 | op2)
|
||||
} else {
|
||||
NOT(s4, s1); // s4 = ~res
|
||||
AND(s3, s4, s3); // s3 = ~res & (op1 | op2)
|
||||
@@ -336,7 +336,7 @@ void emit_add8c(dynarec_rv64_t* dyn, int ninst, int s1, int c, int s2, int s3, i
|
||||
SET_DFNONE();
|
||||
}
|
||||
IFX(X_AF | X_OF) {
|
||||
if(X_PEND) {} else {MOV32w(s4, c&0xff);}
|
||||
IFX(X_PEND) {} else {MOV32w(s4, c&0xff);}
|
||||
OR(s3, s1, s4); // s3 = op1 | op2
|
||||
AND(s4, s1, s4); // s4 = op1 & op2
|
||||
}
|
||||
@@ -344,7 +344,7 @@ void emit_add8c(dynarec_rv64_t* dyn, int ninst, int s1, int c, int s2, int s3, i
|
||||
|
||||
IFX(X_AF|X_OF) {
|
||||
if(rv64_zbb) {
|
||||
ANDN(s3, s1, s3); // s3 = ~res & (op1 | op2)
|
||||
ANDN(s3, s3, s1); // s3 = ~res & (op1 | op2)
|
||||
} else {
|
||||
NOT(s2, s1); // s2 = ~res
|
||||
AND(s3, s2, s3); // s3 = ~res & (op1 | op2)
|
||||
@@ -596,7 +596,7 @@ void emit_inc8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
}
|
||||
IFX(X_AF | X_OF) {
|
||||
if(rv64_zbb) {
|
||||
ANDN(s3, s1, s3); // s3 = ~res & (op1 | op2)
|
||||
ANDN(s3, s3, s1); // s3 = ~res & (op1 | op2)
|
||||
} else {
|
||||
NOT(s2, s1); // s2 = ~res
|
||||
AND(s3, s2, s3); // s3 = ~res & (op1 | op2)
|
||||
@@ -709,7 +709,7 @@ void emit_inc32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
|
||||
}
|
||||
IFX(X_AF | X_OF) {
|
||||
if(rv64_zbb) {
|
||||
ANDN(s3, s1, s3); // s3 = ~res & (op1 | op2)
|
||||
ANDN(s3, s3, s1); // s3 = ~res & (op1 | op2)
|
||||
} else {
|
||||
NOT(s2, s1); // s2 = ~res
|
||||
AND(s3, s2, s3); // s3 = ~res & (op1 | op2)
|
||||
@@ -825,7 +825,7 @@ void emit_inc16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
}
|
||||
IFX(X_AF | X_OF) {
|
||||
if(rv64_zbb) {
|
||||
ANDN(s3, s1, s3); // s3 = ~res & (op1 | op2)
|
||||
ANDN(s3, s3, s1); // s3 = ~res & (op1 | op2)
|
||||
} else {
|
||||
NOT(s2, s1); // s2 = ~res
|
||||
AND(s3, s2, s3); // s3 = ~res & (op1 | op2)
|
||||
@@ -968,8 +968,8 @@ void emit_adc8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
|
||||
SET_DFNONE();
|
||||
}
|
||||
IFX(X_AF | X_OF) {
|
||||
OR(s4, s1, s2); // s3 = op1 | op2
|
||||
AND(s5, s1, s2); // s4 = op1 & op2
|
||||
OR(s4, s1, s2); // s4 = op1 | op2
|
||||
AND(s5, s1, s2); // s5 = op1 & op2
|
||||
}
|
||||
|
||||
ADD(s1, s1, s2);
|
||||
@@ -982,7 +982,7 @@ void emit_adc8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
|
||||
}
|
||||
IFX(X_AF | X_OF) {
|
||||
if(rv64_zbb) {
|
||||
ANDN(s3, s1, s4); // s3 = ~res & (op1 | op2)
|
||||
ANDN(s3, s4, s1); // s3 = ~res & (op1 | op2)
|
||||
} else {
|
||||
NOT(s2, s1); // s2 = ~res
|
||||
AND(s3, s2, s4); // s3 = ~res & (op1 | op2)
|
||||
@@ -1304,8 +1304,8 @@ void emit_adc16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
|
||||
SET_DFNONE();
|
||||
}
|
||||
IFX(X_AF | X_OF) {
|
||||
OR(s4, s1, s2); // s3 = op1 | op2
|
||||
AND(s5, s1, s2); // s4 = op1 & op2
|
||||
OR(s4, s1, s2); // s4 = op1 | op2
|
||||
AND(s5, s1, s2); // s5 = op1 & op2
|
||||
}
|
||||
|
||||
ADD(s1, s1, s2);
|
||||
@@ -1318,7 +1318,7 @@ void emit_adc16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
|
||||
}
|
||||
IFX(X_AF | X_OF) {
|
||||
if(rv64_zbb) {
|
||||
ANDN(s3, s1, s4); // s3 = ~res & (op1 | op2)
|
||||
ANDN(s3, s4, s1); // s3 = ~res & (op1 | op2)
|
||||
} else {
|
||||
NOT(s2, s1); // s2 = ~res
|
||||
AND(s3, s2, s4); // s3 = ~res & (op1 | op2)
|
||||
@@ -1386,8 +1386,8 @@ void emit_adc32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
|
||||
}
|
||||
}
|
||||
IFX(X_AF | X_OF) {
|
||||
OR(s4, s1, s2); // s3 = op1 | op2
|
||||
AND(s5, s1, s2); // s4 = op1 & op2
|
||||
OR(s4, s1, s2); // s4 = op1 | op2
|
||||
AND(s5, s1, s2); // s5 = op1 & op2
|
||||
}
|
||||
|
||||
ADDxw(s1, s1, s2);
|
||||
@@ -1404,7 +1404,7 @@ void emit_adc32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
|
||||
}
|
||||
IFX(X_AF | X_OF) {
|
||||
if(rv64_zbb) {
|
||||
ANDN(s3, s1, s4); // s3 = ~res & (op1 | op2)
|
||||
ANDN(s3, s4, s1); // s3 = ~res & (op1 | op2)
|
||||
} else {
|
||||
NOT(s2, s1); // s2 = ~res
|
||||
AND(s3, s2, s4); // s3 = ~res & (op1 | op2)
|
||||
|
||||
@@ -385,8 +385,8 @@ void emit_ror32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
|
||||
SDxw(s1, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
IFX(X_CF) {
|
||||
SRLI(s3, s1, rex.w?63:31);
|
||||
AND(xFlags, xFlags, s3);
|
||||
SRLIxw(s3, s1, rex.w?63:31);
|
||||
OR(xFlags, xFlags, s3);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
ADDI(s3, xZR, 1);
|
||||
@@ -421,6 +421,8 @@ void emit_rol32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
|
||||
}
|
||||
if(rv64_zbb) {
|
||||
RORIxw(s1, s1, (rex.w?64:32)-c);
|
||||
} else if (rv64_xtheadbb) {
|
||||
TH_SRRIxw(s1, s1, (rex.w?64:32)-c);
|
||||
} else {
|
||||
SLLIxw(s3, s1, c);
|
||||
SRLIxw(s1, s1, (rex.w?64:32)-c);
|
||||
@@ -466,6 +468,8 @@ void emit_ror32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
|
||||
}
|
||||
if(rv64_zbb) {
|
||||
RORIxw(s1, s1, c);
|
||||
} else if (rv64_xtheadbb) {
|
||||
TH_SRRIxw(s1, s1, c);
|
||||
} else {
|
||||
SRLIxw(s3, s1, c);
|
||||
SLLIxw(s1, s1, (rex.w?64:32)-c);
|
||||
@@ -475,8 +479,8 @@ void emit_ror32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
|
||||
SDxw(s1, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
IFX(X_CF) {
|
||||
SRLI(s3, s1, rex.w?63:31);
|
||||
AND(xFlags, xFlags, s3);
|
||||
SRLIxw(s3, s1, rex.w?63:31);
|
||||
OR(xFlags, xFlags, s3);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
if(c==1) {
|
||||
|
||||
Loaded 100 of 1266 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user