From mattst88 at gmail.com Wed Sep 2 15:17:20 2026 From: mattst88 at gmail.com (Matt Turner) Date: Wed, 2 Sep 2026 09:17:20 -0400 Subject: [PATCH] mpi: Drop casts from inline asm output operands. Message-ID: <20260902131720.409681-1-mattst88@gmail.com> * mpi/longlong.h [__a29k__, __alpha, __gmicro__, __hppa, __i960__, __mc68000__, __m88000__, __mips__, __mips, __ns32000__, __pyr__, __ibm032__, __sh2__, __sparc__, __vax__, __z8000__]: Drop the casts on asm output operands. -- Using a cast as an lvalue is a GCC extension that clang does not implement. Clang rejects it with -Winvalid-gnu-asm-cast, which is an error by default, so these blocks fail to build with clang. The casts do nothing. GCC accepts a cast in an asm output only when it is a no-op, and rejects it with "lvalue required in 'asm' statement" otherwise, so any code that compiles today already passes an operand of the right type. GMP's longlong.h dropped these long ago. The Z8000 block is the exception. There W_TYPE_SIZE is 16, so the cast to unsigned int is not a no-op and GCC would reject it too; that block has been dead for a long time and is fixed here for consistency. Casts on *input* operands are left alone: those are ordinary rvalue conversions, and on x86 count_leading_zeros/count_trailing_zeros the "rm" ((USItype)(x)) cast is what selects the operand width. Checked with the cross toolchains available here. GCC generates identical assembly before and after for alpha, hppa, mc68000, sh4, 32-bit sparc and mips. Clang builds the sparc block only after this change; it has no back end for alpha, hppa or mc68000, so those could not be checked with clang. The blocks with no compiler to test against (a29k, gmicro, i960, m88k, ns32000, pyr, RT/ROMP, vax, z8000) are changed mechanically. The MIPS asm blocks are unreachable in practice: any compiler new enough to matter takes the preceding __GNUC__ >= 5 branch, which uses a plain wide multiply, and the asm variants no longer assemble anyway now that GCC has removed the "h" constraint ("impossible constraint in 'asm'"). Signed-off-by: Matt Turner --- mpi/longlong.h | 174 ++++++++++++++++++++++++------------------------- 1 file changed, 87 insertions(+), 87 deletions(-) diff --git ./mpi/longlong.h ./mpi/longlong.h index 453f2704..b27d0b88 100644 --- ./mpi/longlong.h +++ ./mpi/longlong.h @@ -133,8 +133,8 @@ SPDX-License-Identifier: LGPL-2.1-or-later # define add_ssaaaa(sh, sl, ah, al, bh, bl) \ __asm__ ("add %1,%4,%5\n" \ "addc %0,%2,%3" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "%r" ((USItype)(ah)), \ "rI" ((USItype)(bh)), \ "%r" ((USItype)(al)), \ @@ -142,8 +142,8 @@ SPDX-License-Identifier: LGPL-2.1-or-later # define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("sub %1,%4,%5\n" \ "subc %0,%2,%3" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "r" ((USItype)(ah)), \ "rI" ((USItype)(bh)), \ "r" ((USItype)(al)), \ @@ -152,24 +152,24 @@ SPDX-License-Identifier: LGPL-2.1-or-later do { \ USItype __m0 = (m0), __m1 = (m1); \ __asm__ ("multiplu %0,%1,%2" \ - : "=r" ((USItype)(xl)) \ + : "=r" (xl) \ : "r" (__m0), \ "r" (__m1)); \ __asm__ ("multmu %0,%1,%2" \ - : "=r" ((USItype)(xh)) \ + : "=r" (xh) \ : "r" (__m0), \ "r" (__m1)); \ } while (0) # define udiv_qrnnd(q, r, n1, n0, d) \ __asm__ ("dividu %0,%3,%4" \ - : "=r" ((USItype)(q)), \ - "=q" ((USItype)(r)) \ + : "=r" (q), \ + "=q" (r) \ : "1" ((USItype)(n1)), \ "r" ((USItype)(n0)), \ "r" ((USItype)(d))) # define count_leading_zeros(count, x) \ __asm__ ("clz %0,%1" \ - : "=r" ((USItype)(count)) \ + : "=r" (count) \ : "r" ((USItype)(x))) # define COUNT_LEADING_ZEROS_0 32 #endif /* __a29k__ */ @@ -180,7 +180,7 @@ SPDX-License-Identifier: LGPL-2.1-or-later do { \ UDItype __m0 = (m0), __m1 = (m1); \ __asm__ ("umulh %r1,%2,%0" \ - : "=r" ((UDItype)(ph)) \ + : "=r" (ph) \ : "%rJ" (__m0), \ "rI" (__m1)); \ (pl) = __m0 * __m1; \ @@ -365,8 +365,8 @@ extern UDItype __udiv_qrnnd (UDItype *, UDItype, UDItype, UDItype); # define add_ssaaaa(sh, sl, ah, al, bh, bl) \ __asm__ ("add.w %5,%1\n" \ "addx %3,%0" \ - : "=g" ((USItype)(sh)), \ - "=&g" ((USItype)(sl)) \ + : "=g" (sh), \ + "=&g" (sl) \ : "%0" ((USItype)(ah)), \ "g" ((USItype)(bh)), \ "%1" ((USItype)(al)), \ @@ -374,22 +374,22 @@ extern UDItype __udiv_qrnnd (UDItype *, UDItype, UDItype, UDItype); # define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("sub.w %5,%1\n" \ "subx %3,%0" \ - : "=g" ((USItype)(sh)), \ - "=&g" ((USItype)(sl)) \ + : "=g" (sh), \ + "=&g" (sl) \ : "0" ((USItype)(ah)), \ "g" ((USItype)(bh)), \ "1" ((USItype)(al)), \ "g" ((USItype)(bl))) # define umul_ppmm(ph, pl, m0, m1) \ __asm__ ("mulx %3,%0,%1" \ - : "=g" ((USItype)(ph)), \ - "=r" ((USItype)(pl)) \ + : "=g" (ph), \ + "=r" (pl) \ : "%0" ((USItype)(m0)), \ "g" ((USItype)(m1))) # define udiv_qrnnd(q, r, nh, nl, d) \ __asm__ ("divx %4,%0,%1" \ - : "=g" ((USItype)(q)), \ - "=r" ((USItype)(r)) \ + : "=g" (q), \ + "=r" (r) \ : "1" ((USItype)(nh)), \ "0" ((USItype)(nl)), \ "g" ((USItype)(d))) @@ -408,8 +408,8 @@ extern UDItype __udiv_qrnnd (UDItype *, UDItype, UDItype, UDItype); # define add_ssaaaa(sh, sl, ah, al, bh, bl) \ __asm__ ("add %4,%5,%1\n\t" \ "addc %2,%3,%0" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "%rM" ((USItype)(ah)), \ "rM" ((USItype)(bh)), \ "%rM" ((USItype)(al)), \ @@ -417,8 +417,8 @@ extern UDItype __udiv_qrnnd (UDItype *, UDItype, UDItype, UDItype); # define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("sub %4,%5,%1\n\t" \ "subb %2,%3,%0" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "rM" ((USItype)(ah)), \ "rM" ((USItype)(bh)), \ "rM" ((USItype)(al)), \ @@ -658,8 +658,8 @@ extern USItype __udiv_qrnnd (USItype *, USItype, USItype, USItype); __asm__ ("cmpo 1,0\n" \ "addc %5,%4,%1\n" \ "addc %3,%2,%0" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "%dI" ((USItype)(ah)), \ "dI" ((USItype)(bh)), \ "%dI" ((USItype)(al)), \ @@ -668,8 +668,8 @@ extern USItype __udiv_qrnnd (USItype *, USItype, USItype, USItype); __asm__ ("cmpo 0,0\n" \ "subc %5,%4,%1\n" \ "subc %3,%2,%0" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "dI" ((USItype)(ah)), \ "dI" ((USItype)(bh)), \ "dI" ((USItype)(al)), \ @@ -733,8 +733,8 @@ extern USItype __udiv_qrnnd (USItype *, USItype, USItype, USItype); # define add_ssaaaa(sh, sl, ah, al, bh, bl) \ __asm__ ("add%.l %5,%1\n" \ "addx%.l %3,%0" \ - : "=d" ((USItype)(sh)), \ - "=&d" ((USItype)(sl)) \ + : "=d" (sh), \ + "=&d" (sl) \ : "%0" ((USItype)(ah)), \ "d" ((USItype)(bh)), \ "%1" ((USItype)(al)), \ @@ -742,8 +742,8 @@ extern USItype __udiv_qrnnd (USItype *, USItype, USItype, USItype); # define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("sub%.l %5,%1\n" \ "subx%.l %3,%0" \ - : "=d" ((USItype)(sh)), \ - "=&d" ((USItype)(sl)) \ + : "=d" (sh), \ + "=&d" (sl) \ : "0" ((USItype)(ah)), \ "d" ((USItype)(bh)), \ "1" ((USItype)(al)), \ @@ -751,29 +751,29 @@ extern USItype __udiv_qrnnd (USItype *, USItype, USItype, USItype); # if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) # define umul_ppmm(w1, w0, u, v) \ __asm__ ("mulu%.l %3,%1:%0" \ - : "=d" ((USItype)(w0)), \ - "=d" ((USItype)(w1)) \ + : "=d" (w0), \ + "=d" (w1) \ : "%0" ((USItype)(u)), \ "dmi" ((USItype)(v))) # define UMUL_TIME 45 # define udiv_qrnnd(q, r, n1, n0, d) \ __asm__ ("divu%.l %4,%1:%0" \ - : "=d" ((USItype)(q)), \ - "=d" ((USItype)(r)) \ + : "=d" (q), \ + "=d" (r) \ : "0" ((USItype)(n0)), \ "1" ((USItype)(n1)), \ "dmi" ((USItype)(d))) # define UDIV_TIME 90 # define sdiv_qrnnd(q, r, n1, n0, d) \ __asm__ ("divs%.l %4,%1:%0" \ - : "=d" ((USItype)(q)), \ - "=d" ((USItype)(r)) \ + : "=d" (q), \ + "=d" (r) \ : "0" ((USItype)(n0)), \ "1" ((USItype)(n1)), \ "dmi" ((USItype)(d))) # define count_leading_zeros(count, x) \ __asm__ ("bfffo %1{%b2:%b2},%0" \ - : "=d" ((USItype)(count)) \ + : "=d" (count) \ : "od" ((USItype)(x)), "n" (0)) # define COUNT_LEADING_ZEROS_0 32 # else /* not mc68020 */ @@ -801,7 +801,7 @@ extern USItype __udiv_qrnnd (USItype *, USItype, USItype, USItype); " add%.l %3,%1 \n" \ " addx%.l %2,%0 \n" \ " | End inlined umul_ppmm" \ - : "=&d" ((USItype)(xh)), "=&d" ((USItype)(xl)), \ + : "=&d" (xh), "=&d" (xl), \ "=d" (__umul_tmp1), "=&d" (__umul_tmp2) \ : "%2" ((USItype)(a)), "d" ((USItype)(b))); \ } while (0) @@ -818,8 +818,8 @@ extern USItype __udiv_qrnnd (USItype *, USItype, USItype, USItype); # define add_ssaaaa(sh, sl, ah, al, bh, bl) \ __asm__ ("addu.co %1,%r4,%r5\n" \ "addu.ci %0,%r2,%r3" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "%rJ" ((USItype)(ah)), \ "rJ" ((USItype)(bh)), \ "%rJ" ((USItype)(al)), \ @@ -827,8 +827,8 @@ extern USItype __udiv_qrnnd (USItype *, USItype, USItype, USItype); # define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("subu.co %1,%r4,%r5\n" \ "subu.ci %0,%r2,%r3" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "rJ" ((USItype)(ah)), \ "rJ" ((USItype)(bh)), \ "rJ" ((USItype)(al)), \ @@ -884,8 +884,8 @@ extern USItype __udiv_qrnnd (USItype *, USItype, USItype, USItype); # elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7 # define umul_ppmm(w1, w0, u, v) \ __asm__ ("multu %2,%3" \ - : "=l" ((USItype)(w0)), \ - "=h" ((USItype)(w1)) \ + : "=l" (w0), \ + "=h" (w1) \ : "d" ((USItype)(u)), \ "d" ((USItype)(v))) # else @@ -893,8 +893,8 @@ extern USItype __udiv_qrnnd (USItype *, USItype, USItype, USItype); __asm__ ("multu %2,%3 \n" \ "mflo %0 \n" \ "mfhi %1" \ - : "=d" ((USItype)(w0)), \ - "=d" ((USItype)(w1)) \ + : "=d" (w0), \ + "=d" (w1) \ : "d" ((USItype)(u)), \ "d" ((USItype)(v))) # endif @@ -919,8 +919,8 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); # elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7 # define umul_ppmm(w1, w0, u, v) \ __asm__ ("dmultu %2,%3" \ - : "=l" ((UDItype)(w0)), \ - "=h" ((UDItype)(w1)) \ + : "=l" (w0), \ + "=h" (w1) \ : "d" ((UDItype)(u)), \ "d" ((UDItype)(v))) # else @@ -928,8 +928,8 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); __asm__ ("dmultu %2,%3 \n" \ "mflo %0 \n" \ "mfhi %1" \ - : "=d" ((UDItype)(w0)), \ - "=d" ((UDItype)(w1)) \ + : "=d" (w0), \ + "=d" (w1) \ : "d" ((UDItype)(u)), \ "d" ((UDItype)(v))) # endif @@ -971,7 +971,7 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); # define count_trailing_zeros(count,x) \ do { __asm__ ("ffsd %2,%0" \ - : "=r" ((USItype) (count)) \ + : "=r" (count) \ : "0" ((USItype) 0), \ "r" ((USItype) (x))); \ } while (0) @@ -1120,8 +1120,8 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); # define add_ssaaaa(sh, sl, ah, al, bh, bl) \ __asm__ ("addw %5,%1 \n" \ "addwc %3,%0" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "%0" ((USItype)(ah)), \ "g" ((USItype)(bh)), \ "%1" ((USItype)(al)), \ @@ -1129,8 +1129,8 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); # define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("subw %5,%1 \n" \ "subwb %3,%0" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "0" ((USItype)(ah)), \ "g" ((USItype)(bh)), \ "1" ((USItype)(al)), \ @@ -1156,8 +1156,8 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); # define add_ssaaaa(sh, sl, ah, al, bh, bl) \ __asm__ ("a %1,%5 \n" \ "ae %0,%3" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "%0" ((USItype)(ah)), \ "r" ((USItype)(bh)), \ "%1" ((USItype)(al)), \ @@ -1165,8 +1165,8 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); # define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("s %1,%5\n" \ "se %0,%3" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "0" ((USItype)(ah)), \ "r" ((USItype)(bh)), \ "1" ((USItype)(al)), \ @@ -1195,8 +1195,8 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); "m r2,%3 \n" \ "cas %0,r2,r0 \n" \ "mfs r10,%1" \ - : "=r" ((USItype)(ph)), \ - "=r" ((USItype)(pl)) \ + : "=r" (ph), \ + "=r" (pl) \ : "%r" (__m0), \ "r" (__m1) \ : "r2"); \ @@ -1209,12 +1209,12 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); do { \ if ((x) >= 0x10000) \ __asm__ ("clz %0,%1" \ - : "=r" ((USItype)(count)) \ + : "=r" (count) \ : "r" ((USItype)(x) >> 16)); \ else \ { \ __asm__ ("clz %0,%1" \ - : "=r" ((USItype)(count)) \ + : "=r" (count) \ : "r" ((USItype)(x))); \ (count) += 16; \ } \ @@ -1232,8 +1232,8 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); "dmulu.l %2,%3\n" \ "sts macl,%1\n" \ "sts mach,%0" \ - : "=r" ((USItype)(w1)), \ - "=r" ((USItype)(w0)) \ + : "=r" (w1), \ + "=r" (w0) \ : "r" ((USItype)(u)), \ "r" ((USItype)(v)) \ : "macl", "mach") @@ -1247,8 +1247,8 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); # define add_ssaaaa(sh, sl, ah, al, bh, bl) \ __asm__ ("addcc %r4,%5,%1\n" \ "addx %r2,%3,%0" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "%rJ" ((USItype)(ah)), \ "rI" ((USItype)(bh)), \ "%rJ" ((USItype)(al)), \ @@ -1257,8 +1257,8 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); # define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("subcc %r4,%5,%1\n" \ "subx %r2,%3,%0" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "rJ" ((USItype)(ah)), \ "rI" ((USItype)(bh)), \ "rJ" ((USItype)(al)), \ @@ -1271,8 +1271,8 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); but INTERPRETED AS UNSIGNED. */ # define umul_ppmm(w1, w0, u, v) \ __asm__ ("umul %2,%3,%1;rd %%y,%0" \ - : "=r" ((USItype)(w1)), \ - "=r" ((USItype)(w0)) \ + : "=r" (w1), \ + "=r" (w0) \ : "r" ((USItype)(u)), \ "r" ((USItype)(v))) # define UMUL_TIME 5 @@ -1281,7 +1281,7 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); do { \ USItype __q; \ __asm__ ("mov %1,%%y;nop;nop;nop;udiv %2,%3,%0" \ - : "=r" ((USItype)(__q)) \ + : "=r" (__q) \ : "r" ((USItype)(n1)), \ "r" ((USItype)(n0)), \ "r" ((USItype)(d))); \ @@ -1296,8 +1296,8 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); instructions scan (ffs from high bit) and divscc. */ # define umul_ppmm(w1, w0, u, v) \ __asm__ ("umul %2,%3,%1;rd %%y,%0" \ - : "=r" ((USItype)(w1)), \ - "=r" ((USItype)(w0)) \ + : "=r" (w1), \ + "=r" (w0) \ : "r" ((USItype)(u)), \ "r" ((USItype)(v))) # define UMUL_TIME 5 @@ -1341,8 +1341,8 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); " bl,a 1f \n" \ " add %1,%4,%1 \n" \ "1: ! End of inline udiv_qrnnd" \ - : "=r" ((USItype)(q)), \ - "=r" ((USItype)(r)) \ + : "=r" (q), \ + "=r" (r) \ : "r" ((USItype)(n1)), \ "r" ((USItype)(n0)), \ "rI" ((USItype)(d)) \ @@ -1350,7 +1350,7 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); # define UDIV_TIME 37 # define count_leading_zeros(count, x) \ __asm__ ("scan %1,0,%0" \ - : "=r" ((USItype)(x)) \ + : "=r" (x) \ : "r" ((USItype)(count))) /* Early sparclites return 63 for an argument of 0, but they warn that future implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0 @@ -1400,8 +1400,8 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); " mulscc %%g1,0,%%g1 \n" \ " add %%g1,%%g2,%0 \n" \ " rd %%y,%1" \ - : "=r" ((USItype)(w1)), \ - "=r" ((USItype)(w0)) \ + : "=r" (w1), \ + "=r" (w0) \ : "%rI" ((USItype)(u)), \ "r" ((USItype)(v)) \ : "%g1", "%g2" __AND_CLOBBER_CC) @@ -1428,8 +1428,8 @@ extern USItype __udiv_qrnnd (USItype *, USItype, USItype, USItype); # define add_ssaaaa(sh, sl, ah, al, bh, bl) \ __asm__ ("addl2 %5,%1\n" \ "adwc %3,%0" \ - : "=g" ((USItype)(sh)), \ - "=&g" ((USItype)(sl)) \ + : "=g" (sh), \ + "=&g" (sl) \ : "%0" ((USItype)(ah)), \ "g" ((USItype)(bh)), \ "%1" ((USItype)(al)), \ @@ -1437,8 +1437,8 @@ extern USItype __udiv_qrnnd (USItype *, USItype, USItype, USItype); # define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("subl2 %5,%1\n" \ "sbwc %3,%0" \ - : "=g" ((USItype)(sh)), \ - "=&g" ((USItype)(sl)) \ + : "=g" (sh), \ + "=&g" (sl) \ : "0" ((USItype)(ah)), \ "g" ((USItype)(bh)), \ "1" ((USItype)(al)), \ @@ -1476,16 +1476,16 @@ extern USItype __udiv_qrnnd (USItype *, USItype, USItype, USItype); #if defined (__z8000__) && W_TYPE_SIZE == 16 # define add_ssaaaa(sh, sl, ah, al, bh, bl) \ __asm__ ("add %H1,%H5\n\tadc %H0,%H3" \ - : "=r" ((unsigned int)(sh)), \ - "=&r" ((unsigned int)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "%0" ((unsigned int)(ah)), \ "r" ((unsigned int)(bh)), \ "%1" ((unsigned int)(al)), \ "rQR" ((unsigned int)(bl))) # define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("sub %H1,%H5\n\tsbc %H0,%H3" \ - : "=r" ((unsigned int)(sh)), \ - "=&r" ((unsigned int)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "0" ((unsigned int)(ah)), \ "r" ((unsigned int)(bh)), \ "1" ((unsigned int)(al)), \ -- 2.54.0 From gniibe at fsij.org Thu Sep 3 09:22:50 2026 From: gniibe at fsij.org (NIIBE Yutaka) Date: Thu, 03 Sep 2026 16:22:50 +0900 Subject: [PATCH] mpi: Drop casts from inline asm output operands. In-Reply-To: <20260902131720.409681-1-mattst88@gmail.com> References: <20260902131720.409681-1-mattst88@gmail.com> Message-ID: <87bjaekddh.fsf@haruna.fsij.org> Hello, Matt Turner wrote: > Using a cast as an lvalue is a GCC extension that clang does not > implement. Clang rejects it with -Winvalid-gnu-asm-cast, which is an > error by default, so these blocks fail to build with clang. Please find a workaround for Clang. IIUC, please use -Wno-invalid-gnu-asm-cast option. If really needed, we could consider adding the option for Clang in libgcrypt/configure.ac. For longlong.h, the upstream used to be GNU C library. It is GCC now (gcc/include/longlong.h). We don't want further differences of our own from upstream. -- From mattst88 at gmail.com Thu Sep 3 20:32:57 2026 From: mattst88 at gmail.com (Matt Turner) Date: Thu, 3 Sep 2026 14:32:57 -0400 Subject: [PATCH] mpi: Drop casts from inline asm output operands. In-Reply-To: <87bjaekddh.fsf@haruna.fsij.org> References: <20260902131720.409681-1-mattst88@gmail.com> <87bjaekddh.fsf@haruna.fsij.org> Message-ID: On Thu, Sep 3, 2026 at 3:22 AM NIIBE Yutaka wrote: > > Hello, > > Matt Turner wrote: > > Using a cast as an lvalue is a GCC extension that clang does not > > implement. Clang rejects it with -Winvalid-gnu-asm-cast, which is an > > error by default, so these blocks fail to build with clang. > > Please find a workaround for Clang. IIUC, please use > -Wno-invalid-gnu-asm-cast option. If really needed, we could consider > adding the option for Clang in libgcrypt/configure.ac. > > For longlong.h, the upstream used to be GNU C library. It is GCC now > (gcc/include/longlong.h). > > We don't want further differences of our own from upstream. Ah, thank you. I'll fix this in GCC first and then return to this. From jussi.kivilinna at iki.fi Tue Sep 8 13:46:41 2026 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 8 Sep 2026 14:46:41 +0300 Subject: [PATCH 5/6] tests/basic: deduplicate vector cluttering hwf detection In-Reply-To: <20260908114642.1031933-1-jussi.kivilinna@iki.fi> References: <20260908114642.1031933-1-jussi.kivilinna@iki.fi> Message-ID: <20260908114642.1031933-5-jussi.kivilinna@iki.fi> * tests/basic.c (clutter_vector_registers): Replace per-architecture hwflist parsing with table driven detection. -- Each architecture had own copy of hwflist parsing and init handling. Signed-off-by: Jussi Kivilinna --- tests/basic.c | 121 ++++++++++++++++++-------------------------------- 1 file changed, 42 insertions(+), 79 deletions(-) diff --git a/tests/basic.c b/tests/basic.c index 4c5f6038..405f9861 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -307,95 +307,58 @@ clutter_vector_registers(void) static unsigned char data[CLUTTER_VECTOR_REGISTER_COUNT][16]; static int data_init; #endif +#if defined(CLUTTER_VECTOR_REGISTER_AMD64) || \ + defined(CLUTTER_VECTOR_REGISTER_I386) + static int have_ymm; + static int have_zmm; +#endif + static int have_vectors; + static struct + { + const char *match; + int *out_have; + int required; + int have; + } hwfeatures[] = + { #if defined(CLUTTER_VECTOR_REGISTER_AARCH64) || \ defined(CLUTTER_VECTOR_REGISTER_NEON) - static int init; - static int have_neon; - - if (!init) - { - char *string; - - string = gcry_get_config (0, "hwflist"); - if (string) - { - have_neon = (strstr(string, "arm-neon:") != NULL); - xfree(string); - } - init = 1; - } - - if (!have_neon) - return; + { "arm-neon:", &have_vectors, 1, 0 }, #elif defined(CLUTTER_VECTOR_REGISTER_AMD64) || \ defined(CLUTTER_VECTOR_REGISTER_I386) - static int init; - static int have_sse2; - static int have_avx; - static int have_avx512; - - if (!init) - { - char *string; - - string = gcry_get_config (0, "hwflist"); - if (string) - { - int have_ssse3 = (strstr(string, "intel-ssse3:") != NULL); - have_sse2 = have_ssse3; /* XMM registers supported */ - have_avx = (strstr(string, "intel-avx:") != NULL); /* YMM */ - have_avx512 = (strstr(string, "intel-avx512:") != NULL); /* ZMM */ - xfree(string); - } - -#ifdef CLUTTER_VECTOR_REGISTER_AMD64 - have_sse2 = 1; -#endif - - init = 1; - } - - if (!have_sse2) - return; + { "intel-ssse3:", &have_vectors, 1, 0 }, + { "intel-avx:", &have_ymm, 0, 0 }, + { "intel-avx512:", &have_zmm, 0, 0 }, #elif defined(CLUTTER_VECTOR_REGISTER_RISCV) - static int init; - static int have_rvv; + { "riscv-v:", &have_vectors, 1, 0 }, +#elif defined(CLUTTER_VECTOR_REGISTER_PPC) + { "ppc-arch_2_07:", &have_vectors, 1, 0 }, +#endif + }; + static int hwf_init = ((int)DIM(hwfeatures) == 0); - if (!init) + if (!hwf_init) { - char *string; - - string = gcry_get_config (0, "hwflist"); - if (string) + char *hwflist = gcry_get_config (0, "hwflist"); + if (hwflist) { - have_rvv = (strstr(string, "riscv-v:") != NULL); - xfree(string); - } - init = 1; - } + int i; - if (!have_rvv) - return; -#elif defined(CLUTTER_VECTOR_REGISTER_PPC) - static int init; - static int have_ppc_vec; - - if (!init) - { - char *string; + for (i = 0; i < (int)DIM(hwfeatures); i++) + { + int have = (strstr(hwflist, hwfeatures[i].match) != NULL); + hwfeatures[i].have = have; + *hwfeatures[i].out_have |= have; + } - string = gcry_get_config (0, "hwflist"); - if (string) - { - have_ppc_vec = (strstr(string, "ppc-arch_2_07:") != NULL); - xfree(string); + xfree(hwflist); } - init = 1; + + hwf_init = 1; } - if (!have_ppc_vec) + if (!have_vectors) return; -#endif #ifdef CLUTTER_VECTOR_REGISTER_COUNT if (!data_init) @@ -409,7 +372,7 @@ clutter_vector_registers(void) if (0) { } # ifdef HAVE_GCC_INLINE_ASM_AVX512 - else if (have_avx512) + else if (have_zmm) asm volatile("vbroadcasti32x4 (0 * 16)(%[data]), %%zmm0\n" "vbroadcasti32x4 (1 * 16)(%[data]), %%zmm1\n" "vbroadcasti32x4 (2 * 16)(%[data]), %%zmm2\n" @@ -455,7 +418,7 @@ clutter_vector_registers(void) ); # endif # ifdef HAVE_GCC_INLINE_ASM_AVX - else if (have_avx) + else if (have_ymm) asm volatile("vbroadcastf128 (0 * 16)(%[data]), %%ymm0\n" "vbroadcastf128 (1 * 16)(%[data]), %%ymm1\n" "vbroadcastf128 (2 * 16)(%[data]), %%ymm2\n" @@ -506,7 +469,7 @@ clutter_vector_registers(void) if (0) { } # ifdef HAVE_GCC_INLINE_ASM_AVX512 - else if (have_avx512) + else if (have_zmm) asm volatile("vbroadcasti32x4 (0 * 16)(%[data]), %%zmm0\n" "vbroadcasti32x4 (1 * 16)(%[data]), %%zmm1\n" "vbroadcasti32x4 (2 * 16)(%[data]), %%zmm2\n" @@ -522,7 +485,7 @@ clutter_vector_registers(void) ); # endif # ifdef HAVE_GCC_INLINE_ASM_AVX - else if (have_avx) + else if (have_ymm) asm volatile("vbroadcastf128 (0 * 16)(%[data]), %%ymm0\n" "vbroadcastf128 (1 * 16)(%[data]), %%ymm1\n" "vbroadcastf128 (2 * 16)(%[data]), %%ymm2\n" -- 2.53.0 From jussi.kivilinna at iki.fi Tue Sep 8 13:46:38 2026 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 8 Sep 2026 14:46:38 +0300 Subject: [PATCH 2/6] tests/basic: clutter YMM and ZMM registers on i386 and AMD64 In-Reply-To: <20260908114642.1031933-1-jussi.kivilinna@iki.fi> References: <20260908114642.1031933-1-jussi.kivilinna@iki.fi> Message-ID: <20260908114642.1031933-2-jussi.kivilinna@iki.fi> * tests/basic.c (CLUTTER_VECTOR_REGISTER_COUNT) [CLUTTER_VECTOR_REGISTER_AMD64]: Increase to 32. (clutter_vector_registers): Make clutter data static and prepare it only once. [CLUTTER_VECTOR_REGISTER_AMD64, CLUTTER_VECTOR_REGISTER_I386]: Detect AVX and AVX512 from hwflist; add YMM and ZMM register cluttering. -- Cluttering only XMM registers left upper halfs of YMM and ZMM registers untouched, so bugs in AVX and AVX512 implementations could pass unnoticed. Signed-off-by: Jussi Kivilinna --- tests/basic.c | 209 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 167 insertions(+), 42 deletions(-) diff --git a/tests/basic.c b/tests/basic.c index 9ec1b596..00d6586d 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -246,7 +246,7 @@ progress_handler (void *cb_data, const char *what, int printchar, defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \ defined(__SSE2__) # define CLUTTER_VECTOR_REGISTER_AMD64 1 -# define CLUTTER_VECTOR_REGISTER_COUNT 16 +# define CLUTTER_VECTOR_REGISTER_COUNT 32 #elif defined(__i386__) && SIZEOF_UNSIGNED_LONG == 4 && __GNUC__ >= 4 && \ defined(HAVE_GCC_INLINE_ASM_SSSE3) && defined(__SSE2__) # define CLUTTER_VECTOR_REGISTER_I386 1 @@ -295,7 +295,8 @@ static inline ALWAYS_INLINE void clutter_vector_registers(void) { #ifdef CLUTTER_VECTOR_REGISTER_COUNT - unsigned char data[CLUTTER_VECTOR_REGISTER_COUNT][16]; + static unsigned char data[CLUTTER_VECTOR_REGISTER_COUNT][16]; + static int data_init; #if defined(CLUTTER_VECTOR_REGISTER_AARCH64) || \ defined(CLUTTER_VECTOR_REGISTER_NEON) static int init; @@ -316,9 +317,12 @@ clutter_vector_registers(void) if (!have_neon) return; -#elif defined(CLUTTER_VECTOR_REGISTER_I386) +#elif defined(CLUTTER_VECTOR_REGISTER_AMD64) || \ + defined(CLUTTER_VECTOR_REGISTER_I386) static int init; - static int have_ssse3; + static int have_sse2; + static int have_avx; + static int have_avx512; if (!init) { @@ -327,55 +331,176 @@ clutter_vector_registers(void) string = gcry_get_config (0, "hwflist"); if (string) { - have_ssse3 = (strstr(string, "intel-ssse3:") != NULL); + int have_ssse3 = (strstr(string, "intel-ssse3:") != NULL); + have_sse2 = have_ssse3; /* XMM registers supported */ + have_avx = (strstr(string, "intel-avx:") != NULL); /* YMM */ + have_avx512 = (strstr(string, "intel-avx512:") != NULL); /* ZMM */ xfree(string); } + +#ifdef CLUTTER_VECTOR_REGISTER_AMD64 + have_sse2 = 1; +#endif + init = 1; } - if (!have_ssse3) + if (!have_sse2) return; #endif - prepare_vector_data(data); + if (!data_init) + { + prepare_vector_data(data); + data_init = 1; + } #if defined(CLUTTER_VECTOR_REGISTER_AMD64) - asm volatile("movdqu (0 * 16)(%[data]), %%xmm0\n" - "movdqu (1 * 16)(%[data]), %%xmm1\n" - "movdqu (2 * 16)(%[data]), %%xmm2\n" - "movdqu (3 * 16)(%[data]), %%xmm3\n" - "movdqu (4 * 16)(%[data]), %%xmm4\n" - "movdqu (5 * 16)(%[data]), %%xmm5\n" - "movdqu (6 * 16)(%[data]), %%xmm6\n" - "movdqu (7 * 16)(%[data]), %%xmm7\n" - "movdqu (8 * 16)(%[data]), %%xmm8\n" - "movdqu (9 * 16)(%[data]), %%xmm9\n" - "movdqu (10 * 16)(%[data]), %%xmm10\n" - "movdqu (11 * 16)(%[data]), %%xmm11\n" - "movdqu (12 * 16)(%[data]), %%xmm12\n" - "movdqu (13 * 16)(%[data]), %%xmm13\n" - "movdqu (14 * 16)(%[data]), %%xmm14\n" - "movdqu (15 * 16)(%[data]), %%xmm15\n" - : - : [data] "r" (&data[0]) - : "memory", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", - "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", - "xmm13", "xmm14", "xmm15" - ); + if (0) + { } +# ifdef HAVE_GCC_INLINE_ASM_AVX512 + else if (have_avx512) + asm volatile("vbroadcasti32x4 (0 * 16)(%[data]), %%zmm0\n" + "vbroadcasti32x4 (1 * 16)(%[data]), %%zmm1\n" + "vbroadcasti32x4 (2 * 16)(%[data]), %%zmm2\n" + "vbroadcasti32x4 (3 * 16)(%[data]), %%zmm3\n" + "vbroadcasti32x4 (4 * 16)(%[data]), %%zmm4\n" + "vbroadcasti32x4 (5 * 16)(%[data]), %%zmm5\n" + "vbroadcasti32x4 (6 * 16)(%[data]), %%zmm6\n" + "vbroadcasti32x4 (7 * 16)(%[data]), %%zmm7\n" + "vbroadcasti32x4 (8 * 16)(%[data]), %%zmm8\n" + "vbroadcasti32x4 (9 * 16)(%[data]), %%zmm9\n" + "vbroadcasti32x4 (10 * 16)(%[data]), %%zmm10\n" + "vbroadcasti32x4 (11 * 16)(%[data]), %%zmm11\n" + "vbroadcasti32x4 (12 * 16)(%[data]), %%zmm12\n" + "vbroadcasti32x4 (13 * 16)(%[data]), %%zmm13\n" + "vbroadcasti32x4 (14 * 16)(%[data]), %%zmm14\n" + "vbroadcasti32x4 (15 * 16)(%[data]), %%zmm15\n" + "vbroadcasti32x4 (16 * 16)(%[data]), %%zmm16\n" + "vbroadcasti32x4 (17 * 16)(%[data]), %%zmm17\n" + "vbroadcasti32x4 (18 * 16)(%[data]), %%zmm18\n" + "vbroadcasti32x4 (19 * 16)(%[data]), %%zmm19\n" + "vbroadcasti32x4 (20 * 16)(%[data]), %%zmm20\n" + "vbroadcasti32x4 (21 * 16)(%[data]), %%zmm21\n" + "vbroadcasti32x4 (22 * 16)(%[data]), %%zmm22\n" + "vbroadcasti32x4 (23 * 16)(%[data]), %%zmm23\n" + "vbroadcasti32x4 (24 * 16)(%[data]), %%zmm24\n" + "vbroadcasti32x4 (25 * 16)(%[data]), %%zmm25\n" + "vbroadcasti32x4 (26 * 16)(%[data]), %%zmm26\n" + "vbroadcasti32x4 (27 * 16)(%[data]), %%zmm27\n" + "vbroadcasti32x4 (28 * 16)(%[data]), %%zmm28\n" + "vbroadcasti32x4 (29 * 16)(%[data]), %%zmm29\n" + "vbroadcasti32x4 (30 * 16)(%[data]), %%zmm30\n" + "vbroadcasti32x4 (31 * 16)(%[data]), %%zmm31\n" + : + : [data] "r" (&data[0]) + : "memory", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", + "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", + "xmm13", "xmm14", "xmm15" +# ifdef __AVX512F__ + , "xmm16", "xmm17", "xmm18", "xmm19", "xmm20", "xmm21", + "xmm22", "xmm23", "xmm24", "xmm25", "xmm26", "xmm27", + "xmm28", "xmm29", "xmm30", "xmm31" +# endif + ); +# endif +# ifdef HAVE_GCC_INLINE_ASM_AVX + else if (have_avx) + asm volatile("vbroadcastf128 (0 * 16)(%[data]), %%ymm0\n" + "vbroadcastf128 (1 * 16)(%[data]), %%ymm1\n" + "vbroadcastf128 (2 * 16)(%[data]), %%ymm2\n" + "vbroadcastf128 (3 * 16)(%[data]), %%ymm3\n" + "vbroadcastf128 (4 * 16)(%[data]), %%ymm4\n" + "vbroadcastf128 (5 * 16)(%[data]), %%ymm5\n" + "vbroadcastf128 (6 * 16)(%[data]), %%ymm6\n" + "vbroadcastf128 (7 * 16)(%[data]), %%ymm7\n" + "vbroadcastf128 (8 * 16)(%[data]), %%ymm8\n" + "vbroadcastf128 (9 * 16)(%[data]), %%ymm9\n" + "vbroadcastf128 (10 * 16)(%[data]), %%ymm10\n" + "vbroadcastf128 (11 * 16)(%[data]), %%ymm11\n" + "vbroadcastf128 (12 * 16)(%[data]), %%ymm12\n" + "vbroadcastf128 (13 * 16)(%[data]), %%ymm13\n" + "vbroadcastf128 (14 * 16)(%[data]), %%ymm14\n" + "vbroadcastf128 (15 * 16)(%[data]), %%ymm15\n" + : + : [data] "r" (&data[0]) + : "memory", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", + "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", + "xmm13", "xmm14", "xmm15" + ); +# endif + else + asm volatile("movdqu (0 * 16)(%[data]), %%xmm0\n" + "movdqu (1 * 16)(%[data]), %%xmm1\n" + "movdqu (2 * 16)(%[data]), %%xmm2\n" + "movdqu (3 * 16)(%[data]), %%xmm3\n" + "movdqu (4 * 16)(%[data]), %%xmm4\n" + "movdqu (5 * 16)(%[data]), %%xmm5\n" + "movdqu (6 * 16)(%[data]), %%xmm6\n" + "movdqu (7 * 16)(%[data]), %%xmm7\n" + "movdqu (8 * 16)(%[data]), %%xmm8\n" + "movdqu (9 * 16)(%[data]), %%xmm9\n" + "movdqu (10 * 16)(%[data]), %%xmm10\n" + "movdqu (11 * 16)(%[data]), %%xmm11\n" + "movdqu (12 * 16)(%[data]), %%xmm12\n" + "movdqu (13 * 16)(%[data]), %%xmm13\n" + "movdqu (14 * 16)(%[data]), %%xmm14\n" + "movdqu (15 * 16)(%[data]), %%xmm15\n" + : + : [data] "r" (&data[0]) + : "memory", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", + "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", + "xmm13", "xmm14", "xmm15" + ); #elif defined(CLUTTER_VECTOR_REGISTER_I386) - asm volatile("movdqu (0 * 16)(%[data]), %%xmm0\n" - "movdqu (1 * 16)(%[data]), %%xmm1\n" - "movdqu (2 * 16)(%[data]), %%xmm2\n" - "movdqu (3 * 16)(%[data]), %%xmm3\n" - "movdqu (4 * 16)(%[data]), %%xmm4\n" - "movdqu (5 * 16)(%[data]), %%xmm5\n" - "movdqu (6 * 16)(%[data]), %%xmm6\n" - "movdqu (7 * 16)(%[data]), %%xmm7\n" - : - : [data] "r" (&data[0]) - : "memory", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", - "xmm6", "xmm7" - ); + if (0) + { } +# ifdef HAVE_GCC_INLINE_ASM_AVX512 + else if (have_avx512) + asm volatile("vbroadcasti32x4 (0 * 16)(%[data]), %%zmm0\n" + "vbroadcasti32x4 (1 * 16)(%[data]), %%zmm1\n" + "vbroadcasti32x4 (2 * 16)(%[data]), %%zmm2\n" + "vbroadcasti32x4 (3 * 16)(%[data]), %%zmm3\n" + "vbroadcasti32x4 (4 * 16)(%[data]), %%zmm4\n" + "vbroadcasti32x4 (5 * 16)(%[data]), %%zmm5\n" + "vbroadcasti32x4 (6 * 16)(%[data]), %%zmm6\n" + "vbroadcasti32x4 (7 * 16)(%[data]), %%zmm7\n" + : + : [data] "r" (&data[0]) + : "memory", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", + "xmm6", "xmm7" + ); +# endif +# ifdef HAVE_GCC_INLINE_ASM_AVX + else if (have_avx) + asm volatile("vbroadcastf128 (0 * 16)(%[data]), %%ymm0\n" + "vbroadcastf128 (1 * 16)(%[data]), %%ymm1\n" + "vbroadcastf128 (2 * 16)(%[data]), %%ymm2\n" + "vbroadcastf128 (3 * 16)(%[data]), %%ymm3\n" + "vbroadcastf128 (4 * 16)(%[data]), %%ymm4\n" + "vbroadcastf128 (5 * 16)(%[data]), %%ymm5\n" + "vbroadcastf128 (6 * 16)(%[data]), %%ymm6\n" + "vbroadcastf128 (7 * 16)(%[data]), %%ymm7\n" + : + : [data] "r" (&data[0]) + : "memory", "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", + "ymm6", "ymm7" + ); +# endif + else + asm volatile("movdqu (0 * 16)(%[data]), %%xmm0\n" + "movdqu (1 * 16)(%[data]), %%xmm1\n" + "movdqu (2 * 16)(%[data]), %%xmm2\n" + "movdqu (3 * 16)(%[data]), %%xmm3\n" + "movdqu (4 * 16)(%[data]), %%xmm4\n" + "movdqu (5 * 16)(%[data]), %%xmm5\n" + "movdqu (6 * 16)(%[data]), %%xmm6\n" + "movdqu (7 * 16)(%[data]), %%xmm7\n" + : + : [data] "r" (&data[0]) + : "memory", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", + "xmm6", "xmm7" + ); #elif defined(CLUTTER_VECTOR_REGISTER_AARCH64) asm volatile("mov x0, %[ptr]\n" "ld1 {v0.16b}, [x0], #16\n" -- 2.53.0 From jussi.kivilinna at iki.fi Tue Sep 8 13:46:39 2026 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 8 Sep 2026 14:46:39 +0300 Subject: [PATCH 3/6] tests/basic: add vector cluttering for riscv In-Reply-To: <20260908114642.1031933-1-jussi.kivilinna@iki.fi> References: <20260908114642.1031933-1-jussi.kivilinna@iki.fi> Message-ID: <20260908114642.1031933-3-jussi.kivilinna@iki.fi> * tests/basic.c (CLUTTER_VECTOR_REGISTER_RISCV): New. (clutter_vector_registers): Guard clutter data with CLUTTER_VECTOR_REGISTER_COUNT. [CLUTTER_VECTOR_REGISTER_RISCV]: Detect RVV from hwflist; fill v0-v31 with vid.v generated values. -- Vector register width is not known at compile time on RISC-V, so registers are filled with generated values instead of loading from data buffer. Signed-off-by: Jussi Kivilinna --- tests/basic.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/tests/basic.c b/tests/basic.c index 00d6586d..d9664d3c 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -261,6 +261,10 @@ progress_handler (void *cb_data, const char *what, int printchar, defined(__ARM_NEON) # define CLUTTER_VECTOR_REGISTER_NEON 1 # define CLUTTER_VECTOR_REGISTER_COUNT 16 +#elif defined(HAVE_GCC_INLINE_ASM_RISCV_V) && \ + defined(__riscv) +# define CLUTTER_VECTOR_REGISTER_RISCV 1 +# undef CLUTTER_VECTOR_REGISTER_COUNT #endif @@ -297,6 +301,7 @@ clutter_vector_registers(void) #ifdef CLUTTER_VECTOR_REGISTER_COUNT static unsigned char data[CLUTTER_VECTOR_REGISTER_COUNT][16]; static int data_init; +#endif #if defined(CLUTTER_VECTOR_REGISTER_AARCH64) || \ defined(CLUTTER_VECTOR_REGISTER_NEON) static int init; @@ -347,13 +352,34 @@ clutter_vector_registers(void) if (!have_sse2) return; +#elif defined(CLUTTER_VECTOR_REGISTER_RISCV) + static int init; + static int have_rvv; + + if (!init) + { + char *string; + + string = gcry_get_config (0, "hwflist"); + if (string) + { + have_rvv = (strstr(string, "riscv-v:") != NULL); + xfree(string); + } + init = 1; + } + + if (!have_rvv) + return; #endif +#ifdef CLUTTER_VECTOR_REGISTER_COUNT if (!data_init) { prepare_vector_data(data); data_init = 1; } +#endif #if defined(CLUTTER_VECTOR_REGISTER_AMD64) if (0) @@ -565,9 +591,44 @@ clutter_vector_registers(void) : "r0", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15", "memory"); +#elif defined(CLUTTER_VECTOR_REGISTER_RISCV) + asm volatile(".option push;\n" + ".option arch, +v;\n" + "vsetvli t0, %0, e8, m4, ta, ma;\n" + "vid.v v0;\n" + "vid.v v4;\n" + "vid.v v8;\n" + "vid.v v12;\n" + "vid.v v16;\n" + "vid.v v20;\n" + "vid.v v24;\n" + "vid.v v28;\n" + "vadd.vx v4, v4, t0;\n" + "add t1, t0, t0;\n" + "vadd.vx v8, v8, t1;\n" + "add t1, t1, t0;\n" + "vadd.vx v12, v12, t1;\n" + "add t1, t1, t0;\n" + "vadd.vx v16, v16, t1;\n" + "add t1, t1, t0;\n" + "vadd.vx v20, v20, t1;\n" + "add t1, t1, t0;\n" + "add t0, t1, t0;\n" + "vadd.vx v24, v24, t1;\n" + "vadd.vx v28, v28, t0;\n" + ".option pop;\n" + : + : "r" (~0) + : "memory", "vl", "vtype", "t0", "t1", + "v0", "v1", "v2", "v3", + "v4", "v5", "v6", "v7", + "v8", "v9", "v10", "v11", + "v12", "v13", "v14", "v15", + "v16", "v17", "v18", "v19", + "v20", "v21", "v22", "v23", + "v24", "v25", "v26", "v27", + "v28", "v29", "v30", "v31"); #endif - -#endif /* CLUTTER_VECTOR_REGISTER_COUNT */ } -- 2.53.0 From jussi.kivilinna at iki.fi Tue Sep 8 13:46:40 2026 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 8 Sep 2026 14:46:40 +0300 Subject: [PATCH 4/6] tests/basic: add vector cluttering for ppc64 In-Reply-To: <20260908114642.1031933-1-jussi.kivilinna@iki.fi> References: <20260908114642.1031933-1-jussi.kivilinna@iki.fi> Message-ID: <20260908114642.1031933-4-jussi.kivilinna@iki.fi> * tests/basic.c (CLUTTER_VECTOR_REGISTER_PPC): New. (clutter_vector_registers) [CLUTTER_VECTOR_REGISTER_PPC]: Detect ppc-arch_2_07 from hwflist; load all 64 VSX registers. -- Signed-off-by: Jussi Kivilinna --- tests/basic.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/tests/basic.c b/tests/basic.c index d9664d3c..4c5f6038 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -265,6 +265,11 @@ progress_handler (void *cb_data, const char *what, int printchar, defined(__riscv) # define CLUTTER_VECTOR_REGISTER_RISCV 1 # undef CLUTTER_VECTOR_REGISTER_COUNT +#elif defined(HAVE_COMPATIBLE_CC_PPC_ALTIVEC) && \ + defined(HAVE_GCC_INLINE_ASM_PPC_ALTIVEC) && \ + defined(__POWER8_VECTOR__) +# define CLUTTER_VECTOR_REGISTER_PPC 1 +# define CLUTTER_VECTOR_REGISTER_COUNT 64 #endif @@ -371,6 +376,25 @@ clutter_vector_registers(void) if (!have_rvv) return; +#elif defined(CLUTTER_VECTOR_REGISTER_PPC) + static int init; + static int have_ppc_vec; + + if (!init) + { + char *string; + + string = gcry_get_config (0, "hwflist"); + if (string) + { + have_ppc_vec = (strstr(string, "ppc-arch_2_07:") != NULL); + xfree(string); + } + init = 1; + } + + if (!have_ppc_vec) + return; #endif #ifdef CLUTTER_VECTOR_REGISTER_COUNT @@ -628,6 +652,46 @@ clutter_vector_registers(void) "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"); +#elif defined(CLUTTER_VECTOR_REGISTER_PPC) + #define FILL_VECS_10(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) \ + asm volatile("lxvd2x "#v0", %y0\n" \ + "lxvd2x "#v1", %y1\n" \ + "lxvd2x "#v2", %y2\n" \ + "lxvd2x "#v3", %y3\n" \ + "lxvd2x "#v4", %y4\n" \ + "lxvd2x "#v5", %y5\n" \ + "lxvd2x "#v6", %y6\n" \ + "lxvd2x "#v7", %y7\n" \ + "lxvd2x "#v8", %y8\n" \ + "lxvd2x "#v9", %y9\n" \ + : \ + : "Z" (data[v0][0]), "Z" (data[v1][0]), \ + "Z" (data[v2][0]), "Z" (data[v3][0]), \ + "Z" (data[v4][0]), "Z" (data[v5][0]), \ + "Z" (data[v6][0]), "Z" (data[v7][0]), \ + "Z" (data[v8][0]), "Z" (data[v9][0]) \ + : "vs" #v0, "vs" #v1, "vs" #v2, "vs" #v3, \ + "vs" #v4, "vs" #v5, "vs" #v6, "vs" #v7, \ + "vs" #v8, "vs" #v9, "memory"); + #define FILL_VECS_4(v0, v1, v2, v3) \ + asm volatile("lxvd2x "#v0", %y0\n" \ + "lxvd2x "#v1", %y1\n" \ + "lxvd2x "#v2", %y2\n" \ + "lxvd2x "#v3", %y3\n" \ + : \ + : "Z" (data[v0][0]), "Z" (data[v1][0]), \ + "Z" (data[v2][0]), "Z" (data[v3][0]) \ + : "vs" #v0, "vs" #v1, "vs" #v2, "vs" #v3, \ + "memory"); + FILL_VECS_10(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); + FILL_VECS_10(10, 11, 12, 13, 14, 15, 16, 17, 18, 19); + FILL_VECS_10(20, 21, 22, 23, 24, 25, 26, 27, 28, 29); + FILL_VECS_10(30, 31, 32, 33, 34, 35, 36, 37, 38, 39); + FILL_VECS_10(40, 41, 42, 43, 44, 45, 46, 47, 48, 49); + FILL_VECS_10(50, 51, 52, 53, 54, 55, 56, 57, 58, 59); + FILL_VECS_4(60, 61, 62, 63); + #undef FILL_VECS_10 + #undef FILL_VECS_4 #endif } -- 2.53.0 From jussi.kivilinna at iki.fi Tue Sep 8 13:46:42 2026 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 8 Sep 2026 14:46:42 +0300 Subject: [PATCH 6/6] tests/basic: add MAC verify API test for bad tag length In-Reply-To: <20260908114642.1031933-1-jussi.kivilinna@iki.fi> References: <20260908114642.1031933-1-jussi.kivilinna@iki.fi> Message-ID: <20260908114642.1031933-6-jussi.kivilinna@iki.fi> * cipher/cipher-cmac.c (cmac_tag): Return GPG_ERR_INV_LENGTH for invalid tag length. * cipher/cipher-gcm.c (_gcry_cipher_gcm_tag): Likewise. * tests/basic.c (check_one_mac): Check that gcry_mac_verify rejects oversized tag length. -- CMAC returned GPG_ERR_INV_ARG and GCM returned GPG_ERR_CHECKSUM for wrong tag length, while HMAC and Poly1305 return GPG_ERR_INV_LENGTH. Signed-off-by: Jussi Kivilinna --- cipher/cipher-cmac.c | 4 +++- cipher/cipher-gcm.c | 5 +++-- tests/basic.c | 9 +++++++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/cipher/cipher-cmac.c b/cipher/cipher-cmac.c index c8bedc08..aab4b042 100644 --- a/cipher/cipher-cmac.c +++ b/cipher/cipher-cmac.c @@ -216,8 +216,10 @@ cmac_tag (gcry_cipher_hd_t c, gcry_cmac_context_t *ctx, { gcry_err_code_t ret; - if (!tag || taglen == 0 || taglen > c->spec->blocksize) + if (!tag) return GPG_ERR_INV_ARG; + if (taglen == 0 || taglen > c->spec->blocksize) + return GPG_ERR_INV_LENGTH; if (!ctx->tag) { diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c index e6a4df0f..ed04951b 100644 --- a/cipher/cipher-gcm.c +++ b/cipher/cipher-gcm.c @@ -1283,8 +1283,9 @@ _gcry_cipher_gcm_tag (gcry_cipher_hd_t c, { /* OUTBUFLEN gives the length of the user supplied tag in OUTBUF * and thus we need to compare its length first. */ - if (!is_tag_length_valid (outbuflen) - || !buf_eq_const (outbuf, c->u_mode.gcm.u_tag.tag, outbuflen)) + if (!is_tag_length_valid (outbuflen)) + return GPG_ERR_INV_LENGTH; + if (!buf_eq_const (outbuf, c->u_mode.gcm.u_tag.tag, outbuflen)) return GPG_ERR_CHECKSUM; } diff --git a/tests/basic.c b/tests/basic.c index 405f9861..7b8c73f3 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -16405,6 +16405,7 @@ check_one_mac (int algo, const char *data, int datalen, const char *key, int keylen, const char *iv, int ivlen, const char *expect, int test_buffering) { + unsigned char big_bad_tag[64 * 2]; gcry_mac_hd_t hd; unsigned char *p; unsigned int maclen; @@ -16558,6 +16559,14 @@ check_one_mac (int algo, const char *data, int datalen, if (err) fail("algo %d, mac gcry_mac_verify failed: %s\n", algo, gpg_strerror (err)); + clutter_vector_registers(); + err = gcry_mac_verify (hd, big_bad_tag, sizeof(big_bad_tag)); + if (gcry_err_code (err) != GPG_ERR_INV_LENGTH) + fail ("algo %d, gcry_mac_verify: oversized len %d not rejected: %s\n", algo, + (int)sizeof(big_bad_tag), gpg_strerror (err)); + if (err) + goto out; + macoutlen = maclen; clutter_vector_registers(); err = gcry_mac_read (hd, p, &macoutlen); -- 2.53.0 From jussi.kivilinna at iki.fi Tue Sep 8 13:46:37 2026 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 8 Sep 2026 14:46:37 +0300 Subject: [PATCH 1/6] cipher: remove unneeded vzeroupper from AVX implementations Message-ID: <20260908114642.1031933-1-jussi.kivilinna@iki.fi> * cipher/blake2b-amd64-avx2.S (_gcry_blake2b_transform_amd64_avx2): Remove vzeroupper from function entry. * cipher/blake2s-amd64-avx.S (_gcry_blake2s_transform_amd64_avx): Likewise. * cipher/camellia-aesni-avx-amd64.S (_gcry_camellia_aesni_avx_ctr_enc) (_gcry_camellia_aesni_avx_ecb_enc, _gcry_camellia_aesni_avx_ecb_dec) (_gcry_camellia_aesni_avx_cbc_dec, _gcry_camellia_aesni_avx_cfb_dec) (_gcry_camellia_aesni_avx_ocb_enc, _gcry_camellia_aesni_avx_ocb_dec) (_gcry_camellia_aesni_avx_ocb_auth, _gcry_camellia_aesni_avx_keygen): Likewise. * cipher/chacha20-amd64-avx2.S (_gcry_chacha20_amd64_avx2_blocks8) (_gcry_chacha20_poly1305_amd64_avx2_blocks8): Likewise. * cipher/serpent-avx2-amd64.S (_gcry_serpent_avx2_ctr_enc) (_gcry_serpent_avx2_cbc_dec, _gcry_serpent_avx2_cfb_dec) (_gcry_serpent_avx2_ocb_enc, _gcry_serpent_avx2_ocb_dec) (_gcry_serpent_avx2_ocb_auth): Likewise. * cipher/sha1-avx-amd64.S (_gcry_sha1_transform_amd64_avx): Likewise. * cipher/sha1-avx-bmi2-amd64.S (_gcry_sha1_transform_amd64_avx_bmi2): Likewise. * cipher/sha1-avx2-bmi2-amd64.S (_gcry_sha1_transform_amd64_avx2_bmi2): Likewise. * cipher/sha256-avx-amd64.S (_gcry_sha256_transform_amd64_avx): Likewise. * cipher/sha256-avx2-bmi2-amd64.S (_gcry_sha256_transform_amd64_avx2): Likewise. * cipher/sha512-avx-amd64.S (_gcry_sha512_transform_amd64_avx): Likewise. * cipher/sha512-avx2-bmi2-amd64.S (_gcry_sha512_transform_amd64_avx2): Likewise. * cipher/sm3-avx-bmi2-amd64.S (_gcry_sm3_transform_amd64_avx_bmi2): Likewise. * cipher/twofish-avx2-amd64.S (_gcry_twofish_avx2_blk16) (_gcry_twofish_avx2_ctr_enc, _gcry_twofish_avx2_cbc_dec) (_gcry_twofish_avx2_cfb_dec, _gcry_twofish_avx2_ocb_enc) (_gcry_twofish_avx2_ocb_dec, _gcry_twofish_avx2_ocb_auth): Likewise. * cipher/chacha20-amd64-avx512.S (_gcry_chacha20_amd64_avx512_blocks): Remove vzeroupper from register clearing. -- vzeroupper is needed only ahead of legacy SSE code, to avoid AVX-SSE transition penalty. These implementations use VEX/EVEX encoding throughout and clear upper register state with vzeroall before return. Measured on Tiger Lake, leaving upper register state dirty costs 1.54x for legacy SSE loop, but nothing for VEX encoded xmm/ymm code. Zen5 shows no penalty for either. Signed-off-by: Jussi Kivilinna --- cipher/blake2b-amd64-avx2.S | 2 -- cipher/blake2s-amd64-avx.S | 2 -- cipher/camellia-aesni-avx-amd64.S | 18 ------------------ cipher/chacha20-amd64-avx2.S | 4 ---- cipher/chacha20-amd64-avx512.S | 1 - cipher/serpent-avx2-amd64.S | 12 ------------ cipher/sha1-avx-amd64.S | 2 -- cipher/sha1-avx-bmi2-amd64.S | 2 -- cipher/sha1-avx2-bmi2-amd64.S | 2 -- cipher/sha256-avx-amd64.S | 1 - cipher/sha256-avx2-bmi2-amd64.S | 2 -- cipher/sha512-avx-amd64.S | 2 -- cipher/sha512-avx2-bmi2-amd64.S | 2 -- cipher/sm3-avx-bmi2-amd64.S | 2 -- cipher/twofish-avx2-amd64.S | 14 -------------- 15 files changed, 68 deletions(-) diff --git a/cipher/blake2b-amd64-avx2.S b/cipher/blake2b-amd64-avx2.S index 43c2cce1..02ee80a4 100644 --- a/cipher/blake2b-amd64-avx2.S +++ b/cipher/blake2b-amd64-avx2.S @@ -210,8 +210,6 @@ _gcry_blake2b_transform_amd64_avx2: */ CFI_STARTPROC(); - vzeroupper; - addq $128, (STATE_T + 0)(RSTATE); adcq $0, (STATE_T + 8)(RSTATE); diff --git a/cipher/blake2s-amd64-avx.S b/cipher/blake2s-amd64-avx.S index 44b82ab2..d2df67d6 100644 --- a/cipher/blake2s-amd64-avx.S +++ b/cipher/blake2s-amd64-avx.S @@ -196,8 +196,6 @@ _gcry_blake2s_transform_amd64_avx: */ CFI_STARTPROC(); - vzeroupper; - addq $64, (STATE_T + 0)(RSTATE); vmovdqa .Lshuf_ror16 rRIP, R16; diff --git a/cipher/camellia-aesni-avx-amd64.S b/cipher/camellia-aesni-avx-amd64.S index a29b9023..14e11d18 100644 --- a/cipher/camellia-aesni-avx-amd64.S +++ b/cipher/camellia-aesni-avx-amd64.S @@ -896,8 +896,6 @@ _gcry_camellia_aesni_avx_ctr_enc: movq %rsp, %rbp; CFI_DEF_CFA_REGISTER(%rbp); - vzeroupper; - cmpl $128, key_bitlength(CTX); movl $32, %r8d; movl $24, %eax; @@ -1053,8 +1051,6 @@ _gcry_camellia_aesni_avx_ecb_enc: movq %rsp, %rbp; CFI_DEF_CFA_REGISTER(%rbp); - vzeroupper; - cmpl $128, key_bitlength(CTX); movl $32, %r8d; movl $24, %eax; @@ -1099,8 +1095,6 @@ _gcry_camellia_aesni_avx_ecb_dec: movq %rsp, %rbp; CFI_DEF_CFA_REGISTER(%rbp); - vzeroupper; - cmpl $128, key_bitlength(CTX); movl $32, %r8d; movl $24, %eax; @@ -1146,8 +1140,6 @@ _gcry_camellia_aesni_avx_cbc_dec: movq %rsp, %rbp; CFI_DEF_CFA_REGISTER(%rbp); - vzeroupper; - movq %rcx, %r9; cmpl $128, key_bitlength(CTX); @@ -1219,8 +1211,6 @@ _gcry_camellia_aesni_avx_cfb_dec: movq %rsp, %rbp; CFI_DEF_CFA_REGISTER(%rbp); - vzeroupper; - cmpl $128, key_bitlength(CTX); movl $32, %r8d; movl $24, %eax; @@ -1303,8 +1293,6 @@ _gcry_camellia_aesni_avx_ocb_enc: movq %rsp, %rbp; CFI_DEF_CFA_REGISTER(%rbp); - vzeroupper; - subq $(16 * 16 + 4 * 8), %rsp; andq $~31, %rsp; movq %rsp, %rax; @@ -1455,8 +1443,6 @@ _gcry_camellia_aesni_avx_ocb_dec: movq %rsp, %rbp; CFI_DEF_CFA_REGISTER(%rbp); - vzeroupper; - subq $(16 * 16 + 4 * 8), %rsp; andq $~31, %rsp; movq %rsp, %rax; @@ -1625,8 +1611,6 @@ _gcry_camellia_aesni_avx_ocb_auth: movq %rsp, %rbp; CFI_DEF_CFA_REGISTER(%rbp); - vzeroupper; - subq $(16 * 16 + 4 * 8), %rsp; andq $~31, %rsp; movq %rsp, %rax; @@ -2720,8 +2704,6 @@ _gcry_camellia_aesni_avx_keygen: */ CFI_STARTPROC(); - vzeroupper; - vmovdqu (%rsi), %xmm0; cmpl $24, %edx; jb __camellia_avx_setup128; diff --git a/cipher/chacha20-amd64-avx2.S b/cipher/chacha20-amd64-avx2.S index 54e2ffab..b2311ab5 100644 --- a/cipher/chacha20-amd64-avx2.S +++ b/cipher/chacha20-amd64-avx2.S @@ -184,8 +184,6 @@ _gcry_chacha20_amd64_avx2_blocks8: */ CFI_STARTPROC(); - vzeroupper; - pushq %rbp; CFI_PUSH(%rbp); movq %rsp, %rbp; @@ -356,8 +354,6 @@ _gcry_chacha20_poly1305_amd64_avx2_blocks8: movq %rsp, %rbp; CFI_DEF_CFA_REGISTER(%rbp); - vzeroupper; - subq $(9 * 8) + STACK_MAX + 32, %rsp; andq $~31, %rsp; diff --git a/cipher/chacha20-amd64-avx512.S b/cipher/chacha20-amd64-avx512.S index 2d140815..6d421bf2 100644 --- a/cipher/chacha20-amd64-avx512.S +++ b/cipher/chacha20-amd64-avx512.S @@ -625,7 +625,6 @@ _gcry_chacha20_amd64_avx512_blocks: .Lskip4v: /* clear AVX512 registers */ kxorq %k2, %k2, %k2; - vzeroupper; clear_zmm16_zmm31(); .align 16 diff --git a/cipher/serpent-avx2-amd64.S b/cipher/serpent-avx2-amd64.S index a419eb29..9ec31f17 100644 --- a/cipher/serpent-avx2-amd64.S +++ b/cipher/serpent-avx2-amd64.S @@ -645,8 +645,6 @@ _gcry_serpent_avx2_ctr_enc: */ CFI_STARTPROC(); - vzeroupper; - vbroadcasti128 .Lbswap128_mask rRIP, RTMP3; vpcmpeqd RNOT, RNOT, RNOT; vpsrldq $14, RNOT, RNOT; /* ab: -1:0 ; cd: -1:0 */ @@ -718,8 +716,6 @@ _gcry_serpent_avx2_cbc_dec: */ CFI_STARTPROC(); - vzeroupper; - vmovdqu (0 * 32)(%rdx), RA0; vmovdqu (1 * 32)(%rdx), RA1; vmovdqu (2 * 32)(%rdx), RA2; @@ -771,8 +767,6 @@ _gcry_serpent_avx2_cfb_dec: */ CFI_STARTPROC(); - vzeroupper; - /* Load input */ vmovdqu (%rcx), RNOTx; vinserti128 $1, (%rdx), RNOT, RA0; @@ -829,8 +823,6 @@ _gcry_serpent_avx2_ocb_enc: */ CFI_STARTPROC(); - vzeroupper; - subq $(4 * 8), %rsp; CFI_ADJUST_CFA_OFFSET(4 * 8); @@ -943,8 +935,6 @@ _gcry_serpent_avx2_ocb_dec: */ CFI_STARTPROC(); - vzeroupper; - subq $(4 * 8), %rsp; CFI_ADJUST_CFA_OFFSET(4 * 8); @@ -1066,8 +1056,6 @@ _gcry_serpent_avx2_ocb_auth: */ CFI_STARTPROC(); - vzeroupper; - subq $(4 * 8), %rsp; CFI_ADJUST_CFA_OFFSET(4 * 8); diff --git a/cipher/sha1-avx-amd64.S b/cipher/sha1-avx-amd64.S index e5e55684..ca81506c 100644 --- a/cipher/sha1-avx-amd64.S +++ b/cipher/sha1-avx-amd64.S @@ -222,8 +222,6 @@ _gcry_sha1_transform_amd64_avx: cmpq $0, %rdx; jz .Lret; - vzeroupper; - movq %rdx, RNBLKS; movq %rdi, RSTATE; movq %rsi, RDATA; diff --git a/cipher/sha1-avx-bmi2-amd64.S b/cipher/sha1-avx-bmi2-amd64.S index 16a01bfd..85ba22b0 100644 --- a/cipher/sha1-avx-bmi2-amd64.S +++ b/cipher/sha1-avx-bmi2-amd64.S @@ -222,8 +222,6 @@ _gcry_sha1_transform_amd64_avx_bmi2: cmpq $0, %rdx; jz .Lret; - vzeroupper; - movq %rdx, RNBLKS; movq %rdi, RSTATE; movq %rsi, RDATA; diff --git a/cipher/sha1-avx2-bmi2-amd64.S b/cipher/sha1-avx2-bmi2-amd64.S index 06ff92f0..190b9731 100644 --- a/cipher/sha1-avx2-bmi2-amd64.S +++ b/cipher/sha1-avx2-bmi2-amd64.S @@ -224,8 +224,6 @@ _gcry_sha1_transform_amd64_avx2_bmi2: */ CFI_STARTPROC(); - vzeroupper; - movq %rdx, RNBLKS; movq %rdi, RSTATE; movq %rsi, RDATA; diff --git a/cipher/sha256-avx-amd64.S b/cipher/sha256-avx-amd64.S index 8cfd0880..9c15f481 100644 --- a/cipher/sha256-avx-amd64.S +++ b/cipher/sha256-avx-amd64.S @@ -345,7 +345,6 @@ ELF(.type _gcry_sha256_transform_amd64_avx, at function;) .align 16 _gcry_sha256_transform_amd64_avx: CFI_STARTPROC() - vzeroupper push rbx CFI_PUSH(rbx) diff --git a/cipher/sha256-avx2-bmi2-amd64.S b/cipher/sha256-avx2-bmi2-amd64.S index e2a5454c..ec99e57f 100644 --- a/cipher/sha256-avx2-bmi2-amd64.S +++ b/cipher/sha256-avx2-bmi2-amd64.S @@ -268,8 +268,6 @@ _gcry_sha256_transform_amd64_avx2: push r15 CFI_PUSH(r15) - vzeroupper - vmovdqa BYTE_FLIP_MASK, [.LPSHUFFLE_BYTE_FLIP_MASK ADD_RIP] vmovdqa SHUF_00BA, [.L_SHUF_00BA ADD_RIP] vmovdqa SHUF_DC00, [.L_SHUF_DC00 ADD_RIP] diff --git a/cipher/sha512-avx-amd64.S b/cipher/sha512-avx-amd64.S index 1bd38060..22b1058e 100644 --- a/cipher/sha512-avx-amd64.S +++ b/cipher/sha512-avx-amd64.S @@ -254,8 +254,6 @@ _gcry_sha512_transform_amd64_avx: cmp msglen, 0 je .Lnowork - vzeroupper - /* Allocate Stack Space */ sub rsp, frame_size CFI_ADJUST_CFA_OFFSET(frame_size); diff --git a/cipher/sha512-avx2-bmi2-amd64.S b/cipher/sha512-avx2-bmi2-amd64.S index 7b60bf1d..c2275bb5 100644 --- a/cipher/sha512-avx2-bmi2-amd64.S +++ b/cipher/sha512-avx2-bmi2-amd64.S @@ -282,8 +282,6 @@ _gcry_sha512_transform_amd64_avx2: cmp rdx, 0 je .Lnowork - vzeroupper - /* Allocate Stack Space */ mov rax, rsp CFI_DEF_CFA_REGISTER(rax); diff --git a/cipher/sm3-avx-bmi2-amd64.S b/cipher/sm3-avx-bmi2-amd64.S index ef923165..9252e279 100644 --- a/cipher/sm3-avx-bmi2-amd64.S +++ b/cipher/sm3-avx-bmi2-amd64.S @@ -354,8 +354,6 @@ _gcry_sm3_transform_amd64_avx_bmi2: */ CFI_STARTPROC(); - vzeroupper; - pushq %rbp; CFI_PUSH(%rbp); movq %rsp, %rbp; diff --git a/cipher/twofish-avx2-amd64.S b/cipher/twofish-avx2-amd64.S index 72a39d17..c448dfae 100644 --- a/cipher/twofish-avx2-amd64.S +++ b/cipher/twofish-avx2-amd64.S @@ -519,8 +519,6 @@ _gcry_twofish_avx2_blk16: */ CFI_STARTPROC(); - vzeroupper; - vmovdqu (0 * 32)(%rdx), RA0; vmovdqu (1 * 32)(%rdx), RB0; vmovdqu (2 * 32)(%rdx), RC0; @@ -565,8 +563,6 @@ _gcry_twofish_avx2_ctr_enc: */ CFI_STARTPROC(); - vzeroupper; - vbroadcasti128 .Lbswap128_mask rRIP, RTMP3; vpcmpeqd RNOT, RNOT, RNOT; vpsrldq $14, RNOT, RNOT; /* ab: -1:0 ; cd: -1:0 */ @@ -638,8 +634,6 @@ _gcry_twofish_avx2_cbc_dec: */ CFI_STARTPROC(); - vzeroupper; - vmovdqu (0 * 32)(%rdx), RA0; vmovdqu (1 * 32)(%rdx), RB0; vmovdqu (2 * 32)(%rdx), RC0; @@ -691,8 +685,6 @@ _gcry_twofish_avx2_cfb_dec: */ CFI_STARTPROC(); - vzeroupper; - /* Load input */ vmovdqu (%rcx), RNOTx; vinserti128 $1, (%rdx), RNOT, RA0; @@ -749,8 +741,6 @@ _gcry_twofish_avx2_ocb_enc: */ CFI_STARTPROC(); - vzeroupper; - subq $(4 * 8), %rsp; CFI_ADJUST_CFA_OFFSET(4 * 8); @@ -863,8 +853,6 @@ _gcry_twofish_avx2_ocb_dec: */ CFI_STARTPROC(); - vzeroupper; - subq $(4 * 8), %rsp; CFI_ADJUST_CFA_OFFSET(4 * 8); @@ -987,8 +975,6 @@ _gcry_twofish_avx2_ocb_auth: */ CFI_STARTPROC(); - vzeroupper; - subq $(4 * 8), %rsp; CFI_ADJUST_CFA_OFFSET(4 * 8); -- 2.53.0 From jonathan.plata at lightshipsec.com Wed Sep 9 16:12:25 2026 From: jonathan.plata at lightshipsec.com (Jonathan Plata) Date: Wed, 9 Sep 2026 14:12:25 +0000 Subject: PATCH: Padding bug in cSHAKE-128/256 Message-ID: Hello! cshake_input_s()'s padlen computation, padlen = ctx->blocksize - (len_written % ctx->blocksize); does not handle the case where len_written is already an exact multiple of ctx->blocksize: the modulo evaluates to 0, so padlen comes out as ctx->blocksize (a full block) instead of 0. SP 800-185's bytepad (sec. 2.3.3) specifies padding with zero bytes only until the total length becomes a multiple of the rate -- when it already is, no padding bytes should be added at all. The bug results in a full extra block of zero bytes added to the Keccak sponge, producing a wrong cSHAKE digest whenever the encoded N (function-name string) + S (customization string) length lands exactly on a rate boundary (168 bytes for cSHAKE128, 136 for cSHAKE256). Concretely: cSHAKE128 with an empty N and a 161-byte S (2-byte rate prefix + 2-byte encode_string(empty N) + 3-byte encode_string(S) length-prefix + 161 == 168 == the cSHAKE128 rate) triggers it; cSHAKE256 with an empty N and a 129-byte S hits the same condition against its 136-byte rate. Found via NIST ACVP cSHAKE-128/256 conformance vectors: a fixture covering random S lengths reliably produces a wrong digest at S = 161 (cSHAKE128) and S = 129 (cSHAKE256), and only those lengths (adjacent lengths pass), consistent with this exact rate-boundary condition. Confirmed against libgcrypt 1.11.2 and 1.12.0 (unchanged between the two). Signed-off-by: Jonathan Plata --- cipher/keccak.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cipher/keccak.c b/cipher/keccak.c index a0ba1fbb..1351da16 100644 --- a/cipher/keccak.c +++ b/cipher/keccak.c @@ -1694,7 +1694,7 @@ cshake_input_s (KECCAK_CONTEXT *ctx, const void *s, unsigned int s_len, keccak_write (ctx, s, s_len); len_written += buf[0] + 1 + s_len; - padlen = ctx->blocksize - (len_written % ctx->blocksize); + padlen = (ctx->blocksize - (len_written % ctx->blocksize)) % ctx->blocksize; memset (buf, 0, padlen); keccak_write (ctx, buf, padlen); } -- 2.34.1 [cid:image001.png at 01DD4040.AC77CD40] Jonathan Plata | Software Developer Lightship Security, Inc. Tel: 512-362-6594 https://lightshipsec.com This email and attachments are confidential and intended solely for the use of the individual or entity to whom they are addressed. If you are not the named addressee, you may not disseminate, distribute or copy this email. Please notify the sender immediately if you have received this email in error and delete it from your system. -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image001.png Type: image/png Size: 4162 bytes Desc: image001.png URL: From gniibe at fsij.org Thu Sep 10 07:26:04 2026 From: gniibe at fsij.org (NIIBE Yutaka) Date: Thu, 10 Sep 2026 14:26:04 +0900 Subject: PATCH: Padding bug in cSHAKE-128/256 In-Reply-To: References: Message-ID: <87ecf1brtf.fsf@haruna.fsij.org> Hello, Jonathan Plata wrote: > cshake_input_s()'s padlen computation, > > padlen = ctx->blocksize - (len_written % ctx->blocksize); Thank you for your report. > --- a/cipher/keccak.c > +++ b/cipher/keccak.c > @@ -1694,7 +1694,7 @@ cshake_input_s (KECCAK_CONTEXT *ctx, const void *s, unsigned int s_len, > keccak_write (ctx, s, s_len); > > len_written += buf[0] + 1 + s_len; > - padlen = ctx->blocksize - (len_written % ctx->blocksize); > + padlen = (ctx->blocksize - (len_written % ctx->blocksize)) % ctx->blocksize; > memset (buf, 0, padlen); > keccak_write (ctx, buf, padlen); > } While the expression is correct, I'm not sure if multiple %-operations can be optimized well by compiler. Just in case, I think that it's better to use a single %-operation in the expression. Attached is a patch with a single %-operation. If no objections, I will push this to 1.11, 1.12 and master. -- -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-cipher-keccak-Fix-padding-in-cSHAKE.patch Type: text/x-diff Size: 1529 bytes Desc: not available URL: From mattst88 at gmail.com Wed Sep 2 15:17:20 2026 From: mattst88 at gmail.com (Matt Turner) Date: Wed, 2 Sep 2026 09:17:20 -0400 Subject: [PATCH] mpi: Drop casts from inline asm output operands. Message-ID: <20260902131720.409681-1-mattst88@gmail.com> * mpi/longlong.h [__a29k__, __alpha, __gmicro__, __hppa, __i960__, __mc68000__, __m88000__, __mips__, __mips, __ns32000__, __pyr__, __ibm032__, __sh2__, __sparc__, __vax__, __z8000__]: Drop the casts on asm output operands. -- Using a cast as an lvalue is a GCC extension that clang does not implement. Clang rejects it with -Winvalid-gnu-asm-cast, which is an error by default, so these blocks fail to build with clang. The casts do nothing. GCC accepts a cast in an asm output only when it is a no-op, and rejects it with "lvalue required in 'asm' statement" otherwise, so any code that compiles today already passes an operand of the right type. GMP's longlong.h dropped these long ago. The Z8000 block is the exception. There W_TYPE_SIZE is 16, so the cast to unsigned int is not a no-op and GCC would reject it too; that block has been dead for a long time and is fixed here for consistency. Casts on *input* operands are left alone: those are ordinary rvalue conversions, and on x86 count_leading_zeros/count_trailing_zeros the "rm" ((USItype)(x)) cast is what selects the operand width. Checked with the cross toolchains available here. GCC generates identical assembly before and after for alpha, hppa, mc68000, sh4, 32-bit sparc and mips. Clang builds the sparc block only after this change; it has no back end for alpha, hppa or mc68000, so those could not be checked with clang. The blocks with no compiler to test against (a29k, gmicro, i960, m88k, ns32000, pyr, RT/ROMP, vax, z8000) are changed mechanically. The MIPS asm blocks are unreachable in practice: any compiler new enough to matter takes the preceding __GNUC__ >= 5 branch, which uses a plain wide multiply, and the asm variants no longer assemble anyway now that GCC has removed the "h" constraint ("impossible constraint in 'asm'"). Signed-off-by: Matt Turner --- mpi/longlong.h | 174 ++++++++++++++++++++++++------------------------- 1 file changed, 87 insertions(+), 87 deletions(-) diff --git ./mpi/longlong.h ./mpi/longlong.h index 453f2704..b27d0b88 100644 --- ./mpi/longlong.h +++ ./mpi/longlong.h @@ -133,8 +133,8 @@ SPDX-License-Identifier: LGPL-2.1-or-later # define add_ssaaaa(sh, sl, ah, al, bh, bl) \ __asm__ ("add %1,%4,%5\n" \ "addc %0,%2,%3" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "%r" ((USItype)(ah)), \ "rI" ((USItype)(bh)), \ "%r" ((USItype)(al)), \ @@ -142,8 +142,8 @@ SPDX-License-Identifier: LGPL-2.1-or-later # define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("sub %1,%4,%5\n" \ "subc %0,%2,%3" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "r" ((USItype)(ah)), \ "rI" ((USItype)(bh)), \ "r" ((USItype)(al)), \ @@ -152,24 +152,24 @@ SPDX-License-Identifier: LGPL-2.1-or-later do { \ USItype __m0 = (m0), __m1 = (m1); \ __asm__ ("multiplu %0,%1,%2" \ - : "=r" ((USItype)(xl)) \ + : "=r" (xl) \ : "r" (__m0), \ "r" (__m1)); \ __asm__ ("multmu %0,%1,%2" \ - : "=r" ((USItype)(xh)) \ + : "=r" (xh) \ : "r" (__m0), \ "r" (__m1)); \ } while (0) # define udiv_qrnnd(q, r, n1, n0, d) \ __asm__ ("dividu %0,%3,%4" \ - : "=r" ((USItype)(q)), \ - "=q" ((USItype)(r)) \ + : "=r" (q), \ + "=q" (r) \ : "1" ((USItype)(n1)), \ "r" ((USItype)(n0)), \ "r" ((USItype)(d))) # define count_leading_zeros(count, x) \ __asm__ ("clz %0,%1" \ - : "=r" ((USItype)(count)) \ + : "=r" (count) \ : "r" ((USItype)(x))) # define COUNT_LEADING_ZEROS_0 32 #endif /* __a29k__ */ @@ -180,7 +180,7 @@ SPDX-License-Identifier: LGPL-2.1-or-later do { \ UDItype __m0 = (m0), __m1 = (m1); \ __asm__ ("umulh %r1,%2,%0" \ - : "=r" ((UDItype)(ph)) \ + : "=r" (ph) \ : "%rJ" (__m0), \ "rI" (__m1)); \ (pl) = __m0 * __m1; \ @@ -365,8 +365,8 @@ extern UDItype __udiv_qrnnd (UDItype *, UDItype, UDItype, UDItype); # define add_ssaaaa(sh, sl, ah, al, bh, bl) \ __asm__ ("add.w %5,%1\n" \ "addx %3,%0" \ - : "=g" ((USItype)(sh)), \ - "=&g" ((USItype)(sl)) \ + : "=g" (sh), \ + "=&g" (sl) \ : "%0" ((USItype)(ah)), \ "g" ((USItype)(bh)), \ "%1" ((USItype)(al)), \ @@ -374,22 +374,22 @@ extern UDItype __udiv_qrnnd (UDItype *, UDItype, UDItype, UDItype); # define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("sub.w %5,%1\n" \ "subx %3,%0" \ - : "=g" ((USItype)(sh)), \ - "=&g" ((USItype)(sl)) \ + : "=g" (sh), \ + "=&g" (sl) \ : "0" ((USItype)(ah)), \ "g" ((USItype)(bh)), \ "1" ((USItype)(al)), \ "g" ((USItype)(bl))) # define umul_ppmm(ph, pl, m0, m1) \ __asm__ ("mulx %3,%0,%1" \ - : "=g" ((USItype)(ph)), \ - "=r" ((USItype)(pl)) \ + : "=g" (ph), \ + "=r" (pl) \ : "%0" ((USItype)(m0)), \ "g" ((USItype)(m1))) # define udiv_qrnnd(q, r, nh, nl, d) \ __asm__ ("divx %4,%0,%1" \ - : "=g" ((USItype)(q)), \ - "=r" ((USItype)(r)) \ + : "=g" (q), \ + "=r" (r) \ : "1" ((USItype)(nh)), \ "0" ((USItype)(nl)), \ "g" ((USItype)(d))) @@ -408,8 +408,8 @@ extern UDItype __udiv_qrnnd (UDItype *, UDItype, UDItype, UDItype); # define add_ssaaaa(sh, sl, ah, al, bh, bl) \ __asm__ ("add %4,%5,%1\n\t" \ "addc %2,%3,%0" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "%rM" ((USItype)(ah)), \ "rM" ((USItype)(bh)), \ "%rM" ((USItype)(al)), \ @@ -417,8 +417,8 @@ extern UDItype __udiv_qrnnd (UDItype *, UDItype, UDItype, UDItype); # define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("sub %4,%5,%1\n\t" \ "subb %2,%3,%0" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "rM" ((USItype)(ah)), \ "rM" ((USItype)(bh)), \ "rM" ((USItype)(al)), \ @@ -658,8 +658,8 @@ extern USItype __udiv_qrnnd (USItype *, USItype, USItype, USItype); __asm__ ("cmpo 1,0\n" \ "addc %5,%4,%1\n" \ "addc %3,%2,%0" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "%dI" ((USItype)(ah)), \ "dI" ((USItype)(bh)), \ "%dI" ((USItype)(al)), \ @@ -668,8 +668,8 @@ extern USItype __udiv_qrnnd (USItype *, USItype, USItype, USItype); __asm__ ("cmpo 0,0\n" \ "subc %5,%4,%1\n" \ "subc %3,%2,%0" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "dI" ((USItype)(ah)), \ "dI" ((USItype)(bh)), \ "dI" ((USItype)(al)), \ @@ -733,8 +733,8 @@ extern USItype __udiv_qrnnd (USItype *, USItype, USItype, USItype); # define add_ssaaaa(sh, sl, ah, al, bh, bl) \ __asm__ ("add%.l %5,%1\n" \ "addx%.l %3,%0" \ - : "=d" ((USItype)(sh)), \ - "=&d" ((USItype)(sl)) \ + : "=d" (sh), \ + "=&d" (sl) \ : "%0" ((USItype)(ah)), \ "d" ((USItype)(bh)), \ "%1" ((USItype)(al)), \ @@ -742,8 +742,8 @@ extern USItype __udiv_qrnnd (USItype *, USItype, USItype, USItype); # define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("sub%.l %5,%1\n" \ "subx%.l %3,%0" \ - : "=d" ((USItype)(sh)), \ - "=&d" ((USItype)(sl)) \ + : "=d" (sh), \ + "=&d" (sl) \ : "0" ((USItype)(ah)), \ "d" ((USItype)(bh)), \ "1" ((USItype)(al)), \ @@ -751,29 +751,29 @@ extern USItype __udiv_qrnnd (USItype *, USItype, USItype, USItype); # if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) # define umul_ppmm(w1, w0, u, v) \ __asm__ ("mulu%.l %3,%1:%0" \ - : "=d" ((USItype)(w0)), \ - "=d" ((USItype)(w1)) \ + : "=d" (w0), \ + "=d" (w1) \ : "%0" ((USItype)(u)), \ "dmi" ((USItype)(v))) # define UMUL_TIME 45 # define udiv_qrnnd(q, r, n1, n0, d) \ __asm__ ("divu%.l %4,%1:%0" \ - : "=d" ((USItype)(q)), \ - "=d" ((USItype)(r)) \ + : "=d" (q), \ + "=d" (r) \ : "0" ((USItype)(n0)), \ "1" ((USItype)(n1)), \ "dmi" ((USItype)(d))) # define UDIV_TIME 90 # define sdiv_qrnnd(q, r, n1, n0, d) \ __asm__ ("divs%.l %4,%1:%0" \ - : "=d" ((USItype)(q)), \ - "=d" ((USItype)(r)) \ + : "=d" (q), \ + "=d" (r) \ : "0" ((USItype)(n0)), \ "1" ((USItype)(n1)), \ "dmi" ((USItype)(d))) # define count_leading_zeros(count, x) \ __asm__ ("bfffo %1{%b2:%b2},%0" \ - : "=d" ((USItype)(count)) \ + : "=d" (count) \ : "od" ((USItype)(x)), "n" (0)) # define COUNT_LEADING_ZEROS_0 32 # else /* not mc68020 */ @@ -801,7 +801,7 @@ extern USItype __udiv_qrnnd (USItype *, USItype, USItype, USItype); " add%.l %3,%1 \n" \ " addx%.l %2,%0 \n" \ " | End inlined umul_ppmm" \ - : "=&d" ((USItype)(xh)), "=&d" ((USItype)(xl)), \ + : "=&d" (xh), "=&d" (xl), \ "=d" (__umul_tmp1), "=&d" (__umul_tmp2) \ : "%2" ((USItype)(a)), "d" ((USItype)(b))); \ } while (0) @@ -818,8 +818,8 @@ extern USItype __udiv_qrnnd (USItype *, USItype, USItype, USItype); # define add_ssaaaa(sh, sl, ah, al, bh, bl) \ __asm__ ("addu.co %1,%r4,%r5\n" \ "addu.ci %0,%r2,%r3" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "%rJ" ((USItype)(ah)), \ "rJ" ((USItype)(bh)), \ "%rJ" ((USItype)(al)), \ @@ -827,8 +827,8 @@ extern USItype __udiv_qrnnd (USItype *, USItype, USItype, USItype); # define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("subu.co %1,%r4,%r5\n" \ "subu.ci %0,%r2,%r3" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "rJ" ((USItype)(ah)), \ "rJ" ((USItype)(bh)), \ "rJ" ((USItype)(al)), \ @@ -884,8 +884,8 @@ extern USItype __udiv_qrnnd (USItype *, USItype, USItype, USItype); # elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7 # define umul_ppmm(w1, w0, u, v) \ __asm__ ("multu %2,%3" \ - : "=l" ((USItype)(w0)), \ - "=h" ((USItype)(w1)) \ + : "=l" (w0), \ + "=h" (w1) \ : "d" ((USItype)(u)), \ "d" ((USItype)(v))) # else @@ -893,8 +893,8 @@ extern USItype __udiv_qrnnd (USItype *, USItype, USItype, USItype); __asm__ ("multu %2,%3 \n" \ "mflo %0 \n" \ "mfhi %1" \ - : "=d" ((USItype)(w0)), \ - "=d" ((USItype)(w1)) \ + : "=d" (w0), \ + "=d" (w1) \ : "d" ((USItype)(u)), \ "d" ((USItype)(v))) # endif @@ -919,8 +919,8 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); # elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7 # define umul_ppmm(w1, w0, u, v) \ __asm__ ("dmultu %2,%3" \ - : "=l" ((UDItype)(w0)), \ - "=h" ((UDItype)(w1)) \ + : "=l" (w0), \ + "=h" (w1) \ : "d" ((UDItype)(u)), \ "d" ((UDItype)(v))) # else @@ -928,8 +928,8 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); __asm__ ("dmultu %2,%3 \n" \ "mflo %0 \n" \ "mfhi %1" \ - : "=d" ((UDItype)(w0)), \ - "=d" ((UDItype)(w1)) \ + : "=d" (w0), \ + "=d" (w1) \ : "d" ((UDItype)(u)), \ "d" ((UDItype)(v))) # endif @@ -971,7 +971,7 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); # define count_trailing_zeros(count,x) \ do { __asm__ ("ffsd %2,%0" \ - : "=r" ((USItype) (count)) \ + : "=r" (count) \ : "0" ((USItype) 0), \ "r" ((USItype) (x))); \ } while (0) @@ -1120,8 +1120,8 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); # define add_ssaaaa(sh, sl, ah, al, bh, bl) \ __asm__ ("addw %5,%1 \n" \ "addwc %3,%0" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "%0" ((USItype)(ah)), \ "g" ((USItype)(bh)), \ "%1" ((USItype)(al)), \ @@ -1129,8 +1129,8 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); # define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("subw %5,%1 \n" \ "subwb %3,%0" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "0" ((USItype)(ah)), \ "g" ((USItype)(bh)), \ "1" ((USItype)(al)), \ @@ -1156,8 +1156,8 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); # define add_ssaaaa(sh, sl, ah, al, bh, bl) \ __asm__ ("a %1,%5 \n" \ "ae %0,%3" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "%0" ((USItype)(ah)), \ "r" ((USItype)(bh)), \ "%1" ((USItype)(al)), \ @@ -1165,8 +1165,8 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); # define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("s %1,%5\n" \ "se %0,%3" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "0" ((USItype)(ah)), \ "r" ((USItype)(bh)), \ "1" ((USItype)(al)), \ @@ -1195,8 +1195,8 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); "m r2,%3 \n" \ "cas %0,r2,r0 \n" \ "mfs r10,%1" \ - : "=r" ((USItype)(ph)), \ - "=r" ((USItype)(pl)) \ + : "=r" (ph), \ + "=r" (pl) \ : "%r" (__m0), \ "r" (__m1) \ : "r2"); \ @@ -1209,12 +1209,12 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); do { \ if ((x) >= 0x10000) \ __asm__ ("clz %0,%1" \ - : "=r" ((USItype)(count)) \ + : "=r" (count) \ : "r" ((USItype)(x) >> 16)); \ else \ { \ __asm__ ("clz %0,%1" \ - : "=r" ((USItype)(count)) \ + : "=r" (count) \ : "r" ((USItype)(x))); \ (count) += 16; \ } \ @@ -1232,8 +1232,8 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); "dmulu.l %2,%3\n" \ "sts macl,%1\n" \ "sts mach,%0" \ - : "=r" ((USItype)(w1)), \ - "=r" ((USItype)(w0)) \ + : "=r" (w1), \ + "=r" (w0) \ : "r" ((USItype)(u)), \ "r" ((USItype)(v)) \ : "macl", "mach") @@ -1247,8 +1247,8 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); # define add_ssaaaa(sh, sl, ah, al, bh, bl) \ __asm__ ("addcc %r4,%5,%1\n" \ "addx %r2,%3,%0" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "%rJ" ((USItype)(ah)), \ "rI" ((USItype)(bh)), \ "%rJ" ((USItype)(al)), \ @@ -1257,8 +1257,8 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); # define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("subcc %r4,%5,%1\n" \ "subx %r2,%3,%0" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "rJ" ((USItype)(ah)), \ "rI" ((USItype)(bh)), \ "rJ" ((USItype)(al)), \ @@ -1271,8 +1271,8 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); but INTERPRETED AS UNSIGNED. */ # define umul_ppmm(w1, w0, u, v) \ __asm__ ("umul %2,%3,%1;rd %%y,%0" \ - : "=r" ((USItype)(w1)), \ - "=r" ((USItype)(w0)) \ + : "=r" (w1), \ + "=r" (w0) \ : "r" ((USItype)(u)), \ "r" ((USItype)(v))) # define UMUL_TIME 5 @@ -1281,7 +1281,7 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); do { \ USItype __q; \ __asm__ ("mov %1,%%y;nop;nop;nop;udiv %2,%3,%0" \ - : "=r" ((USItype)(__q)) \ + : "=r" (__q) \ : "r" ((USItype)(n1)), \ "r" ((USItype)(n0)), \ "r" ((USItype)(d))); \ @@ -1296,8 +1296,8 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); instructions scan (ffs from high bit) and divscc. */ # define umul_ppmm(w1, w0, u, v) \ __asm__ ("umul %2,%3,%1;rd %%y,%0" \ - : "=r" ((USItype)(w1)), \ - "=r" ((USItype)(w0)) \ + : "=r" (w1), \ + "=r" (w0) \ : "r" ((USItype)(u)), \ "r" ((USItype)(v))) # define UMUL_TIME 5 @@ -1341,8 +1341,8 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); " bl,a 1f \n" \ " add %1,%4,%1 \n" \ "1: ! End of inline udiv_qrnnd" \ - : "=r" ((USItype)(q)), \ - "=r" ((USItype)(r)) \ + : "=r" (q), \ + "=r" (r) \ : "r" ((USItype)(n1)), \ "r" ((USItype)(n0)), \ "rI" ((USItype)(d)) \ @@ -1350,7 +1350,7 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); # define UDIV_TIME 37 # define count_leading_zeros(count, x) \ __asm__ ("scan %1,0,%0" \ - : "=r" ((USItype)(x)) \ + : "=r" (x) \ : "r" ((USItype)(count))) /* Early sparclites return 63 for an argument of 0, but they warn that future implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0 @@ -1400,8 +1400,8 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); " mulscc %%g1,0,%%g1 \n" \ " add %%g1,%%g2,%0 \n" \ " rd %%y,%1" \ - : "=r" ((USItype)(w1)), \ - "=r" ((USItype)(w0)) \ + : "=r" (w1), \ + "=r" (w0) \ : "%rI" ((USItype)(u)), \ "r" ((USItype)(v)) \ : "%g1", "%g2" __AND_CLOBBER_CC) @@ -1428,8 +1428,8 @@ extern USItype __udiv_qrnnd (USItype *, USItype, USItype, USItype); # define add_ssaaaa(sh, sl, ah, al, bh, bl) \ __asm__ ("addl2 %5,%1\n" \ "adwc %3,%0" \ - : "=g" ((USItype)(sh)), \ - "=&g" ((USItype)(sl)) \ + : "=g" (sh), \ + "=&g" (sl) \ : "%0" ((USItype)(ah)), \ "g" ((USItype)(bh)), \ "%1" ((USItype)(al)), \ @@ -1437,8 +1437,8 @@ extern USItype __udiv_qrnnd (USItype *, USItype, USItype, USItype); # define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("subl2 %5,%1\n" \ "sbwc %3,%0" \ - : "=g" ((USItype)(sh)), \ - "=&g" ((USItype)(sl)) \ + : "=g" (sh), \ + "=&g" (sl) \ : "0" ((USItype)(ah)), \ "g" ((USItype)(bh)), \ "1" ((USItype)(al)), \ @@ -1476,16 +1476,16 @@ extern USItype __udiv_qrnnd (USItype *, USItype, USItype, USItype); #if defined (__z8000__) && W_TYPE_SIZE == 16 # define add_ssaaaa(sh, sl, ah, al, bh, bl) \ __asm__ ("add %H1,%H5\n\tadc %H0,%H3" \ - : "=r" ((unsigned int)(sh)), \ - "=&r" ((unsigned int)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "%0" ((unsigned int)(ah)), \ "r" ((unsigned int)(bh)), \ "%1" ((unsigned int)(al)), \ "rQR" ((unsigned int)(bl))) # define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("sub %H1,%H5\n\tsbc %H0,%H3" \ - : "=r" ((unsigned int)(sh)), \ - "=&r" ((unsigned int)(sl)) \ + : "=r" (sh), \ + "=&r" (sl) \ : "0" ((unsigned int)(ah)), \ "r" ((unsigned int)(bh)), \ "1" ((unsigned int)(al)), \ -- 2.54.0 From gniibe at fsij.org Thu Sep 3 09:22:50 2026 From: gniibe at fsij.org (NIIBE Yutaka) Date: Thu, 03 Sep 2026 16:22:50 +0900 Subject: [PATCH] mpi: Drop casts from inline asm output operands. In-Reply-To: <20260902131720.409681-1-mattst88@gmail.com> References: <20260902131720.409681-1-mattst88@gmail.com> Message-ID: <87bjaekddh.fsf@haruna.fsij.org> Hello, Matt Turner wrote: > Using a cast as an lvalue is a GCC extension that clang does not > implement. Clang rejects it with -Winvalid-gnu-asm-cast, which is an > error by default, so these blocks fail to build with clang. Please find a workaround for Clang. IIUC, please use -Wno-invalid-gnu-asm-cast option. If really needed, we could consider adding the option for Clang in libgcrypt/configure.ac. For longlong.h, the upstream used to be GNU C library. It is GCC now (gcc/include/longlong.h). We don't want further differences of our own from upstream. -- From mattst88 at gmail.com Thu Sep 3 20:32:57 2026 From: mattst88 at gmail.com (Matt Turner) Date: Thu, 3 Sep 2026 14:32:57 -0400 Subject: [PATCH] mpi: Drop casts from inline asm output operands. In-Reply-To: <87bjaekddh.fsf@haruna.fsij.org> References: <20260902131720.409681-1-mattst88@gmail.com> <87bjaekddh.fsf@haruna.fsij.org> Message-ID: On Thu, Sep 3, 2026 at 3:22 AM NIIBE Yutaka wrote: > > Hello, > > Matt Turner wrote: > > Using a cast as an lvalue is a GCC extension that clang does not > > implement. Clang rejects it with -Winvalid-gnu-asm-cast, which is an > > error by default, so these blocks fail to build with clang. > > Please find a workaround for Clang. IIUC, please use > -Wno-invalid-gnu-asm-cast option. If really needed, we could consider > adding the option for Clang in libgcrypt/configure.ac. > > For longlong.h, the upstream used to be GNU C library. It is GCC now > (gcc/include/longlong.h). > > We don't want further differences of our own from upstream. Ah, thank you. I'll fix this in GCC first and then return to this. From jussi.kivilinna at iki.fi Tue Sep 8 13:46:41 2026 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 8 Sep 2026 14:46:41 +0300 Subject: [PATCH 5/6] tests/basic: deduplicate vector cluttering hwf detection In-Reply-To: <20260908114642.1031933-1-jussi.kivilinna@iki.fi> References: <20260908114642.1031933-1-jussi.kivilinna@iki.fi> Message-ID: <20260908114642.1031933-5-jussi.kivilinna@iki.fi> * tests/basic.c (clutter_vector_registers): Replace per-architecture hwflist parsing with table driven detection. -- Each architecture had own copy of hwflist parsing and init handling. Signed-off-by: Jussi Kivilinna --- tests/basic.c | 121 ++++++++++++++++++-------------------------------- 1 file changed, 42 insertions(+), 79 deletions(-) diff --git a/tests/basic.c b/tests/basic.c index 4c5f6038..405f9861 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -307,95 +307,58 @@ clutter_vector_registers(void) static unsigned char data[CLUTTER_VECTOR_REGISTER_COUNT][16]; static int data_init; #endif +#if defined(CLUTTER_VECTOR_REGISTER_AMD64) || \ + defined(CLUTTER_VECTOR_REGISTER_I386) + static int have_ymm; + static int have_zmm; +#endif + static int have_vectors; + static struct + { + const char *match; + int *out_have; + int required; + int have; + } hwfeatures[] = + { #if defined(CLUTTER_VECTOR_REGISTER_AARCH64) || \ defined(CLUTTER_VECTOR_REGISTER_NEON) - static int init; - static int have_neon; - - if (!init) - { - char *string; - - string = gcry_get_config (0, "hwflist"); - if (string) - { - have_neon = (strstr(string, "arm-neon:") != NULL); - xfree(string); - } - init = 1; - } - - if (!have_neon) - return; + { "arm-neon:", &have_vectors, 1, 0 }, #elif defined(CLUTTER_VECTOR_REGISTER_AMD64) || \ defined(CLUTTER_VECTOR_REGISTER_I386) - static int init; - static int have_sse2; - static int have_avx; - static int have_avx512; - - if (!init) - { - char *string; - - string = gcry_get_config (0, "hwflist"); - if (string) - { - int have_ssse3 = (strstr(string, "intel-ssse3:") != NULL); - have_sse2 = have_ssse3; /* XMM registers supported */ - have_avx = (strstr(string, "intel-avx:") != NULL); /* YMM */ - have_avx512 = (strstr(string, "intel-avx512:") != NULL); /* ZMM */ - xfree(string); - } - -#ifdef CLUTTER_VECTOR_REGISTER_AMD64 - have_sse2 = 1; -#endif - - init = 1; - } - - if (!have_sse2) - return; + { "intel-ssse3:", &have_vectors, 1, 0 }, + { "intel-avx:", &have_ymm, 0, 0 }, + { "intel-avx512:", &have_zmm, 0, 0 }, #elif defined(CLUTTER_VECTOR_REGISTER_RISCV) - static int init; - static int have_rvv; + { "riscv-v:", &have_vectors, 1, 0 }, +#elif defined(CLUTTER_VECTOR_REGISTER_PPC) + { "ppc-arch_2_07:", &have_vectors, 1, 0 }, +#endif + }; + static int hwf_init = ((int)DIM(hwfeatures) == 0); - if (!init) + if (!hwf_init) { - char *string; - - string = gcry_get_config (0, "hwflist"); - if (string) + char *hwflist = gcry_get_config (0, "hwflist"); + if (hwflist) { - have_rvv = (strstr(string, "riscv-v:") != NULL); - xfree(string); - } - init = 1; - } + int i; - if (!have_rvv) - return; -#elif defined(CLUTTER_VECTOR_REGISTER_PPC) - static int init; - static int have_ppc_vec; - - if (!init) - { - char *string; + for (i = 0; i < (int)DIM(hwfeatures); i++) + { + int have = (strstr(hwflist, hwfeatures[i].match) != NULL); + hwfeatures[i].have = have; + *hwfeatures[i].out_have |= have; + } - string = gcry_get_config (0, "hwflist"); - if (string) - { - have_ppc_vec = (strstr(string, "ppc-arch_2_07:") != NULL); - xfree(string); + xfree(hwflist); } - init = 1; + + hwf_init = 1; } - if (!have_ppc_vec) + if (!have_vectors) return; -#endif #ifdef CLUTTER_VECTOR_REGISTER_COUNT if (!data_init) @@ -409,7 +372,7 @@ clutter_vector_registers(void) if (0) { } # ifdef HAVE_GCC_INLINE_ASM_AVX512 - else if (have_avx512) + else if (have_zmm) asm volatile("vbroadcasti32x4 (0 * 16)(%[data]), %%zmm0\n" "vbroadcasti32x4 (1 * 16)(%[data]), %%zmm1\n" "vbroadcasti32x4 (2 * 16)(%[data]), %%zmm2\n" @@ -455,7 +418,7 @@ clutter_vector_registers(void) ); # endif # ifdef HAVE_GCC_INLINE_ASM_AVX - else if (have_avx) + else if (have_ymm) asm volatile("vbroadcastf128 (0 * 16)(%[data]), %%ymm0\n" "vbroadcastf128 (1 * 16)(%[data]), %%ymm1\n" "vbroadcastf128 (2 * 16)(%[data]), %%ymm2\n" @@ -506,7 +469,7 @@ clutter_vector_registers(void) if (0) { } # ifdef HAVE_GCC_INLINE_ASM_AVX512 - else if (have_avx512) + else if (have_zmm) asm volatile("vbroadcasti32x4 (0 * 16)(%[data]), %%zmm0\n" "vbroadcasti32x4 (1 * 16)(%[data]), %%zmm1\n" "vbroadcasti32x4 (2 * 16)(%[data]), %%zmm2\n" @@ -522,7 +485,7 @@ clutter_vector_registers(void) ); # endif # ifdef HAVE_GCC_INLINE_ASM_AVX - else if (have_avx) + else if (have_ymm) asm volatile("vbroadcastf128 (0 * 16)(%[data]), %%ymm0\n" "vbroadcastf128 (1 * 16)(%[data]), %%ymm1\n" "vbroadcastf128 (2 * 16)(%[data]), %%ymm2\n" -- 2.53.0 From jussi.kivilinna at iki.fi Tue Sep 8 13:46:38 2026 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 8 Sep 2026 14:46:38 +0300 Subject: [PATCH 2/6] tests/basic: clutter YMM and ZMM registers on i386 and AMD64 In-Reply-To: <20260908114642.1031933-1-jussi.kivilinna@iki.fi> References: <20260908114642.1031933-1-jussi.kivilinna@iki.fi> Message-ID: <20260908114642.1031933-2-jussi.kivilinna@iki.fi> * tests/basic.c (CLUTTER_VECTOR_REGISTER_COUNT) [CLUTTER_VECTOR_REGISTER_AMD64]: Increase to 32. (clutter_vector_registers): Make clutter data static and prepare it only once. [CLUTTER_VECTOR_REGISTER_AMD64, CLUTTER_VECTOR_REGISTER_I386]: Detect AVX and AVX512 from hwflist; add YMM and ZMM register cluttering. -- Cluttering only XMM registers left upper halfs of YMM and ZMM registers untouched, so bugs in AVX and AVX512 implementations could pass unnoticed. Signed-off-by: Jussi Kivilinna --- tests/basic.c | 209 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 167 insertions(+), 42 deletions(-) diff --git a/tests/basic.c b/tests/basic.c index 9ec1b596..00d6586d 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -246,7 +246,7 @@ progress_handler (void *cb_data, const char *what, int printchar, defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \ defined(__SSE2__) # define CLUTTER_VECTOR_REGISTER_AMD64 1 -# define CLUTTER_VECTOR_REGISTER_COUNT 16 +# define CLUTTER_VECTOR_REGISTER_COUNT 32 #elif defined(__i386__) && SIZEOF_UNSIGNED_LONG == 4 && __GNUC__ >= 4 && \ defined(HAVE_GCC_INLINE_ASM_SSSE3) && defined(__SSE2__) # define CLUTTER_VECTOR_REGISTER_I386 1 @@ -295,7 +295,8 @@ static inline ALWAYS_INLINE void clutter_vector_registers(void) { #ifdef CLUTTER_VECTOR_REGISTER_COUNT - unsigned char data[CLUTTER_VECTOR_REGISTER_COUNT][16]; + static unsigned char data[CLUTTER_VECTOR_REGISTER_COUNT][16]; + static int data_init; #if defined(CLUTTER_VECTOR_REGISTER_AARCH64) || \ defined(CLUTTER_VECTOR_REGISTER_NEON) static int init; @@ -316,9 +317,12 @@ clutter_vector_registers(void) if (!have_neon) return; -#elif defined(CLUTTER_VECTOR_REGISTER_I386) +#elif defined(CLUTTER_VECTOR_REGISTER_AMD64) || \ + defined(CLUTTER_VECTOR_REGISTER_I386) static int init; - static int have_ssse3; + static int have_sse2; + static int have_avx; + static int have_avx512; if (!init) { @@ -327,55 +331,176 @@ clutter_vector_registers(void) string = gcry_get_config (0, "hwflist"); if (string) { - have_ssse3 = (strstr(string, "intel-ssse3:") != NULL); + int have_ssse3 = (strstr(string, "intel-ssse3:") != NULL); + have_sse2 = have_ssse3; /* XMM registers supported */ + have_avx = (strstr(string, "intel-avx:") != NULL); /* YMM */ + have_avx512 = (strstr(string, "intel-avx512:") != NULL); /* ZMM */ xfree(string); } + +#ifdef CLUTTER_VECTOR_REGISTER_AMD64 + have_sse2 = 1; +#endif + init = 1; } - if (!have_ssse3) + if (!have_sse2) return; #endif - prepare_vector_data(data); + if (!data_init) + { + prepare_vector_data(data); + data_init = 1; + } #if defined(CLUTTER_VECTOR_REGISTER_AMD64) - asm volatile("movdqu (0 * 16)(%[data]), %%xmm0\n" - "movdqu (1 * 16)(%[data]), %%xmm1\n" - "movdqu (2 * 16)(%[data]), %%xmm2\n" - "movdqu (3 * 16)(%[data]), %%xmm3\n" - "movdqu (4 * 16)(%[data]), %%xmm4\n" - "movdqu (5 * 16)(%[data]), %%xmm5\n" - "movdqu (6 * 16)(%[data]), %%xmm6\n" - "movdqu (7 * 16)(%[data]), %%xmm7\n" - "movdqu (8 * 16)(%[data]), %%xmm8\n" - "movdqu (9 * 16)(%[data]), %%xmm9\n" - "movdqu (10 * 16)(%[data]), %%xmm10\n" - "movdqu (11 * 16)(%[data]), %%xmm11\n" - "movdqu (12 * 16)(%[data]), %%xmm12\n" - "movdqu (13 * 16)(%[data]), %%xmm13\n" - "movdqu (14 * 16)(%[data]), %%xmm14\n" - "movdqu (15 * 16)(%[data]), %%xmm15\n" - : - : [data] "r" (&data[0]) - : "memory", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", - "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", - "xmm13", "xmm14", "xmm15" - ); + if (0) + { } +# ifdef HAVE_GCC_INLINE_ASM_AVX512 + else if (have_avx512) + asm volatile("vbroadcasti32x4 (0 * 16)(%[data]), %%zmm0\n" + "vbroadcasti32x4 (1 * 16)(%[data]), %%zmm1\n" + "vbroadcasti32x4 (2 * 16)(%[data]), %%zmm2\n" + "vbroadcasti32x4 (3 * 16)(%[data]), %%zmm3\n" + "vbroadcasti32x4 (4 * 16)(%[data]), %%zmm4\n" + "vbroadcasti32x4 (5 * 16)(%[data]), %%zmm5\n" + "vbroadcasti32x4 (6 * 16)(%[data]), %%zmm6\n" + "vbroadcasti32x4 (7 * 16)(%[data]), %%zmm7\n" + "vbroadcasti32x4 (8 * 16)(%[data]), %%zmm8\n" + "vbroadcasti32x4 (9 * 16)(%[data]), %%zmm9\n" + "vbroadcasti32x4 (10 * 16)(%[data]), %%zmm10\n" + "vbroadcasti32x4 (11 * 16)(%[data]), %%zmm11\n" + "vbroadcasti32x4 (12 * 16)(%[data]), %%zmm12\n" + "vbroadcasti32x4 (13 * 16)(%[data]), %%zmm13\n" + "vbroadcasti32x4 (14 * 16)(%[data]), %%zmm14\n" + "vbroadcasti32x4 (15 * 16)(%[data]), %%zmm15\n" + "vbroadcasti32x4 (16 * 16)(%[data]), %%zmm16\n" + "vbroadcasti32x4 (17 * 16)(%[data]), %%zmm17\n" + "vbroadcasti32x4 (18 * 16)(%[data]), %%zmm18\n" + "vbroadcasti32x4 (19 * 16)(%[data]), %%zmm19\n" + "vbroadcasti32x4 (20 * 16)(%[data]), %%zmm20\n" + "vbroadcasti32x4 (21 * 16)(%[data]), %%zmm21\n" + "vbroadcasti32x4 (22 * 16)(%[data]), %%zmm22\n" + "vbroadcasti32x4 (23 * 16)(%[data]), %%zmm23\n" + "vbroadcasti32x4 (24 * 16)(%[data]), %%zmm24\n" + "vbroadcasti32x4 (25 * 16)(%[data]), %%zmm25\n" + "vbroadcasti32x4 (26 * 16)(%[data]), %%zmm26\n" + "vbroadcasti32x4 (27 * 16)(%[data]), %%zmm27\n" + "vbroadcasti32x4 (28 * 16)(%[data]), %%zmm28\n" + "vbroadcasti32x4 (29 * 16)(%[data]), %%zmm29\n" + "vbroadcasti32x4 (30 * 16)(%[data]), %%zmm30\n" + "vbroadcasti32x4 (31 * 16)(%[data]), %%zmm31\n" + : + : [data] "r" (&data[0]) + : "memory", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", + "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", + "xmm13", "xmm14", "xmm15" +# ifdef __AVX512F__ + , "xmm16", "xmm17", "xmm18", "xmm19", "xmm20", "xmm21", + "xmm22", "xmm23", "xmm24", "xmm25", "xmm26", "xmm27", + "xmm28", "xmm29", "xmm30", "xmm31" +# endif + ); +# endif +# ifdef HAVE_GCC_INLINE_ASM_AVX + else if (have_avx) + asm volatile("vbroadcastf128 (0 * 16)(%[data]), %%ymm0\n" + "vbroadcastf128 (1 * 16)(%[data]), %%ymm1\n" + "vbroadcastf128 (2 * 16)(%[data]), %%ymm2\n" + "vbroadcastf128 (3 * 16)(%[data]), %%ymm3\n" + "vbroadcastf128 (4 * 16)(%[data]), %%ymm4\n" + "vbroadcastf128 (5 * 16)(%[data]), %%ymm5\n" + "vbroadcastf128 (6 * 16)(%[data]), %%ymm6\n" + "vbroadcastf128 (7 * 16)(%[data]), %%ymm7\n" + "vbroadcastf128 (8 * 16)(%[data]), %%ymm8\n" + "vbroadcastf128 (9 * 16)(%[data]), %%ymm9\n" + "vbroadcastf128 (10 * 16)(%[data]), %%ymm10\n" + "vbroadcastf128 (11 * 16)(%[data]), %%ymm11\n" + "vbroadcastf128 (12 * 16)(%[data]), %%ymm12\n" + "vbroadcastf128 (13 * 16)(%[data]), %%ymm13\n" + "vbroadcastf128 (14 * 16)(%[data]), %%ymm14\n" + "vbroadcastf128 (15 * 16)(%[data]), %%ymm15\n" + : + : [data] "r" (&data[0]) + : "memory", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", + "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", + "xmm13", "xmm14", "xmm15" + ); +# endif + else + asm volatile("movdqu (0 * 16)(%[data]), %%xmm0\n" + "movdqu (1 * 16)(%[data]), %%xmm1\n" + "movdqu (2 * 16)(%[data]), %%xmm2\n" + "movdqu (3 * 16)(%[data]), %%xmm3\n" + "movdqu (4 * 16)(%[data]), %%xmm4\n" + "movdqu (5 * 16)(%[data]), %%xmm5\n" + "movdqu (6 * 16)(%[data]), %%xmm6\n" + "movdqu (7 * 16)(%[data]), %%xmm7\n" + "movdqu (8 * 16)(%[data]), %%xmm8\n" + "movdqu (9 * 16)(%[data]), %%xmm9\n" + "movdqu (10 * 16)(%[data]), %%xmm10\n" + "movdqu (11 * 16)(%[data]), %%xmm11\n" + "movdqu (12 * 16)(%[data]), %%xmm12\n" + "movdqu (13 * 16)(%[data]), %%xmm13\n" + "movdqu (14 * 16)(%[data]), %%xmm14\n" + "movdqu (15 * 16)(%[data]), %%xmm15\n" + : + : [data] "r" (&data[0]) + : "memory", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", + "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", + "xmm13", "xmm14", "xmm15" + ); #elif defined(CLUTTER_VECTOR_REGISTER_I386) - asm volatile("movdqu (0 * 16)(%[data]), %%xmm0\n" - "movdqu (1 * 16)(%[data]), %%xmm1\n" - "movdqu (2 * 16)(%[data]), %%xmm2\n" - "movdqu (3 * 16)(%[data]), %%xmm3\n" - "movdqu (4 * 16)(%[data]), %%xmm4\n" - "movdqu (5 * 16)(%[data]), %%xmm5\n" - "movdqu (6 * 16)(%[data]), %%xmm6\n" - "movdqu (7 * 16)(%[data]), %%xmm7\n" - : - : [data] "r" (&data[0]) - : "memory", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", - "xmm6", "xmm7" - ); + if (0) + { } +# ifdef HAVE_GCC_INLINE_ASM_AVX512 + else if (have_avx512) + asm volatile("vbroadcasti32x4 (0 * 16)(%[data]), %%zmm0\n" + "vbroadcasti32x4 (1 * 16)(%[data]), %%zmm1\n" + "vbroadcasti32x4 (2 * 16)(%[data]), %%zmm2\n" + "vbroadcasti32x4 (3 * 16)(%[data]), %%zmm3\n" + "vbroadcasti32x4 (4 * 16)(%[data]), %%zmm4\n" + "vbroadcasti32x4 (5 * 16)(%[data]), %%zmm5\n" + "vbroadcasti32x4 (6 * 16)(%[data]), %%zmm6\n" + "vbroadcasti32x4 (7 * 16)(%[data]), %%zmm7\n" + : + : [data] "r" (&data[0]) + : "memory", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", + "xmm6", "xmm7" + ); +# endif +# ifdef HAVE_GCC_INLINE_ASM_AVX + else if (have_avx) + asm volatile("vbroadcastf128 (0 * 16)(%[data]), %%ymm0\n" + "vbroadcastf128 (1 * 16)(%[data]), %%ymm1\n" + "vbroadcastf128 (2 * 16)(%[data]), %%ymm2\n" + "vbroadcastf128 (3 * 16)(%[data]), %%ymm3\n" + "vbroadcastf128 (4 * 16)(%[data]), %%ymm4\n" + "vbroadcastf128 (5 * 16)(%[data]), %%ymm5\n" + "vbroadcastf128 (6 * 16)(%[data]), %%ymm6\n" + "vbroadcastf128 (7 * 16)(%[data]), %%ymm7\n" + : + : [data] "r" (&data[0]) + : "memory", "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", + "ymm6", "ymm7" + ); +# endif + else + asm volatile("movdqu (0 * 16)(%[data]), %%xmm0\n" + "movdqu (1 * 16)(%[data]), %%xmm1\n" + "movdqu (2 * 16)(%[data]), %%xmm2\n" + "movdqu (3 * 16)(%[data]), %%xmm3\n" + "movdqu (4 * 16)(%[data]), %%xmm4\n" + "movdqu (5 * 16)(%[data]), %%xmm5\n" + "movdqu (6 * 16)(%[data]), %%xmm6\n" + "movdqu (7 * 16)(%[data]), %%xmm7\n" + : + : [data] "r" (&data[0]) + : "memory", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", + "xmm6", "xmm7" + ); #elif defined(CLUTTER_VECTOR_REGISTER_AARCH64) asm volatile("mov x0, %[ptr]\n" "ld1 {v0.16b}, [x0], #16\n" -- 2.53.0 From jussi.kivilinna at iki.fi Tue Sep 8 13:46:39 2026 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 8 Sep 2026 14:46:39 +0300 Subject: [PATCH 3/6] tests/basic: add vector cluttering for riscv In-Reply-To: <20260908114642.1031933-1-jussi.kivilinna@iki.fi> References: <20260908114642.1031933-1-jussi.kivilinna@iki.fi> Message-ID: <20260908114642.1031933-3-jussi.kivilinna@iki.fi> * tests/basic.c (CLUTTER_VECTOR_REGISTER_RISCV): New. (clutter_vector_registers): Guard clutter data with CLUTTER_VECTOR_REGISTER_COUNT. [CLUTTER_VECTOR_REGISTER_RISCV]: Detect RVV from hwflist; fill v0-v31 with vid.v generated values. -- Vector register width is not known at compile time on RISC-V, so registers are filled with generated values instead of loading from data buffer. Signed-off-by: Jussi Kivilinna --- tests/basic.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/tests/basic.c b/tests/basic.c index 00d6586d..d9664d3c 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -261,6 +261,10 @@ progress_handler (void *cb_data, const char *what, int printchar, defined(__ARM_NEON) # define CLUTTER_VECTOR_REGISTER_NEON 1 # define CLUTTER_VECTOR_REGISTER_COUNT 16 +#elif defined(HAVE_GCC_INLINE_ASM_RISCV_V) && \ + defined(__riscv) +# define CLUTTER_VECTOR_REGISTER_RISCV 1 +# undef CLUTTER_VECTOR_REGISTER_COUNT #endif @@ -297,6 +301,7 @@ clutter_vector_registers(void) #ifdef CLUTTER_VECTOR_REGISTER_COUNT static unsigned char data[CLUTTER_VECTOR_REGISTER_COUNT][16]; static int data_init; +#endif #if defined(CLUTTER_VECTOR_REGISTER_AARCH64) || \ defined(CLUTTER_VECTOR_REGISTER_NEON) static int init; @@ -347,13 +352,34 @@ clutter_vector_registers(void) if (!have_sse2) return; +#elif defined(CLUTTER_VECTOR_REGISTER_RISCV) + static int init; + static int have_rvv; + + if (!init) + { + char *string; + + string = gcry_get_config (0, "hwflist"); + if (string) + { + have_rvv = (strstr(string, "riscv-v:") != NULL); + xfree(string); + } + init = 1; + } + + if (!have_rvv) + return; #endif +#ifdef CLUTTER_VECTOR_REGISTER_COUNT if (!data_init) { prepare_vector_data(data); data_init = 1; } +#endif #if defined(CLUTTER_VECTOR_REGISTER_AMD64) if (0) @@ -565,9 +591,44 @@ clutter_vector_registers(void) : "r0", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15", "memory"); +#elif defined(CLUTTER_VECTOR_REGISTER_RISCV) + asm volatile(".option push;\n" + ".option arch, +v;\n" + "vsetvli t0, %0, e8, m4, ta, ma;\n" + "vid.v v0;\n" + "vid.v v4;\n" + "vid.v v8;\n" + "vid.v v12;\n" + "vid.v v16;\n" + "vid.v v20;\n" + "vid.v v24;\n" + "vid.v v28;\n" + "vadd.vx v4, v4, t0;\n" + "add t1, t0, t0;\n" + "vadd.vx v8, v8, t1;\n" + "add t1, t1, t0;\n" + "vadd.vx v12, v12, t1;\n" + "add t1, t1, t0;\n" + "vadd.vx v16, v16, t1;\n" + "add t1, t1, t0;\n" + "vadd.vx v20, v20, t1;\n" + "add t1, t1, t0;\n" + "add t0, t1, t0;\n" + "vadd.vx v24, v24, t1;\n" + "vadd.vx v28, v28, t0;\n" + ".option pop;\n" + : + : "r" (~0) + : "memory", "vl", "vtype", "t0", "t1", + "v0", "v1", "v2", "v3", + "v4", "v5", "v6", "v7", + "v8", "v9", "v10", "v11", + "v12", "v13", "v14", "v15", + "v16", "v17", "v18", "v19", + "v20", "v21", "v22", "v23", + "v24", "v25", "v26", "v27", + "v28", "v29", "v30", "v31"); #endif - -#endif /* CLUTTER_VECTOR_REGISTER_COUNT */ } -- 2.53.0 From jussi.kivilinna at iki.fi Tue Sep 8 13:46:40 2026 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 8 Sep 2026 14:46:40 +0300 Subject: [PATCH 4/6] tests/basic: add vector cluttering for ppc64 In-Reply-To: <20260908114642.1031933-1-jussi.kivilinna@iki.fi> References: <20260908114642.1031933-1-jussi.kivilinna@iki.fi> Message-ID: <20260908114642.1031933-4-jussi.kivilinna@iki.fi> * tests/basic.c (CLUTTER_VECTOR_REGISTER_PPC): New. (clutter_vector_registers) [CLUTTER_VECTOR_REGISTER_PPC]: Detect ppc-arch_2_07 from hwflist; load all 64 VSX registers. -- Signed-off-by: Jussi Kivilinna --- tests/basic.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/tests/basic.c b/tests/basic.c index d9664d3c..4c5f6038 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -265,6 +265,11 @@ progress_handler (void *cb_data, const char *what, int printchar, defined(__riscv) # define CLUTTER_VECTOR_REGISTER_RISCV 1 # undef CLUTTER_VECTOR_REGISTER_COUNT +#elif defined(HAVE_COMPATIBLE_CC_PPC_ALTIVEC) && \ + defined(HAVE_GCC_INLINE_ASM_PPC_ALTIVEC) && \ + defined(__POWER8_VECTOR__) +# define CLUTTER_VECTOR_REGISTER_PPC 1 +# define CLUTTER_VECTOR_REGISTER_COUNT 64 #endif @@ -371,6 +376,25 @@ clutter_vector_registers(void) if (!have_rvv) return; +#elif defined(CLUTTER_VECTOR_REGISTER_PPC) + static int init; + static int have_ppc_vec; + + if (!init) + { + char *string; + + string = gcry_get_config (0, "hwflist"); + if (string) + { + have_ppc_vec = (strstr(string, "ppc-arch_2_07:") != NULL); + xfree(string); + } + init = 1; + } + + if (!have_ppc_vec) + return; #endif #ifdef CLUTTER_VECTOR_REGISTER_COUNT @@ -628,6 +652,46 @@ clutter_vector_registers(void) "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"); +#elif defined(CLUTTER_VECTOR_REGISTER_PPC) + #define FILL_VECS_10(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) \ + asm volatile("lxvd2x "#v0", %y0\n" \ + "lxvd2x "#v1", %y1\n" \ + "lxvd2x "#v2", %y2\n" \ + "lxvd2x "#v3", %y3\n" \ + "lxvd2x "#v4", %y4\n" \ + "lxvd2x "#v5", %y5\n" \ + "lxvd2x "#v6", %y6\n" \ + "lxvd2x "#v7", %y7\n" \ + "lxvd2x "#v8", %y8\n" \ + "lxvd2x "#v9", %y9\n" \ + : \ + : "Z" (data[v0][0]), "Z" (data[v1][0]), \ + "Z" (data[v2][0]), "Z" (data[v3][0]), \ + "Z" (data[v4][0]), "Z" (data[v5][0]), \ + "Z" (data[v6][0]), "Z" (data[v7][0]), \ + "Z" (data[v8][0]), "Z" (data[v9][0]) \ + : "vs" #v0, "vs" #v1, "vs" #v2, "vs" #v3, \ + "vs" #v4, "vs" #v5, "vs" #v6, "vs" #v7, \ + "vs" #v8, "vs" #v9, "memory"); + #define FILL_VECS_4(v0, v1, v2, v3) \ + asm volatile("lxvd2x "#v0", %y0\n" \ + "lxvd2x "#v1", %y1\n" \ + "lxvd2x "#v2", %y2\n" \ + "lxvd2x "#v3", %y3\n" \ + : \ + : "Z" (data[v0][0]), "Z" (data[v1][0]), \ + "Z" (data[v2][0]), "Z" (data[v3][0]) \ + : "vs" #v0, "vs" #v1, "vs" #v2, "vs" #v3, \ + "memory"); + FILL_VECS_10(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); + FILL_VECS_10(10, 11, 12, 13, 14, 15, 16, 17, 18, 19); + FILL_VECS_10(20, 21, 22, 23, 24, 25, 26, 27, 28, 29); + FILL_VECS_10(30, 31, 32, 33, 34, 35, 36, 37, 38, 39); + FILL_VECS_10(40, 41, 42, 43, 44, 45, 46, 47, 48, 49); + FILL_VECS_10(50, 51, 52, 53, 54, 55, 56, 57, 58, 59); + FILL_VECS_4(60, 61, 62, 63); + #undef FILL_VECS_10 + #undef FILL_VECS_4 #endif } -- 2.53.0 From jussi.kivilinna at iki.fi Tue Sep 8 13:46:42 2026 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 8 Sep 2026 14:46:42 +0300 Subject: [PATCH 6/6] tests/basic: add MAC verify API test for bad tag length In-Reply-To: <20260908114642.1031933-1-jussi.kivilinna@iki.fi> References: <20260908114642.1031933-1-jussi.kivilinna@iki.fi> Message-ID: <20260908114642.1031933-6-jussi.kivilinna@iki.fi> * cipher/cipher-cmac.c (cmac_tag): Return GPG_ERR_INV_LENGTH for invalid tag length. * cipher/cipher-gcm.c (_gcry_cipher_gcm_tag): Likewise. * tests/basic.c (check_one_mac): Check that gcry_mac_verify rejects oversized tag length. -- CMAC returned GPG_ERR_INV_ARG and GCM returned GPG_ERR_CHECKSUM for wrong tag length, while HMAC and Poly1305 return GPG_ERR_INV_LENGTH. Signed-off-by: Jussi Kivilinna --- cipher/cipher-cmac.c | 4 +++- cipher/cipher-gcm.c | 5 +++-- tests/basic.c | 9 +++++++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/cipher/cipher-cmac.c b/cipher/cipher-cmac.c index c8bedc08..aab4b042 100644 --- a/cipher/cipher-cmac.c +++ b/cipher/cipher-cmac.c @@ -216,8 +216,10 @@ cmac_tag (gcry_cipher_hd_t c, gcry_cmac_context_t *ctx, { gcry_err_code_t ret; - if (!tag || taglen == 0 || taglen > c->spec->blocksize) + if (!tag) return GPG_ERR_INV_ARG; + if (taglen == 0 || taglen > c->spec->blocksize) + return GPG_ERR_INV_LENGTH; if (!ctx->tag) { diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c index e6a4df0f..ed04951b 100644 --- a/cipher/cipher-gcm.c +++ b/cipher/cipher-gcm.c @@ -1283,8 +1283,9 @@ _gcry_cipher_gcm_tag (gcry_cipher_hd_t c, { /* OUTBUFLEN gives the length of the user supplied tag in OUTBUF * and thus we need to compare its length first. */ - if (!is_tag_length_valid (outbuflen) - || !buf_eq_const (outbuf, c->u_mode.gcm.u_tag.tag, outbuflen)) + if (!is_tag_length_valid (outbuflen)) + return GPG_ERR_INV_LENGTH; + if (!buf_eq_const (outbuf, c->u_mode.gcm.u_tag.tag, outbuflen)) return GPG_ERR_CHECKSUM; } diff --git a/tests/basic.c b/tests/basic.c index 405f9861..7b8c73f3 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -16405,6 +16405,7 @@ check_one_mac (int algo, const char *data, int datalen, const char *key, int keylen, const char *iv, int ivlen, const char *expect, int test_buffering) { + unsigned char big_bad_tag[64 * 2]; gcry_mac_hd_t hd; unsigned char *p; unsigned int maclen; @@ -16558,6 +16559,14 @@ check_one_mac (int algo, const char *data, int datalen, if (err) fail("algo %d, mac gcry_mac_verify failed: %s\n", algo, gpg_strerror (err)); + clutter_vector_registers(); + err = gcry_mac_verify (hd, big_bad_tag, sizeof(big_bad_tag)); + if (gcry_err_code (err) != GPG_ERR_INV_LENGTH) + fail ("algo %d, gcry_mac_verify: oversized len %d not rejected: %s\n", algo, + (int)sizeof(big_bad_tag), gpg_strerror (err)); + if (err) + goto out; + macoutlen = maclen; clutter_vector_registers(); err = gcry_mac_read (hd, p, &macoutlen); -- 2.53.0 From jussi.kivilinna at iki.fi Tue Sep 8 13:46:37 2026 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 8 Sep 2026 14:46:37 +0300 Subject: [PATCH 1/6] cipher: remove unneeded vzeroupper from AVX implementations Message-ID: <20260908114642.1031933-1-jussi.kivilinna@iki.fi> * cipher/blake2b-amd64-avx2.S (_gcry_blake2b_transform_amd64_avx2): Remove vzeroupper from function entry. * cipher/blake2s-amd64-avx.S (_gcry_blake2s_transform_amd64_avx): Likewise. * cipher/camellia-aesni-avx-amd64.S (_gcry_camellia_aesni_avx_ctr_enc) (_gcry_camellia_aesni_avx_ecb_enc, _gcry_camellia_aesni_avx_ecb_dec) (_gcry_camellia_aesni_avx_cbc_dec, _gcry_camellia_aesni_avx_cfb_dec) (_gcry_camellia_aesni_avx_ocb_enc, _gcry_camellia_aesni_avx_ocb_dec) (_gcry_camellia_aesni_avx_ocb_auth, _gcry_camellia_aesni_avx_keygen): Likewise. * cipher/chacha20-amd64-avx2.S (_gcry_chacha20_amd64_avx2_blocks8) (_gcry_chacha20_poly1305_amd64_avx2_blocks8): Likewise. * cipher/serpent-avx2-amd64.S (_gcry_serpent_avx2_ctr_enc) (_gcry_serpent_avx2_cbc_dec, _gcry_serpent_avx2_cfb_dec) (_gcry_serpent_avx2_ocb_enc, _gcry_serpent_avx2_ocb_dec) (_gcry_serpent_avx2_ocb_auth): Likewise. * cipher/sha1-avx-amd64.S (_gcry_sha1_transform_amd64_avx): Likewise. * cipher/sha1-avx-bmi2-amd64.S (_gcry_sha1_transform_amd64_avx_bmi2): Likewise. * cipher/sha1-avx2-bmi2-amd64.S (_gcry_sha1_transform_amd64_avx2_bmi2): Likewise. * cipher/sha256-avx-amd64.S (_gcry_sha256_transform_amd64_avx): Likewise. * cipher/sha256-avx2-bmi2-amd64.S (_gcry_sha256_transform_amd64_avx2): Likewise. * cipher/sha512-avx-amd64.S (_gcry_sha512_transform_amd64_avx): Likewise. * cipher/sha512-avx2-bmi2-amd64.S (_gcry_sha512_transform_amd64_avx2): Likewise. * cipher/sm3-avx-bmi2-amd64.S (_gcry_sm3_transform_amd64_avx_bmi2): Likewise. * cipher/twofish-avx2-amd64.S (_gcry_twofish_avx2_blk16) (_gcry_twofish_avx2_ctr_enc, _gcry_twofish_avx2_cbc_dec) (_gcry_twofish_avx2_cfb_dec, _gcry_twofish_avx2_ocb_enc) (_gcry_twofish_avx2_ocb_dec, _gcry_twofish_avx2_ocb_auth): Likewise. * cipher/chacha20-amd64-avx512.S (_gcry_chacha20_amd64_avx512_blocks): Remove vzeroupper from register clearing. -- vzeroupper is needed only ahead of legacy SSE code, to avoid AVX-SSE transition penalty. These implementations use VEX/EVEX encoding throughout and clear upper register state with vzeroall before return. Measured on Tiger Lake, leaving upper register state dirty costs 1.54x for legacy SSE loop, but nothing for VEX encoded xmm/ymm code. Zen5 shows no penalty for either. Signed-off-by: Jussi Kivilinna --- cipher/blake2b-amd64-avx2.S | 2 -- cipher/blake2s-amd64-avx.S | 2 -- cipher/camellia-aesni-avx-amd64.S | 18 ------------------ cipher/chacha20-amd64-avx2.S | 4 ---- cipher/chacha20-amd64-avx512.S | 1 - cipher/serpent-avx2-amd64.S | 12 ------------ cipher/sha1-avx-amd64.S | 2 -- cipher/sha1-avx-bmi2-amd64.S | 2 -- cipher/sha1-avx2-bmi2-amd64.S | 2 -- cipher/sha256-avx-amd64.S | 1 - cipher/sha256-avx2-bmi2-amd64.S | 2 -- cipher/sha512-avx-amd64.S | 2 -- cipher/sha512-avx2-bmi2-amd64.S | 2 -- cipher/sm3-avx-bmi2-amd64.S | 2 -- cipher/twofish-avx2-amd64.S | 14 -------------- 15 files changed, 68 deletions(-) diff --git a/cipher/blake2b-amd64-avx2.S b/cipher/blake2b-amd64-avx2.S index 43c2cce1..02ee80a4 100644 --- a/cipher/blake2b-amd64-avx2.S +++ b/cipher/blake2b-amd64-avx2.S @@ -210,8 +210,6 @@ _gcry_blake2b_transform_amd64_avx2: */ CFI_STARTPROC(); - vzeroupper; - addq $128, (STATE_T + 0)(RSTATE); adcq $0, (STATE_T + 8)(RSTATE); diff --git a/cipher/blake2s-amd64-avx.S b/cipher/blake2s-amd64-avx.S index 44b82ab2..d2df67d6 100644 --- a/cipher/blake2s-amd64-avx.S +++ b/cipher/blake2s-amd64-avx.S @@ -196,8 +196,6 @@ _gcry_blake2s_transform_amd64_avx: */ CFI_STARTPROC(); - vzeroupper; - addq $64, (STATE_T + 0)(RSTATE); vmovdqa .Lshuf_ror16 rRIP, R16; diff --git a/cipher/camellia-aesni-avx-amd64.S b/cipher/camellia-aesni-avx-amd64.S index a29b9023..14e11d18 100644 --- a/cipher/camellia-aesni-avx-amd64.S +++ b/cipher/camellia-aesni-avx-amd64.S @@ -896,8 +896,6 @@ _gcry_camellia_aesni_avx_ctr_enc: movq %rsp, %rbp; CFI_DEF_CFA_REGISTER(%rbp); - vzeroupper; - cmpl $128, key_bitlength(CTX); movl $32, %r8d; movl $24, %eax; @@ -1053,8 +1051,6 @@ _gcry_camellia_aesni_avx_ecb_enc: movq %rsp, %rbp; CFI_DEF_CFA_REGISTER(%rbp); - vzeroupper; - cmpl $128, key_bitlength(CTX); movl $32, %r8d; movl $24, %eax; @@ -1099,8 +1095,6 @@ _gcry_camellia_aesni_avx_ecb_dec: movq %rsp, %rbp; CFI_DEF_CFA_REGISTER(%rbp); - vzeroupper; - cmpl $128, key_bitlength(CTX); movl $32, %r8d; movl $24, %eax; @@ -1146,8 +1140,6 @@ _gcry_camellia_aesni_avx_cbc_dec: movq %rsp, %rbp; CFI_DEF_CFA_REGISTER(%rbp); - vzeroupper; - movq %rcx, %r9; cmpl $128, key_bitlength(CTX); @@ -1219,8 +1211,6 @@ _gcry_camellia_aesni_avx_cfb_dec: movq %rsp, %rbp; CFI_DEF_CFA_REGISTER(%rbp); - vzeroupper; - cmpl $128, key_bitlength(CTX); movl $32, %r8d; movl $24, %eax; @@ -1303,8 +1293,6 @@ _gcry_camellia_aesni_avx_ocb_enc: movq %rsp, %rbp; CFI_DEF_CFA_REGISTER(%rbp); - vzeroupper; - subq $(16 * 16 + 4 * 8), %rsp; andq $~31, %rsp; movq %rsp, %rax; @@ -1455,8 +1443,6 @@ _gcry_camellia_aesni_avx_ocb_dec: movq %rsp, %rbp; CFI_DEF_CFA_REGISTER(%rbp); - vzeroupper; - subq $(16 * 16 + 4 * 8), %rsp; andq $~31, %rsp; movq %rsp, %rax; @@ -1625,8 +1611,6 @@ _gcry_camellia_aesni_avx_ocb_auth: movq %rsp, %rbp; CFI_DEF_CFA_REGISTER(%rbp); - vzeroupper; - subq $(16 * 16 + 4 * 8), %rsp; andq $~31, %rsp; movq %rsp, %rax; @@ -2720,8 +2704,6 @@ _gcry_camellia_aesni_avx_keygen: */ CFI_STARTPROC(); - vzeroupper; - vmovdqu (%rsi), %xmm0; cmpl $24, %edx; jb __camellia_avx_setup128; diff --git a/cipher/chacha20-amd64-avx2.S b/cipher/chacha20-amd64-avx2.S index 54e2ffab..b2311ab5 100644 --- a/cipher/chacha20-amd64-avx2.S +++ b/cipher/chacha20-amd64-avx2.S @@ -184,8 +184,6 @@ _gcry_chacha20_amd64_avx2_blocks8: */ CFI_STARTPROC(); - vzeroupper; - pushq %rbp; CFI_PUSH(%rbp); movq %rsp, %rbp; @@ -356,8 +354,6 @@ _gcry_chacha20_poly1305_amd64_avx2_blocks8: movq %rsp, %rbp; CFI_DEF_CFA_REGISTER(%rbp); - vzeroupper; - subq $(9 * 8) + STACK_MAX + 32, %rsp; andq $~31, %rsp; diff --git a/cipher/chacha20-amd64-avx512.S b/cipher/chacha20-amd64-avx512.S index 2d140815..6d421bf2 100644 --- a/cipher/chacha20-amd64-avx512.S +++ b/cipher/chacha20-amd64-avx512.S @@ -625,7 +625,6 @@ _gcry_chacha20_amd64_avx512_blocks: .Lskip4v: /* clear AVX512 registers */ kxorq %k2, %k2, %k2; - vzeroupper; clear_zmm16_zmm31(); .align 16 diff --git a/cipher/serpent-avx2-amd64.S b/cipher/serpent-avx2-amd64.S index a419eb29..9ec31f17 100644 --- a/cipher/serpent-avx2-amd64.S +++ b/cipher/serpent-avx2-amd64.S @@ -645,8 +645,6 @@ _gcry_serpent_avx2_ctr_enc: */ CFI_STARTPROC(); - vzeroupper; - vbroadcasti128 .Lbswap128_mask rRIP, RTMP3; vpcmpeqd RNOT, RNOT, RNOT; vpsrldq $14, RNOT, RNOT; /* ab: -1:0 ; cd: -1:0 */ @@ -718,8 +716,6 @@ _gcry_serpent_avx2_cbc_dec: */ CFI_STARTPROC(); - vzeroupper; - vmovdqu (0 * 32)(%rdx), RA0; vmovdqu (1 * 32)(%rdx), RA1; vmovdqu (2 * 32)(%rdx), RA2; @@ -771,8 +767,6 @@ _gcry_serpent_avx2_cfb_dec: */ CFI_STARTPROC(); - vzeroupper; - /* Load input */ vmovdqu (%rcx), RNOTx; vinserti128 $1, (%rdx), RNOT, RA0; @@ -829,8 +823,6 @@ _gcry_serpent_avx2_ocb_enc: */ CFI_STARTPROC(); - vzeroupper; - subq $(4 * 8), %rsp; CFI_ADJUST_CFA_OFFSET(4 * 8); @@ -943,8 +935,6 @@ _gcry_serpent_avx2_ocb_dec: */ CFI_STARTPROC(); - vzeroupper; - subq $(4 * 8), %rsp; CFI_ADJUST_CFA_OFFSET(4 * 8); @@ -1066,8 +1056,6 @@ _gcry_serpent_avx2_ocb_auth: */ CFI_STARTPROC(); - vzeroupper; - subq $(4 * 8), %rsp; CFI_ADJUST_CFA_OFFSET(4 * 8); diff --git a/cipher/sha1-avx-amd64.S b/cipher/sha1-avx-amd64.S index e5e55684..ca81506c 100644 --- a/cipher/sha1-avx-amd64.S +++ b/cipher/sha1-avx-amd64.S @@ -222,8 +222,6 @@ _gcry_sha1_transform_amd64_avx: cmpq $0, %rdx; jz .Lret; - vzeroupper; - movq %rdx, RNBLKS; movq %rdi, RSTATE; movq %rsi, RDATA; diff --git a/cipher/sha1-avx-bmi2-amd64.S b/cipher/sha1-avx-bmi2-amd64.S index 16a01bfd..85ba22b0 100644 --- a/cipher/sha1-avx-bmi2-amd64.S +++ b/cipher/sha1-avx-bmi2-amd64.S @@ -222,8 +222,6 @@ _gcry_sha1_transform_amd64_avx_bmi2: cmpq $0, %rdx; jz .Lret; - vzeroupper; - movq %rdx, RNBLKS; movq %rdi, RSTATE; movq %rsi, RDATA; diff --git a/cipher/sha1-avx2-bmi2-amd64.S b/cipher/sha1-avx2-bmi2-amd64.S index 06ff92f0..190b9731 100644 --- a/cipher/sha1-avx2-bmi2-amd64.S +++ b/cipher/sha1-avx2-bmi2-amd64.S @@ -224,8 +224,6 @@ _gcry_sha1_transform_amd64_avx2_bmi2: */ CFI_STARTPROC(); - vzeroupper; - movq %rdx, RNBLKS; movq %rdi, RSTATE; movq %rsi, RDATA; diff --git a/cipher/sha256-avx-amd64.S b/cipher/sha256-avx-amd64.S index 8cfd0880..9c15f481 100644 --- a/cipher/sha256-avx-amd64.S +++ b/cipher/sha256-avx-amd64.S @@ -345,7 +345,6 @@ ELF(.type _gcry_sha256_transform_amd64_avx, at function;) .align 16 _gcry_sha256_transform_amd64_avx: CFI_STARTPROC() - vzeroupper push rbx CFI_PUSH(rbx) diff --git a/cipher/sha256-avx2-bmi2-amd64.S b/cipher/sha256-avx2-bmi2-amd64.S index e2a5454c..ec99e57f 100644 --- a/cipher/sha256-avx2-bmi2-amd64.S +++ b/cipher/sha256-avx2-bmi2-amd64.S @@ -268,8 +268,6 @@ _gcry_sha256_transform_amd64_avx2: push r15 CFI_PUSH(r15) - vzeroupper - vmovdqa BYTE_FLIP_MASK, [.LPSHUFFLE_BYTE_FLIP_MASK ADD_RIP] vmovdqa SHUF_00BA, [.L_SHUF_00BA ADD_RIP] vmovdqa SHUF_DC00, [.L_SHUF_DC00 ADD_RIP] diff --git a/cipher/sha512-avx-amd64.S b/cipher/sha512-avx-amd64.S index 1bd38060..22b1058e 100644 --- a/cipher/sha512-avx-amd64.S +++ b/cipher/sha512-avx-amd64.S @@ -254,8 +254,6 @@ _gcry_sha512_transform_amd64_avx: cmp msglen, 0 je .Lnowork - vzeroupper - /* Allocate Stack Space */ sub rsp, frame_size CFI_ADJUST_CFA_OFFSET(frame_size); diff --git a/cipher/sha512-avx2-bmi2-amd64.S b/cipher/sha512-avx2-bmi2-amd64.S index 7b60bf1d..c2275bb5 100644 --- a/cipher/sha512-avx2-bmi2-amd64.S +++ b/cipher/sha512-avx2-bmi2-amd64.S @@ -282,8 +282,6 @@ _gcry_sha512_transform_amd64_avx2: cmp rdx, 0 je .Lnowork - vzeroupper - /* Allocate Stack Space */ mov rax, rsp CFI_DEF_CFA_REGISTER(rax); diff --git a/cipher/sm3-avx-bmi2-amd64.S b/cipher/sm3-avx-bmi2-amd64.S index ef923165..9252e279 100644 --- a/cipher/sm3-avx-bmi2-amd64.S +++ b/cipher/sm3-avx-bmi2-amd64.S @@ -354,8 +354,6 @@ _gcry_sm3_transform_amd64_avx_bmi2: */ CFI_STARTPROC(); - vzeroupper; - pushq %rbp; CFI_PUSH(%rbp); movq %rsp, %rbp; diff --git a/cipher/twofish-avx2-amd64.S b/cipher/twofish-avx2-amd64.S index 72a39d17..c448dfae 100644 --- a/cipher/twofish-avx2-amd64.S +++ b/cipher/twofish-avx2-amd64.S @@ -519,8 +519,6 @@ _gcry_twofish_avx2_blk16: */ CFI_STARTPROC(); - vzeroupper; - vmovdqu (0 * 32)(%rdx), RA0; vmovdqu (1 * 32)(%rdx), RB0; vmovdqu (2 * 32)(%rdx), RC0; @@ -565,8 +563,6 @@ _gcry_twofish_avx2_ctr_enc: */ CFI_STARTPROC(); - vzeroupper; - vbroadcasti128 .Lbswap128_mask rRIP, RTMP3; vpcmpeqd RNOT, RNOT, RNOT; vpsrldq $14, RNOT, RNOT; /* ab: -1:0 ; cd: -1:0 */ @@ -638,8 +634,6 @@ _gcry_twofish_avx2_cbc_dec: */ CFI_STARTPROC(); - vzeroupper; - vmovdqu (0 * 32)(%rdx), RA0; vmovdqu (1 * 32)(%rdx), RB0; vmovdqu (2 * 32)(%rdx), RC0; @@ -691,8 +685,6 @@ _gcry_twofish_avx2_cfb_dec: */ CFI_STARTPROC(); - vzeroupper; - /* Load input */ vmovdqu (%rcx), RNOTx; vinserti128 $1, (%rdx), RNOT, RA0; @@ -749,8 +741,6 @@ _gcry_twofish_avx2_ocb_enc: */ CFI_STARTPROC(); - vzeroupper; - subq $(4 * 8), %rsp; CFI_ADJUST_CFA_OFFSET(4 * 8); @@ -863,8 +853,6 @@ _gcry_twofish_avx2_ocb_dec: */ CFI_STARTPROC(); - vzeroupper; - subq $(4 * 8), %rsp; CFI_ADJUST_CFA_OFFSET(4 * 8); @@ -987,8 +975,6 @@ _gcry_twofish_avx2_ocb_auth: */ CFI_STARTPROC(); - vzeroupper; - subq $(4 * 8), %rsp; CFI_ADJUST_CFA_OFFSET(4 * 8); -- 2.53.0 From jonathan.plata at lightshipsec.com Wed Sep 9 16:12:25 2026 From: jonathan.plata at lightshipsec.com (Jonathan Plata) Date: Wed, 9 Sep 2026 14:12:25 +0000 Subject: PATCH: Padding bug in cSHAKE-128/256 Message-ID: Hello! cshake_input_s()'s padlen computation, padlen = ctx->blocksize - (len_written % ctx->blocksize); does not handle the case where len_written is already an exact multiple of ctx->blocksize: the modulo evaluates to 0, so padlen comes out as ctx->blocksize (a full block) instead of 0. SP 800-185's bytepad (sec. 2.3.3) specifies padding with zero bytes only until the total length becomes a multiple of the rate -- when it already is, no padding bytes should be added at all. The bug results in a full extra block of zero bytes added to the Keccak sponge, producing a wrong cSHAKE digest whenever the encoded N (function-name string) + S (customization string) length lands exactly on a rate boundary (168 bytes for cSHAKE128, 136 for cSHAKE256). Concretely: cSHAKE128 with an empty N and a 161-byte S (2-byte rate prefix + 2-byte encode_string(empty N) + 3-byte encode_string(S) length-prefix + 161 == 168 == the cSHAKE128 rate) triggers it; cSHAKE256 with an empty N and a 129-byte S hits the same condition against its 136-byte rate. Found via NIST ACVP cSHAKE-128/256 conformance vectors: a fixture covering random S lengths reliably produces a wrong digest at S = 161 (cSHAKE128) and S = 129 (cSHAKE256), and only those lengths (adjacent lengths pass), consistent with this exact rate-boundary condition. Confirmed against libgcrypt 1.11.2 and 1.12.0 (unchanged between the two). Signed-off-by: Jonathan Plata --- cipher/keccak.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cipher/keccak.c b/cipher/keccak.c index a0ba1fbb..1351da16 100644 --- a/cipher/keccak.c +++ b/cipher/keccak.c @@ -1694,7 +1694,7 @@ cshake_input_s (KECCAK_CONTEXT *ctx, const void *s, unsigned int s_len, keccak_write (ctx, s, s_len); len_written += buf[0] + 1 + s_len; - padlen = ctx->blocksize - (len_written % ctx->blocksize); + padlen = (ctx->blocksize - (len_written % ctx->blocksize)) % ctx->blocksize; memset (buf, 0, padlen); keccak_write (ctx, buf, padlen); } -- 2.34.1 [cid:image001.png at 01DD4040.AC77CD40] Jonathan Plata | Software Developer Lightship Security, Inc. Tel: 512-362-6594 https://lightshipsec.com This email and attachments are confidential and intended solely for the use of the individual or entity to whom they are addressed. If you are not the named addressee, you may not disseminate, distribute or copy this email. Please notify the sender immediately if you have received this email in error and delete it from your system. -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image001.png Type: image/png Size: 4162 bytes Desc: image001.png URL: From gniibe at fsij.org Thu Sep 10 07:26:04 2026 From: gniibe at fsij.org (NIIBE Yutaka) Date: Thu, 10 Sep 2026 14:26:04 +0900 Subject: PATCH: Padding bug in cSHAKE-128/256 In-Reply-To: References: Message-ID: <87ecf1brtf.fsf@haruna.fsij.org> Hello, Jonathan Plata wrote: > cshake_input_s()'s padlen computation, > > padlen = ctx->blocksize - (len_written % ctx->blocksize); Thank you for your report. > --- a/cipher/keccak.c > +++ b/cipher/keccak.c > @@ -1694,7 +1694,7 @@ cshake_input_s (KECCAK_CONTEXT *ctx, const void *s, unsigned int s_len, > keccak_write (ctx, s, s_len); > > len_written += buf[0] + 1 + s_len; > - padlen = ctx->blocksize - (len_written % ctx->blocksize); > + padlen = (ctx->blocksize - (len_written % ctx->blocksize)) % ctx->blocksize; > memset (buf, 0, padlen); > keccak_write (ctx, buf, padlen); > } While the expression is correct, I'm not sure if multiple %-operations can be optimized well by compiler. Just in case, I think that it's better to use a single %-operation in the expression. Attached is a patch with a single %-operation. If no objections, I will push this to 1.11, 1.12 and master. -- -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-cipher-keccak-Fix-padding-in-cSHAKE.patch Type: text/x-diff Size: 1529 bytes Desc: not available URL: