mirror of
https://github.com/ptitSeb/box64.git
synced 2024-11-27 00:30:32 +00:00
[ARM] Added immediate encoding (#1340)
This commit is contained in:
parent
3cd87e68c7
commit
4096869c50
@ -726,6 +726,7 @@ if(ARM_DYNAREC)
|
||||
${DYNAREC_SRC}
|
||||
|
||||
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_functions.c"
|
||||
"${BOX64_ROOT}/src/dynarec/arm64/arm64_immenc.c"
|
||||
"${BOX64_ROOT}/src/dynarec/arm64/arm64_printer.c"
|
||||
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_jmpnext.c"
|
||||
|
||||
|
85
src/dynarec/arm64/arm64_immenc.c
Normal file
85
src/dynarec/arm64/arm64_immenc.c
Normal file
@ -0,0 +1,85 @@
|
||||
#include <stdint.h>
|
||||
#include "arm64_immenc.h"
|
||||
|
||||
#define one (uint64_t)1
|
||||
|
||||
// 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;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
#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);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
8
src/dynarec/arm64/arm64_immenc.h
Normal file
8
src/dynarec/arm64/arm64_immenc.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef __ARM64_IMMENC_H__
|
||||
#define __ARM64_IMMENC_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int convert_bitmask(uint64_t bitmask);
|
||||
|
||||
#endif // __ARM64_IMMENC_H__
|
Loading…
Reference in New Issue
Block a user