base/asm-common.h: Add some macros for shifting entire NEON vectors.
authorMark Wooding <mdw@distorted.org.uk>
Sat, 7 Sep 2019 13:20:19 +0000 (14:20 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Sun, 8 Sep 2019 10:38:19 +0000 (11:38 +0100)
The `vext' (A32 NEON) or `ext' (A64) instructions can be (ab)used for
shifting vectors left and right if you have a spare zero vector lying
around.  But using them is kind of confusing: left shifts, especially,
need a reversed shift quantity, and the shift is measured in bytes
rather than bits.

Add a couple of macros to make this less strange.

base/asm-common.h

index 642820a..6ec238f 100644 (file)
@@ -739,6 +739,29 @@ name:
 #endif
 .endm
 
+.macro vzero   vz=q15
+       // Set VZ (default q15) to zero.
+       vmov.u32 \vz, #0
+.endm
+
+.macro vshl128 vd, vn, nbit, vz=q15
+       // Set VD to VN shifted left by NBIT.  Assume VZ (default q15) is
+       // all-bits-zero.  NBIT must be a multiple of 8.
+  .if \nbit&3 != 0
+       .error  "shift quantity must be whole number of bytes"
+  .endif
+       vext.8  \vd, \vz, \vn, #16 - (\nbit >> 3)
+.endm
+
+.macro vshr128 vd, vn, nbit, vz=q15
+       // Set VD to VN shifted right by NBIT.  Assume VZ (default q15) is
+       // all-bits-zero.  NBIT must be a multiple of 8.
+  .if \nbit&3 != 0
+       .error  "shift quantity must be whole number of bytes"
+  .endif
+       vext.8  \vd, \vn, \vz, #\nbit >> 3
+.endm
+
 // Apply decoration decor to register name reg.
 #define _REGFORM(reg, decor) _GLUE(_REGFORM_, reg)(decor)
 
@@ -1073,6 +1096,29 @@ name:
 #endif
 .endm
 
+.macro vzero   vz=v31
+       // Set VZ (default v31) to zero.
+       dup     \vz\().4s, wzr
+.endm
+
+.macro vshl128 vd, vn, nbit, vz=v31
+       // Set VD to VN shifted left by NBIT.  Assume VZ (default v31) is
+       // all-bits-zero.  NBIT must be a multiple of 8.
+  .if \nbit&3 != 0
+       .error  "shift quantity must be whole number of bytes"
+  .endif
+       ext     \vd\().16b, \vz\().16b, \vn\().16b, #16 - (\nbit >> 3)
+.endm
+
+.macro vshr128 vd, vn, nbit, vz=v31
+       // Set VD to VN shifted right by NBIT.  Assume VZ (default v31) is
+       // all-bits-zero.  NBIT must be a multiple of 8.
+  .if \nbit&3 != 0
+       .error  "shift quantity must be whole number of bytes"
+  .endif
+       ext     \vd\().16b, \vn\().16b, \vz\().16b, #\nbit >> 3
+.endm
+
 // Stack management and unwinding.
 .macro setfp   fp=x29, offset=0
   // If you're just going through the motions with a fixed-size stack frame,