[PATCH 1/1] x86: add "udb" opcode (permanent official #UD in 64-bit mode)

H.J. Lu hjl.tools@gmail.com
Mon Aug 11 18:31:07 GMT 2025


On Mon, Aug 11, 2025 at 10:48 AM H. Peter Anvin <hpa@zytor.com> wrote:
>
> The opcode D6 has been officially reserved as a single-byte permanent
> undefined (#UD) opcode in 64-bit mode with the mnemonic UDB.  This is
> already the behavior of all known 64-bit implementations; this is thus
> merely an official statement of forward compatibility and the
> assignment of a mnemonic.
>
> This will be documented in the next version of the Intel Software
> Developer's Manual; in the meantime I DO speak officially for Intel on
> this issue.
>
> The x86 Advisory Council has ratified this decision, and so it is
> expected to be honored across vendors, but I obviously cannot make any
> official statement on any other vendor's behalf.
>
> I am covered by the Intel-FSF copyright assignment for binutils.
>
> Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
> ---
>  gas/testsuite/gas/i386/x86-64-opcode.d | 1 +
>  gas/testsuite/gas/i386/x86-64-opcode.s | 1 +
>  opcodes/i386-dis.c                     | 9 ++++++++-
>  opcodes/i386-opc.tbl                   | 2 ++
>  4 files changed, 12 insertions(+), 1 deletion(-)
>
> diff --git a/gas/testsuite/gas/i386/x86-64-opcode.d b/gas/testsuite/gas/i386/x86-64-opcode.d
> index 1b8a9fa9014c..0d7cbd2f17ba 100644
> --- a/gas/testsuite/gas/i386/x86-64-opcode.d
> +++ b/gas/testsuite/gas/i386/x86-64-opcode.d
> @@ -328,6 +328,7 @@ Disassembly of section .text:
>  [      ]*[a-f0-9]+:    f1                      int1
>  [      ]*[a-f0-9]+:    cc                      int3
>  [      ]*[a-f0-9]+:    cd 90                   int    \$0x90
> +[      ]*[a-f0-9]+:    d6                      udb
>  [      ]*[a-f0-9]+:    f6 c9 01                test   \$(0x)?0*1,%cl
>  [      ]*[a-f0-9]+:    66 f7 c9 02 00          test   \$(0x)?0*2,%cx
>  [      ]*[a-f0-9]+:    f7 c9 04 00 00 00       test   \$(0x)?0*4,%ecx
> diff --git a/gas/testsuite/gas/i386/x86-64-opcode.s b/gas/testsuite/gas/i386/x86-64-opcode.s
> index 220998c86535..95559d7d15e5 100644
> --- a/gas/testsuite/gas/i386/x86-64-opcode.s
> +++ b/gas/testsuite/gas/i386/x86-64-opcode.s
> @@ -457,6 +457,7 @@
>         int1
>         int3
>         int    $0x90
> +       udb
>
>         .insn 0xf6/1, $1, %cl
>         .insn 0xf7/1, $2{:u16}, %cx
> diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c
> index 703f09dbb774..e6637ab26f71 100644
> --- a/opcodes/i386-dis.c
> +++ b/opcodes/i386-dis.c
> @@ -1325,6 +1325,7 @@ enum
>    X86_64_CE,
>    X86_64_D4,
>    X86_64_D5,
> +  X86_64_D6,
>    X86_64_E8,
>    X86_64_E9,
>    X86_64_EA,
> @@ -2194,7 +2195,7 @@ static const struct dis386 dis386[] = {
>    { REG_TABLE (REG_D3) },
>    { X86_64_TABLE (X86_64_D4) },
>    { X86_64_TABLE (X86_64_D5) },
> -  { Bad_Opcode },
> +  { X86_64_TABLE (X86_64_D6) },
>    { "xlat",            { DSBX }, 0 },
>    /* d8 */
>    { FLOAT },
> @@ -4511,6 +4512,12 @@ static const struct dis386 x86_64_table[][2] = {
>      { "aad", { Ib }, 0 },
>    },
>
> +  /* X86_64_D6 */
> +  {
> +    { Bad_Opcode },
> +    { "udb", { XX }, 0 },
> +  },
> +
>    /* X86_64_E8 */
>    {
>      { "callP",         { Jv, BND }, 0 },
> diff --git a/opcodes/i386-opc.tbl b/opcodes/i386-opc.tbl
> index 6eadc2ebf734..b03fbc3325f5 100644
> --- a/opcodes/i386-opc.tbl
> +++ b/opcodes/i386-opc.tbl
> @@ -993,6 +993,8 @@ ud2b, 0xfb9, i286, Modrm|CheckOperandSize|No_bSuf|No_sSuf, { Reg16|Reg32|Reg64|U
>  // 3rd official undefined instr (older CPUs don't take a ModR/M byte)
>  ud0, 0xfff, i286, NoSuf, {}
>  ud0, 0xfff, i286, Modrm|CheckOperandSize|No_bSuf|No_sSuf, { Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
> +// 4th official undefined instruction (single byte in 64-bit mode only)
> +udb, 0xd6, x64, NoSuf, {}
>
>  // C (commutative) isn't quite correct here on its own; the condition also
>  // needs inverting when source operands are swapped in order to convert to
> --
> 2.50.1
>

OK.

Thanks.

-- 
H.J.


More information about the Binutils mailing list