arm64: Improve constant generation, with tests.

master
Edmund Grimley Evans 2015-03-02 20:39:28 +00:00
parent 883fd365c7
commit 86e8dcd5e2
3 changed files with 55 additions and 8 deletions

View File

@ -204,16 +204,30 @@ static void arm64_movimm(int r, uint64_t x)
{
uint32_t i;
if ((i = arm64_movi(r, x)))
o(i);
o(i); // a single MOV
else {
// This could be improved:
o(0x52800000 | r | (x & 0xffff) << 5); // movz w(r),#(x & 0xffff)
for (i = 1; i < 4; i++)
if (x >> 16 * i & 0xffff) {
o(0xf2800000 | r | (x >> 16 * i & 0xffff) << 5 | i << 21);
// movk w(r),#(*),lsl #(*)
// MOVZ/MOVN and 1-3 MOVKs
int z = 0, m = 0;
uint32_t mov1 = 0xd2800000; // movz
uint64_t x1 = x;
for (i = 0; i < 64; i += 16) {
z += !(x >> i & 0xffff);
m += !(~x >> i & 0xffff);
}
if (m > z) {
x1 = ~x;
mov1 = 0x92800000; // movn
}
for (i = 0; i < 64; i += 16)
if (x1 >> i & 0xffff) {
o(mov1 | r | (x1 >> i & 0xffff) << 5 | i << 17);
// movz/movn x(r),#(*),lsl #(i)
break;
}
for (i += 16; i < 64; i += 16)
if (x1 >> i & 0xffff)
o(0xf2800000 | r | (x >> i & 0xffff) << 5 | i << 17);
// movk x(r),#(*),lsl #(i)
}
}

View File

@ -409,6 +409,24 @@ void movi(void)
pll(0x007fffc0);
pll(0x03fff80003fff800);
pll(0x0007fffffffffe00);
pll(0xabcd1234);
pll(0xabcd00001234);
pll(0xabcd000000001234);
pll(0xabcd12340000);
pll(0xabcd000012340000);
pll(0xabcd123400000000);
pll(0xffffffffabcd1234);
pll(0xffffabcdffff1234);
pll(0xabcdffffffff1234);
pll(0xffffabcd1234ffff);
pll(0xabcdffff1234ffff);
pll(0xabcd1234ffffffff);
pll(0xffffef0123456789);
pll(0xabcdef012345ffff);
pll(0xabcdef0123456789);
}
void pcs(void)

View File

@ -121,3 +121,18 @@ f8f8f8f8
7fffc0
3fff80003fff800
7fffffffffe00
abcd1234
abcd00001234
abcd000000001234
abcd12340000
abcd000012340000
abcd123400000000
ffffffffabcd1234
ffffabcdffff1234
abcdffffffff1234
ffffabcd1234ffff
abcdffff1234ffff
abcd1234ffffffff
ffffef0123456789
abcdef012345ffff
abcdef0123456789