x86: Support BHI_CTRL instruction
Checks
| Context |
Check |
Description |
| linaro-tcwg-bot/tcwg_binutils_build--master-arm |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 |
success
|
Test passed
|
| linaro-tcwg-bot/tcwg_binutils_check--master-arm |
success
|
Test passed
|
Commit Message
Hi all,
The following patch aimed to add BHI_CTRL. The ISA has been published in a
separate tech paper last year and still missing its assembler/disassembler
support.
One tricky thing is that it utilized part of the nops encoding and we need
to keep the same behavior for the not touched one, i.e., repz nop. That is
why I added a Fixup for now since I did not have a better idea for that.
Discussions are welcomed on this.
Ok for trunk?
Thx,
Haochen
---
BHI_CTRL is an ISA with only one instruction ibhf. The following tech paper
is published in May, 2025:
https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/technical-documentation/branch-history-injection.html#ibhf
As shown in the paper, The encoding is F3 48 0F 1E F8.
I added a Fixup for disassembler since we need to keep the same behavior
for "repz nop" encodings.
gas/ChangeLog:
* NEWS: Mention BHI_CTRL.
* config/tc-i386.c: Add .bhi_ctrl.
* testsuite/gas/i386/x86-64.exp: Add BHI_CTRL tests.
* testsuite/gas/i386/x86-64-bhi-ctrl-intel.d: New test.
* testsuite/gas/i386/x86-64-bhi-ctrl.d: Ditto.
* testsuite/gas/i386/x86-64-bhi-ctrl.s: Ditto.
opcodes/ChangeLog:
* i386-dis.c: (RM_0F1E_P_1_MOD_3_REG_7): Adjust for ibhf.
(IBHF_Fixup): New. Revert mnemonic back to repz nop for ~REX_W.
* i386-gen.c: (isa_dependencies): Add BHI_CTRL.
(cpu_flags): Ditto.
* i386-opc.h (enum i386_cpu): Ditto.
(i386_cpu_flags): Ditto.
* i386-opc.tbl: Add BHI_CTRL instruction.
* i386-init.h: Regenerated.
* i386-mnem.h: Ditto.
* i386-tbl.h: Ditto.
---
gas/NEWS | 2 +
gas/config/tc-i386.c | 1 +
.../gas/i386/x86-64-bhi-ctrl-intel.d | 12 +
gas/testsuite/gas/i386/x86-64-bhi-ctrl.d | 10 +
gas/testsuite/gas/i386/x86-64-bhi-ctrl.s | 9 +
gas/testsuite/gas/i386/x86-64.exp | 2 +
opcodes/i386-dis.c | 21 +-
opcodes/i386-gen.c | 3 +
opcodes/i386-init.h | 995 ++++---
opcodes/i386-mnem.h | 2639 +++++++++--------
opcodes/i386-opc.h | 3 +
opcodes/i386-opc.tbl | 6 +
opcodes/i386-tbl.h | 1241 ++++----
13 files changed, 2516 insertions(+), 2428 deletions(-)
create mode 100644 gas/testsuite/gas/i386/x86-64-bhi-ctrl-intel.d
create mode 100644 gas/testsuite/gas/i386/x86-64-bhi-ctrl.d
create mode 100644 gas/testsuite/gas/i386/x86-64-bhi-ctrl.s
Comments
On 01.06.2026 08:24, Haochen Jiang wrote:
> The following patch aimed to add BHI_CTRL. The ISA has been published in a
> separate tech paper last year and still missing its assembler/disassembler
> support.
>
> One tricky thing is that it utilized part of the nops encoding and we need
> to keep the same behavior for the not touched one, i.e., repz nop. That is
> why I added a Fixup for now since I did not have a better idea for that.
> Discussions are welcomed on this.
Instead of this, add a decode step through prefix_table[]?
> --- a/opcodes/i386-opc.tbl
> +++ b/opcodes/i386-opc.tbl
> @@ -3630,3 +3630,9 @@ vmovrs<bw>, 0xf26f, AVX10_2&MOVRS&x64, Modrm|Masking|Map5|<bw:vexw>|Disp8ShiftVL
> vmovrs<dq>, 0xf36f, AVX10_2&MOVRS&x64, Modrm|Masking|Map5|<dq:vexw>|Disp8ShiftVL|CheckOperandSize|NoSuf, { Xmmword|Ymmword|Zmmword|Unspecified|BaseIndex, RegXMM|RegYMM|RegZMM }
>
> // MOVRS instructions end.
> +
> +// BHI_CTRL insructions.
> +
> +ibhf, 0xf30f1ef8, BHI_CTRL, NoSuf|Size64, {}
So Size64 is here to have REX.W emitted. The whitepaper isn't clear about APX
at all, though: Would REX2.W also have the same effect? (Whichever way it is,
this then perhaps also wants covering in the testsuite.)
In any event, I don't think we want the i386-gen.c change; instead we want
x64&BHI_CTRL here: Aiui BHI_CTRL itself isn't 64-bit only, it's only this new
insn which is.
Jan
On 02.06.2026 10:26, Jan Beulich wrote:
> On 01.06.2026 08:24, Haochen Jiang wrote:
>> The following patch aimed to add BHI_CTRL. The ISA has been published in a
>> separate tech paper last year and still missing its assembler/disassembler
>> support.
>>
>> One tricky thing is that it utilized part of the nops encoding and we need
>> to keep the same behavior for the not touched one, i.e., repz nop. That is
>> why I added a Fixup for now since I did not have a better idea for that.
>> Discussions are welcomed on this.
>
> Instead of this, add a decode step through prefix_table[]?
Oh, wait - that's already in place. The problem is the REX.W aspect. For that
a fixup likely is indeed best.
Jan
> From: Jan Beulich <jbeulich@suse.com>
> Sent: Tuesday, June 2, 2026 4:27 PM
>
> On 01.06.2026 08:24, Haochen Jiang wrote:
>
> > --- a/opcodes/i386-opc.tbl
> > +++ b/opcodes/i386-opc.tbl
> > @@ -3630,3 +3630,9 @@ vmovrs<bw>, 0xf26f, AVX10_2&MOVRS&x64,
> Modrm|Masking|Map5|<bw:vexw>|Disp8ShiftVL
> > vmovrs<dq>, 0xf36f, AVX10_2&MOVRS&x64,
> Modrm|Masking|Map5|<dq:vexw>|Disp8ShiftVL|CheckOperandSize|NoSuf,
> { Xmmword|Ymmword|Zmmword|Unspecified|BaseIndex,
> RegXMM|RegYMM|RegZMM }
> >
> > // MOVRS instructions end.
> > +
> > +// BHI_CTRL insructions.
> > +
> > +ibhf, 0xf30f1ef8, BHI_CTRL, NoSuf|Size64, {}
>
> So Size64 is here to have REX.W emitted. The whitepaper isn't clear about APX
> at all, though: Would REX2.W also have the same effect? (Whichever way it is,
> this then perhaps also wants covering in the testsuite.)
No, it won't. The encoding is fixed. But a testcase is welcomed here to clarify.
>
> In any event, I don't think we want the i386-gen.c change; instead we want
> x64&BHI_CTRL here: Aiui BHI_CTRL itself isn't 64-bit only, it's only this new
> insn which is.
I am okay with both solutions. But, yes, if we have a new inst in this ISA
(although very low probability) that supports both 32 and 64 bit, then the
current implementation will need re-do. And your point also stands.
Thus, I will change to x64&BHI_CTRL.
Thx,
Haochen
> From: Jiang, Haochen
> Sent: Wednesday, June 3, 2026 10:38 AM
> To: 'Jan Beulich' <jbeulich@suse.com>
>
> > From: Jan Beulich <jbeulich@suse.com>
> > Sent: Tuesday, June 2, 2026 4:27 PM
> >
> > On 01.06.2026 08:24, Haochen Jiang wrote:
> >
> > > --- a/opcodes/i386-opc.tbl
> > > +++ b/opcodes/i386-opc.tbl
> > > @@ -3630,3 +3630,9 @@ vmovrs<bw>, 0xf26f, AVX10_2&MOVRS&x64,
> > Modrm|Masking|Map5|<bw:vexw>|Disp8ShiftVL
> > > vmovrs<dq>, 0xf36f, AVX10_2&MOVRS&x64,
> >
> Modrm|Masking|Map5|<dq:vexw>|Disp8ShiftVL|CheckOperandSize|NoSuf,
> > { Xmmword|Ymmword|Zmmword|Unspecified|BaseIndex,
> > RegXMM|RegYMM|RegZMM }
> > >
> > > // MOVRS instructions end.
> > > +
> > > +// BHI_CTRL insructions.
> > > +
> > > +ibhf, 0xf30f1ef8, BHI_CTRL, NoSuf|Size64, {}
> >
> > So Size64 is here to have REX.W emitted. The whitepaper isn't clear about
> APX
> > at all, though: Would REX2.W also have the same effect? (Whichever way it
> is,
> > this then perhaps also wants covering in the testsuite.)
>
> No, it won't. The encoding is fixed. But a testcase is welcomed here to clarify.
>
But you had a good point here, the current disassembler won't "reject" rex2.w
(i.e., not taking this back to nop from my understanding) and take it as rex.w.
This let me further wonder if a user input something like "{rex2} ibhf", should we
accept that? Let me double check that.
Thx,
Haochen
On 03.06.2026 09:47, Jiang, Haochen wrote:
>> From: Jiang, Haochen
>> Sent: Wednesday, June 3, 2026 10:38 AM
>> To: 'Jan Beulich' <jbeulich@suse.com>
>>
>>> From: Jan Beulich <jbeulich@suse.com>
>>> Sent: Tuesday, June 2, 2026 4:27 PM
>>>
>>> On 01.06.2026 08:24, Haochen Jiang wrote:
>>>
>>>> --- a/opcodes/i386-opc.tbl
>>>> +++ b/opcodes/i386-opc.tbl
>>>> @@ -3630,3 +3630,9 @@ vmovrs<bw>, 0xf26f, AVX10_2&MOVRS&x64,
>>> Modrm|Masking|Map5|<bw:vexw>|Disp8ShiftVL
>>>> vmovrs<dq>, 0xf36f, AVX10_2&MOVRS&x64,
>>>
>> Modrm|Masking|Map5|<dq:vexw>|Disp8ShiftVL|CheckOperandSize|NoSuf,
>>> { Xmmword|Ymmword|Zmmword|Unspecified|BaseIndex,
>>> RegXMM|RegYMM|RegZMM }
>>>>
>>>> // MOVRS instructions end.
>>>> +
>>>> +// BHI_CTRL insructions.
>>>> +
>>>> +ibhf, 0xf30f1ef8, BHI_CTRL, NoSuf|Size64, {}
>>>
>>> So Size64 is here to have REX.W emitted. The whitepaper isn't clear about
>> APX
>>> at all, though: Would REX2.W also have the same effect? (Whichever way it
>> is,
>>> this then perhaps also wants covering in the testsuite.)
>>
>> No, it won't. The encoding is fixed. But a testcase is welcomed here to clarify.
>
> But you had a good point here, the current disassembler won't "reject" rex2.w
> (i.e., not taking this back to nop from my understanding) and take it as rex.w.
>
> This let me further wonder if a user input something like "{rex2} ibhf", should we
> accept that? Let me double check that.
We should accept it if the resulting encoding does what is intended / written.
According to Christian's reply REX2.W doesn't have the same effect, but I wonder
if it's really sensible that way. The W bits, whether encoded in REX or REX2,
really ought to have the same meaning as per the APX spec. Unless of course this
is indeed meant to be another special case besides PUSHP/POPP (when imo it would
be really nice if special cases were avoided whenever possible).
Jan
> From: Jan Beulich <jbeulich@suse.com>
> Sent: Wednesday, June 3, 2026 4:08 PM
>
> On 03.06.2026 09:47, Jiang, Haochen wrote:
> >> From: Jiang, Haochen
> >> Sent: Wednesday, June 3, 2026 10:38 AM
> >> To: 'Jan Beulich' <jbeulich@suse.com>
> >>
> >>> From: Jan Beulich <jbeulich@suse.com>
> >>> Sent: Tuesday, June 2, 2026 4:27 PM
> >>>
> >>> So Size64 is here to have REX.W emitted. The whitepaper isn't clear about
> >> APX
> >>> at all, though: Would REX2.W also have the same effect? (Whichever way it
> >> is,
> >>> this then perhaps also wants covering in the testsuite.)
> >>
> >> No, it won't. The encoding is fixed. But a testcase is welcomed here to clarify.
> >
> > But you had a good point here, the current disassembler won't "reject" rex2.w
> > (i.e., not taking this back to nop from my understanding) and take it as rex.w.
> >
> > This let me further wonder if a user input something like "{rex2} ibhf", should we
> > accept that? Let me double check that.
>
> We should accept it if the resulting encoding does what is intended / written.
> According to Christian's reply REX2.W doesn't have the same effect, but I wonder
> if it's really sensible that way. The W bits, whether encoded in REX or REX2,
> really ought to have the same meaning as per the APX spec. Unless of course this
> is indeed meant to be another special case besides PUSHP/POPP (when imo it
> would be really nice if special cases were avoided whenever possible).
I am confirming with arch team for these issues. This instruction seems to me
the first instruction we only borrowed W1 with no effect, other using REX.W1
at least implied operand size. This definitely needs some clarification.
Will come back to you all after I get a clear answer.
Thx,
Haochen
On Wed, Jun 3, 2026 at 1:16 AM Jiang, Haochen <haochen.jiang@intel.com> wrote:
> I am confirming with arch team for these issues. This instruction seems to me
> the first instruction we only borrowed W1 with no effect, other using REX.W1
> at least implied operand size. This definitely needs some clarification.
>
> Will come back to you all after I get a clear answer.
Arguably RDSSP{D,Q} is a litmus test – can it REX2 or EVEX?
--
C.
> From: Christian Ludloff <ludloff@gmail.com>
> Sent: Thursday, June 4, 2026 4:07 AM
>
> On Wed, Jun 3, 2026 at 1:16 AM Jiang, Haochen <haochen.jiang@intel.com>
> wrote:
> > I am confirming with arch team for these issues. This instruction seems to me
> > the first instruction we only borrowed W1 with no effect, other using
> REX.W1
> > at least implied operand size. This definitely needs some clarification.
> >
> > Will come back to you all after I get a clear answer.
>
> Arguably RDSSP{D,Q} is a litmus test – can it REX2 or EVEX?
I suppose it should be a REX2, not EVEX MAP4. Its opcode is in those
REX2 permitted opcode.
Thx,
Haochen
On Thu, Jun 4, 2026 at 12:39 AM Jiang, Haochen <haochen.jiang@intel.com> wrote:
> > From: Christian Ludloff <ludloff@gmail.com>
> > Arguably RDSSP{D,Q} is a litmus test – can it REX2 or EVEX?
>
> I suppose it should be a REX2, not EVEX MAP4.
From the perspective of the ISA, the W for D-vs-Q
can come from REX or REX2 or EVEX – it should
not matter which of the three encodings gets used
for RDSSP. If that is not the case, then please get
it documented too, together with IBHF behavior.
--
C.
> From: Christian Ludloff <ludloff@gmail.com>
> Sent: Friday, June 5, 2026 12:46 AM
>
> On Thu, Jun 4, 2026 at 12:39 AM Jiang, Haochen <haochen.jiang@intel.com>
> wrote:
> > > From: Christian Ludloff <ludloff@gmail.com>
> > > Arguably RDSSP{D,Q} is a litmus test – can it REX2 or EVEX?
> >
> > I suppose it should be a REX2, not EVEX MAP4.
>
> From the perspective of the ISA, the W for D-vs-Q
> can come from REX or REX2 or EVEX – it should
> not matter which of the three encodings gets used
> for RDSSP. If that is not the case, then please get
> it documented too, together with IBHF behavior.
>
APX documentation has mentioned which instructions could be
promoted to EVEX MAP4. Only the inst mentioned in chart could
use EVEX MAP4. Actually, those EVEX MAP4 insts are all listed
one by one in EAS since the encoding are quite different.
Thx,
Haochen
On Thu, Jun 4, 2026 at 11:02 PM Jiang, Haochen <haochen.jiang@intel.com> wrote:
> > > > Arguably RDSSP{D,Q} is a litmus test – can it REX2 or EVEX?
> > >
> > > I suppose it should be a REX2, not EVEX MAP4.
> >
> > From the perspective of the ISA, the W for D-vs-Q
> > can come from REX or REX2 or EVEX – it should
> > not matter which of the three encodings gets used
> > for RDSSP. If that is not the case, then please get
> > it documented too, together with IBHF behavior.
>
> APX documentation has mentioned which instructions could be
> promoted to EVEX MAP4. Only the inst mentioned in chart could
> use EVEX MAP4. Actually, those EVEX MAP4 insts are all listed
> one by one in EAS since the encoding are quite different.
Sure, MAP4 is documented as a "no".
But MAP1 otoh... :-)
0x62,0xF9,0x7E,0x08,0x1E,0xC8
0x62,0xF9,0xFE,0x08,0x1E,0xC8
--
C.
> From: Christian Ludloff <ludloff@gmail.com>
> Sent: Friday, June 5, 2026 2:25 PM
> To: Jiang, Haochen <haochen.jiang@intel.com>
> Cc: Beulich, Jan <JBeulich@suse.com>; hjl.tools@gmail.com;
> binutils@sourceware.org
> Subject: Re: [PATCH] x86: Support BHI_CTRL instruction
>
> On Thu, Jun 4, 2026 at 11:02 PM Jiang, Haochen <haochen.jiang@intel.com>
> wrote:
> > > > > Arguably RDSSP{D,Q} is a litmus test – can it REX2 or EVEX?
> > > >
> > > > I suppose it should be a REX2, not EVEX MAP4.
> > >
> > > From the perspective of the ISA, the W for D-vs-Q
> > > can come from REX or REX2 or EVEX – it should
> > > not matter which of the three encodings gets used
> > > for RDSSP. If that is not the case, then please get
> > > it documented too, together with IBHF behavior.
> >
> > APX documentation has mentioned which instructions could be
> > promoted to EVEX MAP4. Only the inst mentioned in chart could
> > use EVEX MAP4. Actually, those EVEX MAP4 insts are all listed
> > one by one in EAS since the encoding are quite different.
>
> Sure, MAP4 is documented as a "no".
>
> But MAP1 otoh... :-)
>
> 0x62,0xF9,0x7E,0x08,0x1E,0xC8
> 0x62,0xF9,0xFE,0x08,0x1E,0xC8
>
RDSSP{D,Q} are only legacy encodings, they have nothing to do with
EVEX encoding. So, they should obey legacy space rule, not EVEX space
rule in APX. Those rules are quite clear in documentation. I did not quite
get your confusion here.
Thx,
Haochen
@@ -1,5 +1,7 @@
-*- text -*-
+* Add support for the x86 BHI_CTRL instruction.
+
Changes in 2.46:
* Add support for AMD Zen6 processor.
@@ -1260,6 +1260,7 @@ static const arch_entry cpu_arch[] =
SUBARCH (padlockphe2, PADLOCKPHE2, PADLOCKPHE2, false),
SUBARCH (padlockxmodx, PADLOCKXMODX, PADLOCKXMODX, false),
SUBARCH (movrs, MOVRS, MOVRS, false),
+ SUBARCH (bhi_ctrl, BHI_CTRL, BHI_CTRL, false),
};
#undef SUBARCH
new file mode 100644
@@ -0,0 +1,12 @@
+#objdump: -dw
+#name: x86_64 BHI_CTRL insns (Intel disassembly)
+#source: x86-64-bhi-ctrl.s
+
+.*: +file format .*
+
+Disassembly of section \.text:
+
+#...
+[a-f0-9]+ <_intel>:
+\s*[a-f0-9]+:\s*f3 48 0f 1e f8\s+ibhf
+#pass
new file mode 100644
@@ -0,0 +1,10 @@
+#objdump: -dw
+#name: x86_64 BHI_CTRL insns
+
+.*: +file format .*
+
+Disassembly of section \.text:
+
+0+ <_start>:
+\s*[a-f0-9]+:\s*f3 48 0f 1e f8\s+ibhf
+#pass
new file mode 100644
@@ -0,0 +1,9 @@
+# Check 64bit BHI_CTRL instructions
+
+ .text
+_start:
+ ibhf
+
+_intel:
+ .intel_syntax noprefix
+ ibhf
@@ -550,6 +550,8 @@ run_dump_test "x86-64-movrs-avx10_2-512"
run_dump_test "x86-64-movrs-avx10_2-512-intel"
run_dump_test "x86-64-movrs-avx10_2-256"
run_dump_test "x86-64-movrs-avx10_2-256-intel"
+run_dump_test "x86-64-bhi-ctrl"
+run_dump_test "x86-64-bhi-ctrl-intel"
run_dump_test "x86-64-clzero"
run_dump_test "x86-64-mwaitx-bdver4"
run_list_test "x86-64-mwaitx-reg"
@@ -109,6 +109,7 @@ static bool PREFETCHI_Fixup (instr_info *, int, int);
static bool PUSH2_POP2_Fixup (instr_info *, int, int);
static bool JMPABS_Fixup (instr_info *, int, int);
static bool CFCMOV_Fixup (instr_info *, int, int);
+static bool IBHF_Fixup (instr_info *, int, int);
static void ATTRIBUTE_PRINTF_3 i386_dis_printf (const disassemble_info *,
enum disassembler_style,
@@ -8750,7 +8751,7 @@ static const struct dis386 rm_table[][8] = {
},
{
/* RM_0F1E_P_1_MOD_3_REG_7 */
- { "nopQ", { Ev }, PREFIX_IGNORED },
+ { "ibhf", { IBHF_Fixup }, 0 },
{ "nopQ", { Ev }, PREFIX_IGNORED },
{ "endbr64", { Skip_MODRM }, 0 },
{ "endbr32", { Skip_MODRM }, 0 },
@@ -14671,3 +14672,21 @@ CFCMOV_Fixup (instr_info *ins, int opnd, int sizeflag)
return OP_G (ins, v_mode, sizeflag);
return OP_E (ins, v_mode, sizeflag);
}
+
+static bool
+IBHF_Fixup (instr_info *ins, int bytemode, int sizeflag)
+{
+ if (!(ins->rex & REX_W))
+ {
+ ins->mnemonicendp = stpcpy (ins->obuf, "repz nop");
+ return OP_E (ins, v_mode, sizeflag);
+ }
+ else
+ {
+ USED_REX (REX_W);
+ MODRM_CHECK;
+ ins->codep++;
+ ins->has_skipped_modrm = true;
+ return true;
+ }
+}
@@ -319,6 +319,8 @@ static const dependency isa_dependencies[] =
"PadLock" },
{ "PadLockXMODX",
"PadLock" },
+ { "BHI_CTRL",
+ "64" },
};
/* This array is populated as process_i386_initializers() walks cpu_flags[]. */
@@ -451,6 +453,7 @@ static bitfield cpu_flags[] =
BITFIELD (APX_F),
BITFIELD (AVX10_2),
BITFIELD (MOVRS),
+ BITFIELD (BHI_CTRL),
BITFIELD (MWAITX),
BITFIELD (CLZERO),
BITFIELD (OSPKE),
@@ -241,6 +241,8 @@ enum i386_cpu
CpuMSR_IMM,
/* Intel MOVRS Instructions support required. */
CpuMOVRS,
+ /* Intel BHI_CTRL instruction support required. */
+ CpuBHI_CTRL,
/* mwaitx instruction required */
CpuMWAITX,
/* Clzero instruction required */
@@ -523,6 +525,7 @@ typedef union i386_cpu_flags
unsigned int cpuuser_msr:1;
unsigned int cpumsr_imm:1;
unsigned int cpumovrs:1;
+ unsigned int cpubhi_ctrl:1;
unsigned int cpumwaitx:1;
unsigned int cpuclzero:1;
unsigned int cpuospke:1;
@@ -3630,3 +3630,9 @@ vmovrs<bw>, 0xf26f, AVX10_2&MOVRS&x64, Modrm|Masking|Map5|<bw:vexw>|Disp8ShiftVL
vmovrs<dq>, 0xf36f, AVX10_2&MOVRS&x64, Modrm|Masking|Map5|<dq:vexw>|Disp8ShiftVL|CheckOperandSize|NoSuf, { Xmmword|Ymmword|Zmmword|Unspecified|BaseIndex, RegXMM|RegYMM|RegZMM }
// MOVRS instructions end.
+
+// BHI_CTRL insructions.
+
+ibhf, 0xf30f1ef8, BHI_CTRL, NoSuf|Size64, {}
+
+// BHI_CTRL insructions end.