ARM64: Use movi to materialize FP constants.

Thanks to Peter Cawley. #1245
This commit is contained in:
Mike Pall 2024-08-15 00:22:47 +02:00
parent 2d54213e7c
commit 6f834087d0
3 changed files with 35 additions and 0 deletions

View File

@ -658,6 +658,10 @@ local map_datafp = { -- Data processing, SIMD and FP.
} }
} }
} }
},
{ -- 010
shift = 0, mask = 0x81f8fc00,
[0x100e400] = "moviDdG"
} }
} }
@ -832,6 +836,20 @@ local function parse_fpimm8(op)
return sign * frac * 2^exp return sign * frac * 2^exp
end end
local function decode_fpmovi(op)
local lo = rshift(op, 5)
local hi = rshift(op, 9)
lo = bor(band(lo, 1) * 0xff, band(lo, 2) * 0x7f80, band(lo, 4) * 0x3fc000,
band(lo, 8) * 0x1fe00000)
hi = bor(band(hi, 1) * 0xff, band(hi, 0x80) * 0x1fe,
band(hi, 0x100) * 0xff00, band(hi, 0x200) * 0x7f8000)
if hi ~= 0 then
return fmt_hex32(hi)..tohex(lo)
else
return fmt_hex32(lo)
end
end
local function prefer_bfx(sf, uns, imms, immr) local function prefer_bfx(sf, uns, imms, immr)
if imms < immr or imms == 31 or imms == 63 then if imms < immr or imms == 31 or imms == 63 then
return false return false
@ -1131,6 +1149,8 @@ local function disass_ins(ctx)
x = 0 x = 0
elseif p == "F" then elseif p == "F" then
x = parse_fpimm8(op) x = parse_fpimm8(op)
elseif p == "G" then
x = "#0x"..decode_fpmovi(op)
elseif p == "g" or p == "f" or p == "x" or p == "w" or elseif p == "g" or p == "f" or p == "x" or p == "w" or
p == "d" or p == "s" then p == "d" or p == "s" then
-- These are handled in D/N/M/A. -- These are handled in D/N/M/A.

View File

@ -66,6 +66,17 @@ static uint32_t emit_isfpk64(uint64_t n)
return ~0u; return ~0u;
} }
static uint32_t emit_isfpmovi(uint64_t n)
{
/* Is every byte either 0x00 or 0xff? */
if ((n & U64x(01010101,01010101)) * 0xff != n) return 0;
/* Form 8-bit value by taking one bit from each byte. */
n &= U64x(80402010,08040201);
n = (n * U64x(01010101,01010101)) >> 56;
/* Split into the format expected by movi. */
return ((n & 0xe0) << 6) | 0x700 | (n & 0x1f);
}
/* -- Emit basic instructions --------------------------------------------- */ /* -- Emit basic instructions --------------------------------------------- */
static void emit_dnma(ASMState *as, A64Ins ai, Reg rd, Reg rn, Reg rm, Reg ra) static void emit_dnma(ASMState *as, A64Ins ai, Reg rd, Reg rn, Reg rm, Reg ra)
@ -300,6 +311,9 @@ static void emit_loadk64(ASMState *as, Reg r, IRIns *ir)
if (fpk != ~0u) { if (fpk != ~0u) {
emit_d(as, A64I_FMOV_DI | A64F_FP8(fpk), (r & 31)); emit_d(as, A64I_FMOV_DI | A64F_FP8(fpk), (r & 31));
return; return;
} else if ((fpk = emit_isfpmovi(*k))) {
emit_d(as, A64I_MOVI_DI | (fpk << 5), (r & 31));
return;
} }
} }
ofs = glofs(as, k); ofs = glofs(as, k);

View File

@ -320,6 +320,7 @@ typedef enum A64Ins {
A64I_FMOV_R_D = 0x9e660000, A64I_FMOV_R_D = 0x9e660000,
A64I_FMOV_D_R = 0x9e670000, A64I_FMOV_D_R = 0x9e670000,
A64I_FMOV_DI = 0x1e601000, A64I_FMOV_DI = 0x1e601000,
A64I_MOVI_DI = 0x2f000400,
} A64Ins; } A64Ins;
#define A64I_BR_AUTH (LJ_ABI_PAUTH ? A64I_BRAAZ : A64I_BR) #define A64I_BR_AUTH (LJ_ABI_PAUTH ? A64I_BRAAZ : A64I_BR)