[PATCH v4] Add AMD znver6 processor support

Jan Beulich jbeulich@suse.com
Mon Nov 24 10:00:08 GMT 2025


On 21.11.2025 11:33, Umesh Kalvakuntla wrote:
> commit 11f297857a76ca7f198c4a15e99882bd40e7c948
> Author: Umesh Kalvakuntla <umesh.kalvakuntla@amd.com>
> Date:   Fri Nov 14 19:27:21 2025 +0530
> 
>     Add AMD znver6 processor support
>     
>     In --help option, adds znver6 to the list of CPUs under -march.
>     
>     Please find the ISA descriptions for AVX512_BMM instructions below.
>     
>     AVX512 Bit Manipulation Instructions
>     ====================================
>     The AVX512BMM instructions include Bit Matrix Multiply and Bit Reversal
>     operations.
>     
>     CPUID
>     -----
>     Support is indicated by the new CPUID 8000_0021, EAX bit 23, labeled AVX512_BMM.
>     
>     Encoding
>     --------
>     VBMACOR16x16x16
>     EVEX.256.NP.MAP6.W0 80 /r VBMACOR16x16x16  ymm1, ymm2, ymm3/m256
>     EVEX.512.NP.MAP6.W0 80 /r VBMACOR16x16x16  zmm1, zmm2, zmm3/m512
>     
>     VBMACXOR16x16x16
>     EVEX.256.NP.MAP6.W1 80 /r VBMACXOR16x16x16  ymm1, ymm2, ymm3/m256
>     EVEX.512.NP.MAP6.W1 80 /r VBMACXOR16x16x16  zmm1, zmm2, zmm3/m512
>     
>     DESCRIPTION
>     -----------
>     256 BIT VERSIONS
>     ----------------
>     16x16 non-transposed fused BMM-accumulate (BMAC) with OR/XOR reduction.
>     A ymm register holds a 16x16 bit matrix. The third source matrix for
>     accumulation is in ymm1.
>     
>     512 BIT VERSIONS
>     ----------------
>     2 parallel 16x16 non-transposed fused BMM-accumulate (BMAC) with OR/XOR
>     reduction.
>     Each 256-bit chunk of a zmm register holds a 16x16 bit matrix. The third source
>     matrices for accumulation are in zmm1.
>     
>     VBITREVB
>     --------
>     EVEX.128.NP.MAP6.W0 81 /r VBITREVB  xmm1{k1}{z}, xmm2/m128
>     EVEX.256.NP.MAP6.W0 81 /r VBITREVB  ymm1{k1}{z}, ymm2/m256
>     EVEX.512.NP.MAP6.W0 81 /r VBITREVB  zmm1{k1}{z}, zmm2/m512
>     
>     DESCRIPTION
>     -----------
>     Bit reversal within a byte boundary. Only applied to input bytes where the
>     corresponding mask bit is set; otherwise, bytes are left untouched or zeroed out
>     if zero masking is indicated.
>     
>     gas/ChangeLog:
>     
>             * NEWS: Add znver6 ARCH.
>             * config/tc-i386.c: Add znver6 ARCH, avx512_bmm SUBARCH.
>             * doc/c-i386.texi: Likewise.
>             * testsuite/gas/i386/i386.exp: Add znver6 test cases.
>             * testsuite/gas/i386/x86-64.exp: Add znver6 test cases.
>             * testsuite/gas/i386/arch-16-znver6.d: New test.
>             * testsuite/gas/i386/arch-16.d: New test.
>             * testsuite/gas/i386/arch-16.s: New test.
>             * testsuite/gas/i386/avx512_bmm.d: New test.
>             * testsuite/gas/i386/avx512_bmm.s: New test.
>             * testsuite/gas/i386/avx512_bmm_vl-inval.l: New test.
>             * testsuite/gas/i386/avx512_bmm_vl-inval.s: New test.
>             * testsuite/gas/i386/avx512_bmm_vl.d: New test.
>             * testsuite/gas/i386/avx512_bmm_vl.s: New test.
>             * testsuite/gas/i386/x86-64-arch-6-znver6.d: New test.
>             * testsuite/gas/i386/x86-64-arch-6.d: New test.
>             * testsuite/gas/i386/x86-64-arch-6.s: New test.
>             * testsuite/gas/i386/x86-64-avx512_bmm-bad.d: New test.
>             * testsuite/gas/i386/x86-64-avx512_bmm-bad.s: New test.
>             * testsuite/gas/i386/x86-64-avx512_bmm.d: New test.
>             * testsuite/gas/i386/x86-64-avx512_bmm.s: New test.
>             * testsuite/gas/i386/x86-64-avx512_bmm_vl-inval.l: New test.
>             * testsuite/gas/i386/x86-64-avx512_bmm_vl-inval.s: New test.
>             * testsuite/gas/i386/x86-64-avx512_bmm_vl.d: New test.
>             * testsuite/gas/i386/x86-64-avx512_bmm_vl.s: New test.
>     
>     opcodes/ChangeLog:
>     
>             * i386-dis-evex-len.h: Likewise.
>             * i386-dis-evex-w.h: Likewise.
>             * i386-dis-evex.h: Likewise.
>             * i386-dis.c: Add EVEX_LEN_MAP6_80, EVEX_W_MAP6_80_L_n, EVEX_W_MAP6_81.
>             * i386-gen.c: Likewise.
>             * i386-init.h: Re-generated.
>             * i386-mnem.h: Re-generated.
>             * i386-opc.h (enum i386_cpu): Add CpuAVX512_BMM.
>             (i386_cpu_flags): Add cpuvavx512_bmm.
>             * i386-opc.tbl: Add vbmacor16x16x16, vbmacxor16x16x16, vbitrevb.
>             * i386-tbl.h: Re-generated.

Looks largely okay to me now.

Assuming this will (eventually) need applying on your behalf, can we get a
git-am-able form of the patch, though? The above has extra indentation,
which I'm not sure "git am" would properly strip.

Two further remarks:

> --- /dev/null
> +++ b/gas/testsuite/gas/i386/x86-64-avx512_bmm-bad.d
> @@ -0,0 +1,16 @@
> +#objdump: -dw
> +#name: x86_64 AVX512_BMM BAD insn
> +#source: x86-64-avx512_bmm-bad.s
> +
> +.*: +file format .*
> +
> +Disassembly of section \.text:
> +
> +[0-9a-f]+ <\.text>:
> +[\s]*[a-f0-9]+:[\s]*62 f6 6c 08 80[\s]*\(bad\)
> +[\s]*[a-f0-9]+:[\s]*d9 62 f6[\s]*fldenv -0xa\(%rdx\)
> +[\s]*[a-f0-9]+:[\s]*ec[\s]*in     \(%dx\),%al
> +[\s]*[a-f0-9]+:[\s]*08[\s]*\.byte 0x8
> +[\s]*[a-f0-9]+:[\s]*80[\s]*\.byte 0x80
> +[\s]*[a-f0-9]+:[\s]*d9[\s]*\.byte 0xd9
> +#pass

This only really tests ...

> --- /dev/null
> +++ b/gas/testsuite/gas/i386/x86-64-avx512_bmm-bad.s
> @@ -0,0 +1,6 @@
> +.text
> +	#vbmacor16x16x16 %xmm1, %xmm2, %xmm3
> +	.insn EVEX.128.NP.M6.W0 0x80, %xmm1, %xmm2, %xmm3

... this, but not ...

> +	#vbmacxor16x16x16 %xmm1, %xmm2, %xmm3
> +	.insn EVEX.128.NP.M6.W1 0x80, %xmm1, %xmm2, %xmm3

... this. You will want to alter operands such that the ModR/M byte ends up as a
single-byte opcode, such that the disassembler will properly recognize the insn
boundary ahead of the 2nd insn under test. Further, the comments don't indicate
what's being checked (i.e. what is deliberately wrong). Finally, please also
indent .text by a tab. No directive should start in the very first column.

> --- a/opcodes/i386-dis-evex-len.h
> +++ b/opcodes/i386-dis-evex-len.h
> @@ -193,4 +193,11 @@ static const struct dis386 evex_len_table[][3] = {
>    {
>      { PREFIX_TABLE (PREFIX_EVEX_MAP5_7E_L_0) },
>    },
> +
> +  /* EVEX_LEN_MAP6_80 */
> +  {
> +    { Bad_Opcode },
> +    { VEX_W_TABLE (EVEX_W_MAP6_80_L_n) },
> +    { VEX_W_TABLE (EVEX_W_MAP6_80_L_n) },
> +  },
>  };

Using ..._L_n entries isn't very nice: What if L'L=0 also gains a (different)
meaning? Then whether the _L_n also applies to it would end up ambiguous. IOW
it would be better ...

> --- a/opcodes/i386-dis-evex.h
> +++ b/opcodes/i386-dis-evex.h
> @@ -1601,8 +1601,8 @@ static const struct dis386 evex_table[][256] = {
>      { Bad_Opcode },
>      { Bad_Opcode },
>      /* 80 */
> -    { Bad_Opcode },
> -    { Bad_Opcode },
> +    { EVEX_LEN_TABLE (EVEX_LEN_MAP6_80) },
> +    { VEX_W_TABLE (EVEX_W_MAP6_81) },

... to decode EVEX.W first in both cases. But that's benign for now, so I
won't insist on such a change.

Jan


More information about the Binutils mailing list