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

H. Peter Anvin hpa@zytor.com
Mon Aug 11 17:48:40 GMT 2025


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



More information about the Binutils mailing list