[PATCH] x86: refine UD<n> kind-of-insns
Jan Beulich
jbeulich@suse.com
Fri May 16 10:10:05 GMT 2025
While documentation of these continues to be lacking sufficient detail,
it is becoming increasingly clear that in 66f1eba0b7e8 ("x86: correct
UDn") I went too far with requiring operands, to populate a ModR/M byte.
AMD hardware appears to always behave as indicated as "may" in PM 3.36,
which for all practical purposes means there's no ModR/M byte. The SDM
(rev 087) indicates that such behavior can occur on older hardware for
UD0. Re-add an operand-less UD1 form (as well as its UD2B alias), while
newly adding such a form also for UD0. Because of the ambiguity, there's
no good/easy way of handling both possibilities in the disassembler,
which hence remains unaltered.
Further, from all information I'm able to gather, the 0F opcode space
was only introduced with the i286; bump the minimal hardware requirement
for all UD<n> accordingly.
--- a/gas/testsuite/gas/i386/arch-4.d
+++ b/gas/testsuite/gas/i386/arch-4.d
@@ -6,7 +6,9 @@
Disassembly of section .text:
0+ <.text>:
+[ ]*[a-f0-9]+: 0f ff cc [ ]*ud0 %esp,%ecx
[ ]*[a-f0-9]+: 0f ff 07 [ ]*ud0 \(%edi\),%eax
+[ ]*[a-f0-9]+: 0f b9 cc [ ]*ud1 %esp,%ecx
[ ]*[a-f0-9]+: 0f b9 07 [ ]*ud1 \(%edi\),%eax
[ ]*[a-f0-9]+: 0f 0b ud2
[ ]*[a-f0-9]+: 0f 0b ud2
--- a/gas/testsuite/gas/i386/arch-4.s
+++ b/gas/testsuite/gas/i386/arch-4.s
@@ -1,5 +1,9 @@
.text
+ ud0
+ int3
ud0 (%edi),%eax
+ ud1
+ int3
ud1 (%edi),%eax
ud2
ud2a
--- a/opcodes/i386-opc.tbl
+++ b/opcodes/i386-opc.tbl
@@ -981,15 +981,18 @@ fxrstor, 0xfae/1, FXSR, Modrm|No_bSuf|No
fxrstor64, 0xfae/1, FXSR&x64, Modrm|NoSuf|Size64, { Unspecified|BaseIndex }
rdpmc, 0xf33, i686, NoSuf, {}
// official undefined instr.
-ud2, 0xf0b, i186, NoSuf, {}
+ud2, 0xf0b, i286, NoSuf, {}
// alias for ud2
-ud2a, 0xf0b, i186, NoSuf, {}
-// 2nd. official undefined instr.
-ud1, 0xfb9, i186, Modrm|CheckOperandSize|No_bSuf|No_sSuf, { Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
+ud2a, 0xf0b, i286, NoSuf, {}
+// 2nd official undefined instr (older AMD CPUs don't take a ModR/M byte)
+ud1, 0xfb9, i286, /*Amd|*/NoSuf, {}
+ud1, 0xfb9, i286, Modrm|CheckOperandSize|No_bSuf|No_sSuf, { Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
// alias for ud1
-ud2b, 0xfb9, i186, Modrm|CheckOperandSize|No_bSuf|No_sSuf, { Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
+ud2b, 0xfb9, i286, /*Amd|*/NoSuf, {}
+ud2b, 0xfb9, i286, Modrm|CheckOperandSize|No_bSuf|No_sSuf, { Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
// 3rd official undefined instr (older CPUs don't take a ModR/M byte)
-ud0, 0xfff, i186, Modrm|CheckOperandSize|No_bSuf|No_sSuf, { Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
+ud0, 0xfff, i286, NoSuf, {}
+ud0, 0xfff, i286, Modrm|CheckOperandSize|No_bSuf|No_sSuf, { Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
// 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
More information about the Binutils
mailing list