diff options
| author | Edmund Grimley Evans <Edmund.Grimley.Evans@gmail.com> | 2015-03-02 20:39:28 +0000 |
|---|---|---|
| committer | Edmund Grimley Evans <Edmund.Grimley.Evans@gmail.com> | 2015-03-02 20:39:28 +0000 |
| commit | 86e8dcd5e291965c27761633174fd9e65a293136 (patch) | |
| tree | 7252c4e6fb85bfc165df16ea74ca2f16b3f7ef1d /arm64-gen.c | |
| parent | 883fd365c7e17b6ede1a49835661b2446c752d19 (diff) | |
| download | tinycc-86e8dcd5e291965c27761633174fd9e65a293136.tar.gz tinycc-86e8dcd5e291965c27761633174fd9e65a293136.tar.bz2 | |
arm64: Improve constant generation, with tests.
Diffstat (limited to 'arm64-gen.c')
| -rw-r--r-- | arm64-gen.c | 30 |
1 files changed, 22 insertions, 8 deletions
diff --git a/arm64-gen.c b/arm64-gen.c index 814fa16..d64be1a 100644 --- a/arm64-gen.c +++ b/arm64-gen.c @@ -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) } } |
