diff options
| author | salt431 <35209044+salt431@users.noreply.github.com> | 2024-06-19 02:55:01 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-06-19 08:55:01 +0200 |
| commit | 44deff987cbca95caf8f296a27ec2f4ee2bd32c5 (patch) | |
| tree | e087ab003fbb6205cfcec5f3de165edea89b7d69 /src | |
| parent | 7273ac0d34d226066d457ec6a15ba4a9935c5680 (diff) | |
| download | box64-44deff987cbca95caf8f296a27ec2f4ee2bd32c5.tar.gz box64-44deff987cbca95caf8f296a27ec2f4ee2bd32c5.zip | |
Update arm64_immenc.c (#1602)
combine if (!bitmask || !~bitmask) to (bitmask == 0 || bitmask == ~0ULL) to reduce overhead. use bitwise operators instead of + operators.
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/arm64/arm64_immenc.c | 144 |
1 files changed, 73 insertions, 71 deletions
diff --git a/src/dynarec/arm64/arm64_immenc.c b/src/dynarec/arm64/arm64_immenc.c index ea28c9fb..010fc36d 100644 --- a/src/dynarec/arm64/arm64_immenc.c +++ b/src/dynarec/arm64/arm64_immenc.c @@ -5,82 +5,84 @@ // Returns the packed valid-N-imms-immr (1-1-6-6 bits); returns 0 if bitmask is not encodable int convert_bitmask(uint64_t bitmask) { - if (!bitmask || !~bitmask) return 0; - - uint64_t size, mask, pat; - - for (size = 6; size > 1; --size) { - mask = (one << (1 << (size - 1))) - 1; - pat = bitmask & mask; - // printf("%016lX/%lu: %016lX %016lX %2d\n", bitmask, size, mask, pat, (1 << (size - 1))); - if (pat != ((bitmask >> (1 << (size - 1))) & mask)) { - // printf("%016lX/%lu: %016lX %016lX xx\n", bitmask, size, pat, (bitmask >> (1 << (size - 1))) & mask); - break; - } - } - mask = (size >= 6) ? ((uint64_t)-1) : ((one << (1 << size)) - 1); - pat = bitmask & mask; - for (uint64_t i = 1; i < 7 - size; ++i) { - uint64_t boff = i * (1 << size); - if (((bitmask >> boff) & mask) != pat) { - // printf("%016lX/%lu: no %lu %lu %016lX %016lX %016lX\n", bitmask, size, i, size, boff, mask, pat); - return 0; - } - } - // Note that here, pat != 0 and ~pat & (1 << size) != 0 (otherwise size = 1 and bitmask = all 0 or all 1) - int immr = 0; - uint64_t last_bit = one << ((1 << size) - 1); - // printf("%016lX/%lu: %016lX %016lX %lu\n", bitmask, size, mask, pat, last_bit); - if (pat & 1) { - while (pat & last_bit) { - pat = ((pat - last_bit) << 1) + 1; - ++immr; - } - } else { - immr = 1 << size; - while (!(pat & 1)) { - pat >>= 1; - --immr; - } - } - // printf("%016lX/%lu: %016lX %016lX %lu %d\n", bitmask, size, mask, pat, last_bit, immr); - if (pat & (pat + 1)) return 0; // Not 0...01...1 - int to = 1; - while (pat & (one << to)) ++to; - - // printf("%016lX/%lu: returning %c%c%02lX%02lX\n", bitmask, size, '2' + (size == 6), (uint64_t)(((0x1E << size) & 0x3F) + (to - 1)), (uint64_t)immr); - return 0x2000 + ((size == 6) << 12) + ((((0x1E << size) & 0x3F) + (to - 1)) << 6) + immr; + if (bitmask == 0 || bitmask == ~0ULL) return 0; + + uint64_t size, mask, pat; + + for (size = 6; size > 1; --size) { + mask = (one << (1 << (size - 1))) - 1; + pat = bitmask & mask; + + if (pat != ((bitmask >> (1 << (size - 1))) & mask)) { + break; + } + } + + mask = (size >= 6) ? ~0ULL : ((one << (1 << size)) - 1); + pat = bitmask & mask; + + for (uint64_t i = 1; i < 7 - size; ++i) { + uint64_t boff = i * (1 << size); + if (((bitmask >> boff) & mask) != pat) { + return 0; + } + } + + int immr = 0; + uint64_t last_bit = one << ((1 << size) - 1); + + if (pat & 1) { + while (pat & last_bit) { + pat = ((pat - last_bit) << 1) | 1; + ++immr; + } + } else { + immr = 1 << size; + while (!(pat & 1)) { + pat >>= 1; + --immr; + } + } + + if (pat & (pat + 1)) return 0; + + int to = 1; + while (pat & (one << to)) ++to; + + return 0x2000 + ((size == 6) << 12) + ((((0x1E << size) & 0x3F) + (to - 1)) << 6) + immr; } #if 0 #include <unordered_set> int main() { - std::unordered_set<uint64_t> okvals; - uint64_t val; - for (int n = 1; n < 7; ++n) { - int imms0 = ((n == 6) ? 0xC0 : 0x80) + ((0x1E << n) & 0x3F); - for (int nones = 0; nones < (1 << n) - 1; ++nones) { - val = (one << (nones + 1)) - 1; - for (int j = 0; j < 6 - n; ++j) { - val = val + (val << (1 << (n + j))); - } - for (int immr = 0; immr < (1 << n); ++immr) { - int exp = ((imms0 + nones) << 6) + immr; - int got = convert_bitmask(val); - if (exp != got) { - printf("0x%016lX: expected %04X, got %04X\n", val, exp, got); - } - okvals.emplace(val); - val = (val >> 1) + ((val & 1) << 63); - } - } - } + std::unordered_set<uint64_t> okvals; + uint64_t val; + + for (int n = 1; n < 7; ++n) { + int imms0 = ((n == 6) ? 0xC0 : 0x80) + ((0x1E << n) & 0x3F); + for (int nones = 0; nones < (1 << n) - 1; ++nones) { + val = (one << (nones + 1)) - 1; + for (int j = 0; j < 6 - n; ++j) { + val += val << (1 << (n + j)); + } + for (int immr = 0; immr < (1 << n); ++immr) { + int exp = ((imms0 + nones) << 6) + immr; + int got = convert_bitmask(val); + if (exp != got) { + printf("0x%016lX: expected %04X, got %04X\n", val, exp, got); + } + okvals.emplace(val); + val = (val >> 1) | ((val & 1) << 63); + } + } + } + #pragma omp parallel for - for (uint64_t i = 1; i < 0xFFFFFFFFFFFFFFFFu; ++i) { - int got = convert_bitmask(val); - if (!!got != (okvals.find(val) != okvals.cend())) { - printf("0x%016lX: expected %s, got %04X\n", val, (!!got ? "0000" : "non0"), got); - } - } + for (uint64_t i = 1; i < 0xFFFFFFFFFFFFFFFFu; ++i) { + int got = convert_bitmask(i); + if (!!got != (okvals.find(i) != okvals.cend())) { + printf("0x%016lX: expected %s, got %04X\n", i, (!!got ? "non0" : "0000"), got); + } + } } #endif |