]> git.ipfire.org Git - thirdparty/LuaJIT.git/commitdiff
ARM64: Use movi to materialize FP constants.
authorMike Pall <mike>
Wed, 14 Aug 2024 22:22:47 +0000 (00:22 +0200)
committerMike Pall <mike>
Wed, 14 Aug 2024 22:22:47 +0000 (00:22 +0200)
Thanks to Peter Cawley. #1245

src/jit/dis_arm64.lua
src/lj_emit_arm64.h
src/lj_target_arm64.h

index 84677666285e3e8cfe734a6019a6f36a76a5822a..2741cd2ecc7113a6f2fea72c74fcd40bccd77dc4 100644 (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
 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)
   if imms < immr or imms == 31 or imms == 63 then
     return false
@@ -1131,6 +1149,8 @@ local function disass_ins(ctx)
       x = 0
     elseif p == "F" then
       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
           p == "d" or p == "s" then
       -- These are handled in D/N/M/A.
index 51d0c351eae6b7d68d6a8b27c329d086a4459e57..0967f6e4ee9dab6f758e9f9e37dff7b7898d448e 100644 (file)
@@ -66,6 +66,17 @@ static uint32_t emit_isfpk64(uint64_t n)
   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 --------------------------------------------- */
 
 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) {
       emit_d(as, A64I_FMOV_DI | A64F_FP8(fpk), (r & 31));
       return;
+    } else if ((fpk = emit_isfpmovi(*k))) {
+      emit_d(as, A64I_MOVI_DI | (fpk << 5), (r & 31));
+      return;
     }
   }
   ofs = glofs(as, k);
index c34f1e59c75d5ddee6fc05ce414e5e3d696322f4..8ed8851c034a332364778d6311744c4ae97c7ea4 100644 (file)
@@ -320,6 +320,7 @@ typedef enum A64Ins {
   A64I_FMOV_R_D = 0x9e660000,
   A64I_FMOV_D_R = 0x9e670000,
   A64I_FMOV_DI = 0x1e601000,
+  A64I_MOVI_DI = 0x2f000400,
 } A64Ins;
 
 #define A64I_BR_AUTH   (LJ_ABI_PAUTH ? A64I_BRAAZ : A64I_BR)