[10/10] Support Intel PREFETCHI

Message ID 20221014091248.4920-11-haochen.jiang@intel.com
State Accepted
Headers
Series Add new Intel Sierra Forest, Grand Ridge, Granite Rapids Instructions |

Checks

Context Check Description
snail/binutils-gdb-check success Github commit url

Commit Message

Jiang, Haochen Oct. 14, 2022, 9:12 a.m. UTC
  From: "Cui, Lili" <lili.cui@intel.com>

gas/
	* NEWS: Add support for Intel PREFETCHI instruction.
	* config/tc-i386.c: Add prefetchi.
	* doc/c-i386.texi: Document .prefetchi, noprefetchi.
	* testsuite/gas/i386/i386.exp: Run PREFETCHI tests.
	* testsuite/gas/i386/x86-64-prefetchi-intel.d: New test.
	* testsuite/gas/i386/x86-64-prefetchi-inval-register.d: Likewise.
	* testsuite/gas/i386/x86-64-prefetchi-inval-register.s: Likewise.
	* testsuite/gas/i386/x86-64-prefetchi.d: Likewise.
	* testsuite/gas/i386/x86-64-prefetchi.s: Likewise.

opcodes/
	* i386-dis.c (MOD_0F18_REG_6): New.
	(MOD_0F18_REG_7): Ditto.
	(X86_64_MOD_0F18_REG_6): Ditto.
	(X86_64_MOD_0F18_REG_7): Ditto.
	(x86_64_table): Add X86_64_MOD_0F18_REG_6 and X86_64_MOD_0F18_REG_7.
	(mod_table): Add MOD_0F18_REG_6 and MOD_0F18_REG_7.
	(PREFETCHI_Fixup): New.
	* i386-gen.c (cpu_flag_init): Add CPU_PREFETCHI_FLAGS and
	CPU_ANY_PREFETCHI_FLAGS.
	(cpu_flags): Add CpuPREFETCHI.
	* i386-opc.h (CpuPREFETCHI): New.
	(i386_cpu_flags): Add cpuprefetchi.
	* i386-opc.tbl: Add Intel PREFETCHI instructions.
	* i386-init.h: Regenerated.
	* i386-tbl.h: Likewise.
---
 gas/NEWS                                      |    2 +
 gas/config/tc-i386.c                          |    4 +-
 gas/doc/c-i386.texi                           |    4 +-
 gas/testsuite/gas/i386/i386.exp               |    3 +
 gas/testsuite/gas/i386/x86-64-lfence-load.d   |    2 +
 gas/testsuite/gas/i386/x86-64-lfence-load.s   |    2 +
 gas/testsuite/gas/i386/x86-64-lockbad-1.l     |  104 +-
 gas/testsuite/gas/i386/x86-64-lockbad-1.s     |    4 +
 .../gas/i386/x86-64-prefetchi-intel.d         |   16 +
 .../i386/x86-64-prefetchi-inval-register.d    |   13 +
 .../i386/x86-64-prefetchi-inval-register.s    |    9 +
 gas/testsuite/gas/i386/x86-64-prefetchi.d     |   15 +
 gas/testsuite/gas/i386/x86-64-prefetchi.s     |   14 +
 opcodes/i386-dis.c                            |   46 +-
 opcodes/i386-gen.c                            |    5 +
 opcodes/i386-init.h                           |  522 +-
 opcodes/i386-opc.h                            |    3 +
 opcodes/i386-opc.tbl                          |    7 +
 opcodes/i386-tbl.h                            | 7846 +++++++++--------
 19 files changed, 4407 insertions(+), 4214 deletions(-)
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi-intel.d
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.d
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.s
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi.d
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi.s
  

Comments

Jan Beulich Oct. 17, 2022, 8:15 a.m. UTC | #1
On 14.10.2022 11:12, Haochen Jiang wrote:
> From: "Cui, Lili" <lili.cui@intel.com>
> 
> gas/
> 	* NEWS: Add support for Intel PREFETCHI instruction.
> 	* config/tc-i386.c: Add prefetchi.
> 	* doc/c-i386.texi: Document .prefetchi, noprefetchi.
> 	* testsuite/gas/i386/i386.exp: Run PREFETCHI tests.
> 	* testsuite/gas/i386/x86-64-prefetchi-intel.d: New test.
> 	* testsuite/gas/i386/x86-64-prefetchi-inval-register.d: Likewise.
> 	* testsuite/gas/i386/x86-64-prefetchi-inval-register.s: Likewise.
> 	* testsuite/gas/i386/x86-64-prefetchi.d: Likewise.
> 	* testsuite/gas/i386/x86-64-prefetchi.s: Likewise.
> 
> opcodes/
> 	* i386-dis.c (MOD_0F18_REG_6): New.
> 	(MOD_0F18_REG_7): Ditto.
> 	(X86_64_MOD_0F18_REG_6): Ditto.
> 	(X86_64_MOD_0F18_REG_7): Ditto.
> 	(x86_64_table): Add X86_64_MOD_0F18_REG_6 and X86_64_MOD_0F18_REG_7.
> 	(mod_table): Add MOD_0F18_REG_6 and MOD_0F18_REG_7.
> 	(PREFETCHI_Fixup): New.
> 	* i386-gen.c (cpu_flag_init): Add CPU_PREFETCHI_FLAGS and
> 	CPU_ANY_PREFETCHI_FLAGS.
> 	(cpu_flags): Add CpuPREFETCHI.
> 	* i386-opc.h (CpuPREFETCHI): New.
> 	(i386_cpu_flags): Add cpuprefetchi.
> 	* i386-opc.tbl: Add Intel PREFETCHI instructions.
> 	* i386-init.h: Regenerated.
> 	* i386-tbl.h: Likewise.
> ---
>  gas/NEWS                                      |    2 +
>  gas/config/tc-i386.c                          |    4 +-
>  gas/doc/c-i386.texi                           |    4 +-
>  gas/testsuite/gas/i386/i386.exp               |    3 +
>  gas/testsuite/gas/i386/x86-64-lfence-load.d   |    2 +
>  gas/testsuite/gas/i386/x86-64-lfence-load.s   |    2 +
>  gas/testsuite/gas/i386/x86-64-lockbad-1.l     |  104 +-
>  gas/testsuite/gas/i386/x86-64-lockbad-1.s     |    4 +

As for earlier patches I question the additions here. The purpose of this
test (and its 32-bit counterpart) isn't to cover all insns not valid with
LOCK, but just forms of insns which _may_ allow for LOCK. (But yes, these
tests aren't really complete.)

Note also how your ChangeLog entry doesn't mention tests you're altering.
You're not required anymore to provide ChangeLog entries, but if you do I
think they will want to match the actual patch.

> --- a/gas/config/tc-i386.c
> +++ b/gas/config/tc-i386.c
> @@ -1102,6 +1102,7 @@ static const arch_entry cpu_arch[] =
>    SUBARCH (wrmsrns, WRMSRNS, ANY_WRMSRNS, false),
>    SUBARCH (msrlist, MSRLIST, ANY_MSRLIST, false),
>    SUBARCH (amx_fp16, AMX_FP16, ANY_AMX_FP16, false),
> +  SUBARCH (prefetchi, PREFETCHI, ANY_PREFETCHI, false),
>  };

Once again - likely no need for ANY_PREFETCHI (but see question further
down).

> @@ -4522,7 +4523,8 @@ load_insn_p (void)
>      {
>        /* Anysize insns: lea, invlpg, clflush, prefetchnta, prefetcht0,
>  	 prefetcht1, prefetcht2, prefetchtw, bndmk, bndcl, bndcu, bndcn,
> -	 bndstx, bndldx, prefetchwt1, clflushopt, clwb, cldemote.  */
> +	 bndstx, bndldx, prefetchwt1, clflushopt, clwb, cldemote, prefetchit0
> +	 prefetchit1.  */
>        if (i.tm.opcode_modifier.anysize)
>  	return 0;

Rather than further increasing the comment volume (and hence making it
harder to recognize quickly what is or is not covered here), may I suggest
to fold all mentioning of prefetches here into a single "prefetch*"?

> --- /dev/null
> +++ b/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.d
> @@ -0,0 +1,13 @@
> +#as:
> +#objdump: -dw
> +#name: x86-64 PREFETCHI INVAL REGISTER insns
> +
> +.*: +file format .*
> +
> +
> +Disassembly of section .text:
> +
> +0+ <\.text>:
> +[ 	]*[a-f0-9]+:[ 	]0f 18 39[ 	]*nopl   \(%rcx\)
> +[ 	]*[a-f0-9]+:[ 	]0f 18 31[ 	]*nopl   \(%rcx\)
> +#pass
> diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.s b/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.s
> new file mode 100644
> index 0000000000..550449a0c9
> --- /dev/null
> +++ b/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.s
> @@ -0,0 +1,9 @@
> +.text
> +        #prefetchit0 (%rcx) PREFETCHIT0/1 apply without RIP-relative addressing, should stay NOPs.
> +        .byte 0x0f
> +        .byte 0x18
> +        .byte 0x39
> +        #prefetchit1 (%rcx) PREFETCHIT1/1 apply without RIP-relative addressing, should stay NOPs.
> +        .byte 0x0f
> +        .byte 0x18
> +        .byte 0x31

This is the disassembler side test. An assembler side counterpart is
needed as well, which I assume will point out that you also need to
make another change to the assembler (to actually reject non-RIP-
relative addressing).

> @@ -1297,6 +1300,8 @@ enum
>    X86_64_0F01_REG_7_MOD_3_RM_6_PREFIX_1,
>    X86_64_0F01_REG_7_MOD_3_RM_6_PREFIX_3,
>    X86_64_0F01_REG_7_MOD_3_RM_7_PREFIX_1,
> +  X86_64_MOD_0F18_REG_6,
> +  X86_64_MOD_0F18_REG_7,

X86_64_0F18_REG_6_MOD_0 and X86_64_0F18_REG_7_MOD_0 respectively.

> @@ -4414,6 +4419,18 @@ static const struct dis386 x86_64_table[][2] = {
>      { "psmash",	{ Skip_MODRM }, 0 },
>    },
>  
> +  /* X86_64_MOD_0F18_REG_6 */
> +  {
> +    { "nopQ",		{ Ev }, 0 },
> +    { "prefetchit1",    { { PREFETCHI_Fixup, b_mode } }, 0 },
> +  },
> +
> +  /* X86_64_MOD_0F18_REG_7 */
> +  {
> +    { "nopQ",		{ Ev }, 0 },
> +    { "prefetchit0",    { { PREFETCHI_Fixup, b_mode } }, 0 },
> +  },

Nit: Please use consistent padding (tabs) after the first comma each.

> @@ -14021,3 +14048,18 @@ OP_Rounding (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
>      }
>    oappend (ins, "sae}");
>  }
> +
> +static void
> +PREFETCHI_Fixup (instr_info *ins, int bytemode, int sizeflag)
> +{
> +  if (ins->modrm.mod != 0 || ins->modrm.rm != 5)
> +    {
> +      if (ins->intel_syntax)
> +	ins->mnemonicendp = stpcpy (ins->obuf, "nop   ");
> +      else
> +	ins->mnemonicendp = stpcpy (ins->obuf, "nopl  ");

Why "nopl"? There's no NP ahead of the opcode (and you also don't go
through prefix_table[]), so I expect operand size should be expressed
here correctly.

> --- a/opcodes/i386-gen.c
> +++ b/opcodes/i386-gen.c
> @@ -261,6 +261,8 @@ static initializer cpu_flag_init[] =
>      "CpuMSRLIST" },
>    { "CPU_AMX_FP16_FLAGS",
>      "CpuAMX_FP16" },
> +  { "CPU_PREFETCHI_FLAGS",
> +    "CpuPREFETCHI"},
>    { "CPU_IAMCU_FLAGS",
>      "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuIAMCU" },
>    { "CPU_ADX_FLAGS",
> @@ -471,6 +473,8 @@ static initializer cpu_flag_init[] =
>      "CpuMSRLIST" },
>    { "CPU_ANY_AMX_FP16_FLAGS",
>      "CpuAMX_FP16" },
> +  { "CPU_ANY_PREFETCHI_FLAGS",
> +    "CpuPREFETCHI" },
>  };

Are there intended to be dependencies between these and the earlier
prefetch features?

> --- a/opcodes/i386-opc.tbl
> +++ b/opcodes/i386-opc.tbl
> @@ -3345,3 +3345,10 @@ wrmsrlist, 0xf30f01c6, None, CpuMSRLIST|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|N
>  tdpfp16ps, 0xf25c, None, CpuAMX_FP16|Cpu64, Modrm|Vex128|Space0F38|VexVVVV=1|VexW0|SwapSources|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { RegTMM, RegTMM, RegTMM }
>  
>  // AMX-FP16 instructions end.
> +
> +// PREFETCHI instructions.
> +
> +prefetchit0, 0xf18, 0x7, CpuPREFETCHI|Cpu64, Modrm|Anysize|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { BaseIndex }
> +prefetchit1, 0xf18, 0x6, CpuPREFETCHI|Cpu64, Modrm|Anysize|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { BaseIndex }
> +
> +// PREFETCHI instructions end.

With the restriction to RIP-relative addressing I think a better form of
expressing such operands would be along the lines of CALL/JMP:

	prefetchit0 code_label
	...
code_label:

I think it should be suggested to those having defined the ISA extension
to at least permit assemblers to support this form (and then do so here,
along with the present forms, unless the doc was changed to _only_ allow
for the alternative form).

Jan
  
Frager, Neal via Binutils Oct. 25, 2022, 1:03 p.m. UTC | #2
> >  gas/testsuite/gas/i386/x86-64-lockbad-1.l     |  104 +-
> >  gas/testsuite/gas/i386/x86-64-lockbad-1.s     |    4 +
> 
> As for earlier patches I question the additions here. The purpose of this test
> (and its 32-bit counterpart) isn't to cover all insns not valid with LOCK, but just
> forms of insns which _may_ allow for LOCK. (But yes, these tests aren't really
> complete.)
> 
Done.

> Note also how your ChangeLog entry doesn't mention tests you're altering.
> You're not required anymore to provide ChangeLog entries, but if you do I
> think they will want to match the actual patch.
> 
Done.

> >        /* Anysize insns: lea, invlpg, clflush, prefetchnta, prefetcht0,
> >  	 prefetcht1, prefetcht2, prefetchtw, bndmk, bndcl, bndcu, bndcn,
> > -	 bndstx, bndldx, prefetchwt1, clflushopt, clwb, cldemote.  */
> > +	 bndstx, bndldx, prefetchwt1, clflushopt, clwb, cldemote, prefetchit0
> > +	 prefetchit1.  */
> >        if (i.tm.opcode_modifier.anysize)
> >  	return 0;
> 
> Rather than further increasing the comment volume (and hence making it
> harder to recognize quickly what is or is not covered here), may I suggest to
> fold all mentioning of prefetches here into a single "prefetch*"?
> 
Done.

> 
> This is the disassembler side test. An assembler side counterpart is needed
> as well, which I assume will point out that you also need to make another
> change to the assembler (to actually reject non-RIP- relative addressing).
> 
Added warning for illegal input of PREFECHI

> > @@ -1297,6 +1300,8 @@ enum
> >    X86_64_0F01_REG_7_MOD_3_RM_6_PREFIX_1,
> >    X86_64_0F01_REG_7_MOD_3_RM_6_PREFIX_3,
> >    X86_64_0F01_REG_7_MOD_3_RM_7_PREFIX_1,
> > +  X86_64_MOD_0F18_REG_6,
> > +  X86_64_MOD_0F18_REG_7,
> 
> X86_64_0F18_REG_6_MOD_0 and X86_64_0F18_REG_7_MOD_0
> respectively.
Done.

> > +    { "nopQ",		{ Ev }, 0 },
> > +    { "prefetchit0",    { { PREFETCHI_Fixup, b_mode } }, 0 },
> > +  },
> 
> Nit: Please use consistent padding (tabs) after the first comma each.
Done.

> > +    {
> > +      if (ins->intel_syntax)
> > +	ins->mnemonicendp = stpcpy (ins->obuf, "nop   ");
> > +      else
> > +	ins->mnemonicendp = stpcpy (ins->obuf, "nopl  ");
> 
> Why "nopl"? There's no NP ahead of the opcode (and you also don't go
> through prefix_table[]), so I expect operand size should be expressed here
> correctly.
I changed it to nop.

> With the restriction to RIP-relative addressing I think a better form of
> expressing such operands would be along the lines of CALL/JMP:
> 
> 	prefetchit0 code_label
> 	...
> code_label:
> 
> I think it should be suggested to those having defined the ISA extension to at
> least permit assemblers to support this form (and then do so here, along
> with the present forms, unless the doc was changed to _only_ allow for the
> alternative form).
> 
Regarding this code_lable , I suppose we can't support it for a short time.
@ H.J what do you think of this place? Thanks.



Subject: [PATCH] Support Intel PREFETCHI

gas/ChangeLog:

	* NEWS: Add support for Intel PREFETCHI instruction.
	* config/tc-i386.c (load_insn_p): Use prefetch* to fold all prefetches.
	(check_VecOperands): Add warning for illegal input of PREFETCHI.
	* doc/c-i386.texi: Document .prefetchi.
	* testsuite/gas/i386/i386.exp: Run PREFETCHI tests.
	* testsuite/gas/i386/x86-64-lfence-load.d: Add PREFETCHI.
	* testsuite/gas/i386/x86-64-lfence-load.s: Likewise.
	* testsuite/gas/i386/x86-64-prefetch.d: New test.
	* testsuite/gas/i386/x86-64-prefetchi-intel.d: Likewise.
	* testsuite/gas/i386/x86-64-prefetchi-inval-register.d: Likewise..
	* testsuite/gas/i386/x86-64-prefetchi-inval-register.s: Likewise.
	* testsuite/gas/i386/x86-64-prefetchi-warn.l: Likewise.
	* testsuite/gas/i386/x86-64-prefetchi-warn.s: Likewise.
	* testsuite/gas/i386/x86-64-prefetchi.d: Likewise.
	* testsuite/gas/i386/x86-64-prefetchi.s: Likewise.

opcodes/ChangeLog:

	* i386-dis.c (reg_table): Add MOD_0F18_REG_6 and MOD_0F18_REG_7
	(x86_64_table): Add X86_64_0F18_REG_6_MOD_0 and X86_64_0F18_REG_7_MOD_0.
	(mod_table): Add MOD_0F18_REG_6 and MOD_0F18_REG_7.
	(PREFETCHI_Fixup): New.
	* i386-gen.c (cpu_flag_init): Add CPU_PREFETCHI_FLAGS.
	(cpu_flags): Add CpuPREFETCHI.
	(struct): Add RegRIP.
	* i386-opc.h (CpuPREFETCHI): New.
	(i386_cpu_flags): Add cpuprefetchi.
	* i386-opc.tbl: Add Intel PREFETCHI instructions.
	* i386-init.h: Regenerated.
	* i386-tbl.h: Likewise.
---
 gas/NEWS                                      |  2 +
 gas/config/tc-i386.c                          | 13 ++++--
 gas/doc/c-i386.texi                           |  3 +-
 gas/testsuite/gas/i386/i386.exp               |  3 ++
 gas/testsuite/gas/i386/x86-64-lfence-load.d   |  2 +
 gas/testsuite/gas/i386/x86-64-lfence-load.s   |  2 +
 gas/testsuite/gas/i386/x86-64-prefetch.d      |  4 +-
 .../gas/i386/x86-64-prefetchi-intel.d         | 16 +++++++
 .../i386/x86-64-prefetchi-inval-register.d    | 13 ++++++
 .../i386/x86-64-prefetchi-inval-register.s    |  9 ++++
 .../gas/i386/x86-64-prefetchi-warn.l          |  5 +++
 .../gas/i386/x86-64-prefetchi-warn.s          | 11 +++++
 gas/testsuite/gas/i386/x86-64-prefetchi.d     | 15 +++++++
 gas/testsuite/gas/i386/x86-64-prefetchi.s     | 14 ++++++
 opcodes/i386-dis.c                            | 43 ++++++++++++++++++-
 opcodes/i386-gen.c                            |  4 ++
 opcodes/i386-opc.h                            |  4 ++
 opcodes/i386-opc.tbl                          |  8 ++++
 18 files changed, 163 insertions(+), 8 deletions(-)
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi-intel.d
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.d
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.s
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi-warn.l
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi-warn.s
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi.d
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi.s

diff --git a/gas/NEWS b/gas/NEWS
index 961449545d..5eb479f5a1 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -1,5 +1,7 @@
 -*- text -*-
 
+* Add support for Intel PREFETCHI instructions.
+
 * Add support for Intel AMX-FP16 instructions.
 
 * Add support for Intel MSRLIST instructions.
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index c1623f216e..67cc61a7e7 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -1102,6 +1102,7 @@ static const arch_entry cpu_arch[] =
   SUBARCH (rao_int, RAO_INT, RAO_INT, false),
   SUBARCH (wrmsrns, WRMSRNS, WRMSRNS, false),
   SUBARCH (msrlist, MSRLIST, MSRLIST, false),
+  SUBARCH (prefetchi, PREFETCHI, PREFETCHI, false),
 };
 
 #undef SUBARCH
@@ -4520,9 +4521,8 @@ load_insn_p (void)
 
   if (!any_vex_p)
     {
-      /* Anysize insns: lea, invlpg, clflush, prefetchnta, prefetcht0,
-	 prefetcht1, prefetcht2, prefetchtw, bndmk, bndcl, bndcu, bndcn,
-	 bndstx, bndldx, prefetchwt1, clflushopt, clwb, cldemote.  */
+      /* Anysize insns: lea, invlpg, clflush, prefetch*, bndmk, bndcl, bndcu,
+	 bndcn, bndstx, bndldx, clflushopt, clwb, cldemote.  */
       if (i.tm.opcode_modifier.anysize)
 	return 0;
 
@@ -6363,6 +6363,13 @@ check_VecOperands (const insn_template *t)
 	    i.types[op].bitfield.disp8 = 0;
 	  }
     }
+  /* Check if IP-relative addressing requirements can be satisfied.  */
+  for (op = 0; op < t->operands; op++)
+    {
+      if (t->operand_types[op].bitfield.instance == RegRIP
+	  && !(i.base_reg && i.base_reg->reg_num == RegIP))
+	as_warn (_("only support RIP-relative address"));
+    }
 
   i.memshift = 0;
 
diff --git a/gas/doc/c-i386.texi b/gas/doc/c-i386.texi
index b33f17c698..fae902c034 100644
--- a/gas/doc/c-i386.texi
+++ b/gas/doc/c-i386.texi
@@ -201,6 +201,7 @@ accept various extension mnemonics.  For example,
 @code{rao_int},
 @code{wrmsrns},
 @code{msrlist},
+@code{prefetchi},
 @code{amx_int8},
 @code{amx_bf16},
 @code{amx_fp16},
@@ -1496,7 +1497,7 @@ supported on the CPU specified.  The choices for @var{cpu_type} are:
 @item @samp{.clwb} @tab @samp{.rdpid} @tab @samp{.ptwrite} @tab @samp{.ibt}
 @item @samp{.avx_ifma} @tab @samp{.avx_vnni_int8} @tab @samp{.avx_ne_convert}
 @item @samp{.cmpccxadd} @tab @samp{.rao_int} @tab @samp{.wrmsrns}
-@item @samp{.msrlist}
+@item @samp{.msrlist} @tab @samp{.prefetchi}
 @item @samp{.wbnoinvd} @tab @samp{.pconfig} @tab @samp{.waitpkg} @tab @samp{.cldemote}
 @item @samp{.shstk} @tab @samp{.gfni} @tab @samp{.vaes} @tab @samp{.vpclmulqdq}
 @item @samp{.movdiri} @tab @samp{.movdir64b} @tab @samp{.enqcmd} @tab @samp{.tsxldtrk}
diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp
index 9f5fa7f612..80bd2835ca 100644
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -1209,6 +1209,9 @@ if [gas_64_check] then {
     run_dump_test "x86-64-tdx"
     run_dump_test "x86-64-tsxldtrk"
     run_dump_test "x86-64-hreset"
+    run_dump_test "x86-64-prefetchi"
+    run_dump_test "x86-64-prefetchi-intel"
+    run_dump_test "x86-64-prefetchi-inval-register"
     run_dump_test "x86-64-vp2intersect"
     run_dump_test "x86-64-vp2intersect-intel"
     run_list_test "x86-64-vp2intersect-inval-bcast"
diff --git a/gas/testsuite/gas/i386/x86-64-lfence-load.d b/gas/testsuite/gas/i386/x86-64-lfence-load.d
index 2af86fc93f..17c3b9f286 100644
--- a/gas/testsuite/gas/i386/x86-64-lfence-load.d
+++ b/gas/testsuite/gas/i386/x86-64-lfence-load.d
@@ -33,6 +33,8 @@ Disassembly of section .text:
  +[a-f0-9]+:	0f 18 55 00          	prefetcht1 0x0\(%rbp\)
  +[a-f0-9]+:	0f 18 5d 00          	prefetcht2 0x0\(%rbp\)
  +[a-f0-9]+:	0f 0d 4d 00          	prefetchw 0x0\(%rbp\)
+ +[a-f0-9]+:	0f 18 3d 78 56 34 12 	prefetchit0 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+ +[a-f0-9]+:	0f 18 35 78 56 34 12 	prefetchit1 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
  +[a-f0-9]+:	0f a1                	pop    %fs
  +[a-f0-9]+:	0f ae e8             	lfence
  +[a-f0-9]+:	9d                   	popf
diff --git a/gas/testsuite/gas/i386/x86-64-lfence-load.s b/gas/testsuite/gas/i386/x86-64-lfence-load.s
index 2a3ac6b7d2..c478082416 100644
--- a/gas/testsuite/gas/i386/x86-64-lfence-load.s
+++ b/gas/testsuite/gas/i386/x86-64-lfence-load.s
@@ -20,6 +20,8 @@ _start:
 	prefetcht1 (%rbp)
 	prefetcht2 (%rbp)
 	prefetchw (%rbp)
+	prefetchit0 0x12345678(%rip)
+	prefetchit1 0x12345678(%rip)
 	pop %fs
 	popf
 	xlatb (%rbx)
diff --git a/gas/testsuite/gas/i386/x86-64-prefetch.d b/gas/testsuite/gas/i386/x86-64-prefetch.d
index 121592b6ec..246e296956 100644
--- a/gas/testsuite/gas/i386/x86-64-prefetch.d
+++ b/gas/testsuite/gas/i386/x86-64-prefetch.d
@@ -23,5 +23,5 @@ Disassembly of section .text:
 \s*[a-f0-9]+:	0f 18 18             	prefetcht2 \(%rax\)
 \s*[a-f0-9]+:	0f 18 20             	nopl   \(%rax\)
 \s*[a-f0-9]+:	0f 18 28             	nopl   \(%rax\)
-\s*[a-f0-9]+:	0f 18 30             	nopl   \(%rax\)
-\s*[a-f0-9]+:	0f 18 38             	nopl   \(%rax\)
+\s*[a-f0-9]+:	0f 18 30             	nop    \(%rax\)
+\s*[a-f0-9]+:	0f 18 38             	nop    \(%rax\)
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-intel.d b/gas/testsuite/gas/i386/x86-64-prefetchi-intel.d
new file mode 100644
index 0000000000..7f72f0a1eb
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi-intel.d
@@ -0,0 +1,16 @@
+#as:
+#objdump: -dwMintel
+#name: x86-64 PREFETCHI insns (Intel disassembly)
+#source: x86-64-prefetchi.s
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <_start>:
+[ 	]*[a-f0-9]+:	0f 18 3d 78 56 34 12 	prefetchit0 BYTE PTR \[rip\+0x12345678\]        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 35 78 56 34 12 	prefetchit1 BYTE PTR \[rip\+0x12345678\]        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 3d 78 56 34 12 	prefetchit0 BYTE PTR \[rip\+0x12345678\]        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 35 78 56 34 12 	prefetchit1 BYTE PTR \[rip\+0x12345678\]        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.d b/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.d
new file mode 100644
index 0000000000..4c2f19b697
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.d
@@ -0,0 +1,13 @@
+#as:
+#objdump: -dw
+#name: x86-64 PREFETCHI INVAL REGISTER insns
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <\.text>:
+[ 	]*[a-f0-9]+:[ 	]0f 18 39[ 	]*nop    \(%rcx\)
+[ 	]*[a-f0-9]+:[ 	]0f 18 31[ 	]*nop    \(%rcx\)
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.s b/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.s
new file mode 100644
index 0000000000..550449a0c9
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.s
@@ -0,0 +1,9 @@
+.text
+        #prefetchit0 (%rcx) PREFETCHIT0/1 apply without RIP-relative addressing, should stay NOPs.
+        .byte 0x0f
+        .byte 0x18
+        .byte 0x39
+        #prefetchit1 (%rcx) PREFETCHIT1/1 apply without RIP-relative addressing, should stay NOPs.
+        .byte 0x0f
+        .byte 0x18
+        .byte 0x31
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-warn.l b/gas/testsuite/gas/i386/x86-64-prefetchi-warn.l
new file mode 100644
index 0000000000..4e15389463
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi-warn.l
@@ -0,0 +1,5 @@
+.*: Assembler messages:
+.*:[0-9]*: Warning: only support RIP-relative address
+.*:[0-9]*: Warning: only support RIP-relative address
+.*:[0-9]*: Warning: only support RIP-relative address
+.*:[0-9]*: Warning: only support RIP-relative address
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-warn.s b/gas/testsuite/gas/i386/x86-64-prefetchi-warn.s
new file mode 100644
index 0000000000..330ff31c75
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi-warn.s
@@ -0,0 +1,11 @@
+# Check error for ICACHE-PREFETCH 64-bit instruction
+
+	.allow_index_reg
+	.text
+_start:
+	prefetchit0     0x12345678(%rax)
+	prefetchit1     0x12345678(%rax)
+
+	.intel_syntax noprefix
+	prefetchit0     BYTE PTR [rax+0x12345678]
+	prefetchit1     BYTE PTR [rax+0x12345678]
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi.d b/gas/testsuite/gas/i386/x86-64-prefetchi.d
new file mode 100644
index 0000000000..c8ab92d147
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi.d
@@ -0,0 +1,15 @@
+#as:
+#objdump: -dw
+#name: x86-64 PREFETCHI insns
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <_start>:
+[ 	]*[a-f0-9]+:	0f 18 3d 78 56 34 12 	prefetchit0 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 35 78 56 34 12 	prefetchit1 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 3d 78 56 34 12 	prefetchit0 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 35 78 56 34 12 	prefetchit1 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi.s b/gas/testsuite/gas/i386/x86-64-prefetchi.s
new file mode 100644
index 0000000000..cc7c61e9a9
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi.s
@@ -0,0 +1,14 @@
+# Check 64bit PREFETCHI instructions
+
+	.allow_index_reg
+	.text
+_start:
+
+        prefetchit0     0x12345678(%rip)
+        prefetchit1     0x12345678(%rip)
+
+        .intel_syntax noprefix
+
+        prefetchit0     BYTE PTR [rip+0x12345678]
+        prefetchit1     BYTE PTR [rip+0x12345678]
+
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c
index 27ae8eaf46..ccf151c2d9 100644
--- a/opcodes/i386-dis.c
+++ b/opcodes/i386-dis.c
@@ -114,6 +114,7 @@ static void FXSAVE_Fixup (instr_info *, int, int);
 
 static void MOVSXD_Fixup (instr_info *, int, int);
 static void DistinctDest_Fixup (instr_info *, int, int);
+static void PREFETCHI_Fixup (instr_info *, int, int);
 
 /* This character is used to encode style information within the output
    buffers.  See oappend_insert_style for more details.  */
@@ -841,6 +842,8 @@ enum
   MOD_0F18_REG_1,
   MOD_0F18_REG_2,
   MOD_0F18_REG_3,
+  MOD_0F18_REG_6,
+  MOD_0F18_REG_7,
   MOD_0F1A_PREFIX_0,
   MOD_0F1B_PREFIX_0,
   MOD_0F1B_PREFIX_1,
@@ -1280,6 +1283,8 @@ enum
   X86_64_0F01_REG_7_MOD_3_RM_6_PREFIX_1,
   X86_64_0F01_REG_7_MOD_3_RM_6_PREFIX_3,
   X86_64_0F01_REG_7_MOD_3_RM_7_PREFIX_1,
+  X86_64_0F18_REG_6_MOD_0,
+  X86_64_0F18_REG_7_MOD_0,
   X86_64_0F24,
   X86_64_0F26,
   X86_64_0FC7_REG_6_MOD_3_PREFIX_1,
@@ -2751,8 +2756,8 @@ static const struct dis386 reg_table[][8] = {
     { MOD_TABLE (MOD_0F18_REG_3) },
     { "nopQ",		{ Ev }, 0 },
     { "nopQ",		{ Ev }, 0 },
-    { "nopQ",		{ Ev }, 0 },
-    { "nopQ",		{ Ev }, 0 },
+    { MOD_TABLE (MOD_0F18_REG_6) },
+    { MOD_TABLE (MOD_0F18_REG_7) },
   },
   /* REG_0F1C_P_0_MOD_0 */
   {
@@ -4394,6 +4399,18 @@ static const struct dis386 x86_64_table[][2] = {
     { "psmash",	{ Skip_MODRM }, 0 },
   },
 
+  /* X86_64_0F18_REG_6_MOD_0 */
+  {
+    { "nopQ",		{ Ev }, 0 },
+    { "prefetchit1",	{ { PREFETCHI_Fixup, b_mode } }, 0 },
+  },
+
+  /* X86_64_0F18_REG_7_MOD_0 */
+  {
+    { "nopQ",		{ Ev }, 0 },
+    { "prefetchit0",	{ { PREFETCHI_Fixup, b_mode } }, 0 },
+  },
+
   {
     /* X86_64_0F24 */
     { "movZ",		{ Em, Td }, 0 },
@@ -8193,6 +8210,16 @@ static const struct dis386 mod_table[][2] = {
     { "prefetcht2",	{ Mb }, 0 },
     { "nopQ",		{ Ev }, 0 },
   },
+  {
+    /* MOD_0F18_REG_6 */
+    { X86_64_TABLE (X86_64_0F18_REG_6_MOD_0) },
+    { "nopQ",		{ Ev }, 0 },
+  },
+  {
+    /* MOD_0F18_REG_7 */
+    { X86_64_TABLE (X86_64_0F18_REG_7_MOD_0) },
+    { "nopQ",		{ Ev }, 0 },
+  },
   {
     /* MOD_0F1A_PREFIX_0 */
     { "bndldx",		{ Gbnd, Mv_bnd }, 0 },
@@ -13940,3 +13967,15 @@ OP_Rounding (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
     }
   oappend (ins, "sae}");
 }
+
+static void
+PREFETCHI_Fixup (instr_info *ins, int bytemode, int sizeflag)
+{
+  if (ins->modrm.mod != 0 || ins->modrm.rm != 5)
+    {
+      ins->mnemonicendp = stpcpy (ins->obuf, "nop   ");
+      bytemode = v_mode;
+    }
+
+  OP_M (ins, bytemode, sizeflag);
+}
diff --git a/opcodes/i386-gen.c b/opcodes/i386-gen.c
index 237f147ad4..60ec3504dd 100644
--- a/opcodes/i386-gen.c
+++ b/opcodes/i386-gen.c
@@ -259,6 +259,8 @@ static initializer cpu_flag_init[] =
     "CpuWRMSRNS" },
   { "CPU_MSRLIST_FLAGS",
     "CpuMSRLIST" },
+  { "CPU_PREFETCHI_FLAGS",
+    "CpuPREFETCHI"},
   { "CPU_IAMCU_FLAGS",
     "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuIAMCU" },
   { "CPU_ADX_FLAGS",
@@ -677,6 +679,7 @@ static bitfield cpu_flags[] =
   BITFIELD (CpuRAO_INT),
   BITFIELD (CpuWRMSRNS),
   BITFIELD (CpuMSRLIST),
+  BITFIELD (CpuPREFETCHI),
   BITFIELD (CpuMWAITX),
   BITFIELD (CpuCLZERO),
   BITFIELD (CpuOSPKE),
@@ -802,6 +805,7 @@ static const struct {
     INSTANCE (RegC),
     INSTANCE (RegD),
     INSTANCE (RegB),
+    INSTANCE (RegRIP),
 };
 
 #undef INSTANCE
diff --git a/opcodes/i386-opc.h b/opcodes/i386-opc.h
index 645abe7f34..9e4931530a 100644
--- a/opcodes/i386-opc.h
+++ b/opcodes/i386-opc.h
@@ -223,6 +223,8 @@ enum
   CpuWRMSRNS,
   /* Intel MSRLIST Instructions support required.  */
   CpuMSRLIST,
+  /* PREFETCHI instruction required */
+  CpuPREFETCHI,
   /* mwaitx instruction required */
   CpuMWAITX,
   /* Clzero instruction required */
@@ -411,6 +413,7 @@ typedef union i386_cpu_flags
       unsigned int cpurao_int:1;
       unsigned int cpuwrmsrns:1;
       unsigned int cpumsrlist:1;
+      unsigned int cpuprefetchi:1;
       unsigned int cpumwaitx:1;
       unsigned int cpuclzero:1;
       unsigned int cpuospke:1;
@@ -814,6 +817,7 @@ enum operand_instance
   RegC,  /* %cl / %cx / %ecx / %rcx, e.g. register to hold shift count */
   RegD,  /* %dl / %dx / %edx / %rdx, e.g. register to hold I/O port addr */
   RegB,  /* %bl / %bx / %ebx / %rbx */
+  RegRIP,  /* %rip */
 };
 
 /* Position of operand_type bits.  */
diff --git a/opcodes/i386-opc.tbl b/opcodes/i386-opc.tbl
index bb5dc6799d..370dc10b9e 100644
--- a/opcodes/i386-opc.tbl
+++ b/opcodes/i386-opc.tbl
@@ -40,6 +40,7 @@
 #define RegC Instance=RegC
 #define RegD Instance=RegD
 #define RegB Instance=RegB
+#define RegRIP Instance=RegRIP
 
 #define ShiftCount   RegC|Byte
 #define InOutPortReg RegD|Word
@@ -3323,3 +3324,10 @@ rdmsrlist, 0xf20f01c6, None, CpuMSRLIST|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|N
 wrmsrlist, 0xf30f01c6, None, CpuMSRLIST|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, {}
 
 // MSRLIST instructions end.
+
+// PREFETCHI instructions.
+
+prefetchit0, 0xf18, 0x7, CpuPREFETCHI|Cpu64, Modrm|Anysize|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { RegRIP|BaseIndex }
+prefetchit1, 0xf18, 0x6, CpuPREFETCHI|Cpu64, Modrm|Anysize|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { RegRIP|BaseIndex }
+
+// PREFETCHI instructions end.
-- 
2.17.1
Thanks,
Lili.
  
Jan Beulich Oct. 25, 2022, 3:41 p.m. UTC | #3
On 25.10.2022 15:03, Cui, Lili wrote:
>>> +    {
>>> +      if (ins->intel_syntax)
>>> +	ins->mnemonicendp = stpcpy (ins->obuf, "nop   ");
>>> +      else
>>> +	ins->mnemonicendp = stpcpy (ins->obuf, "nopl  ");
>>
>> Why "nopl"? There's no NP ahead of the opcode (and you also don't go
>> through prefix_table[]), so I expect operand size should be expressed here
>> correctly.
> I changed it to nop.

But that still doesn't correctly express operand size. It needs to
be nopl / nopq / nopw depending on operand size prefix and REX.W.
IOW no different than how this opcode would (hopefully) disassemble
before your change.

Jan
  
Jan Beulich Oct. 25, 2022, 3:52 p.m. UTC | #4
On 25.10.2022 15:03, Cui, Lili wrote:
> @@ -6363,6 +6363,13 @@ check_VecOperands (const insn_template *t)
>  	    i.types[op].bitfield.disp8 = 0;
>  	  }
>      }
> +  /* Check if IP-relative addressing requirements can be satisfied.  */
> +  for (op = 0; op < t->operands; op++)
> +    {
> +      if (t->operand_types[op].bitfield.instance == RegRIP
> +	  && !(i.base_reg && i.base_reg->reg_num == RegIP))
> +	as_warn (_("only support RIP-relative address"));
> +    }

I don't think this function should be checking legacy encoded non-vector
insn properties. I guess this wants moving into the caller; ideally you'd
find an existing loop over all operands where could stick this. This
check, after all, can be done any time after template matching, even as
late as e.g. in build_modrm_byte().

> --- a/opcodes/i386-opc.tbl
> +++ b/opcodes/i386-opc.tbl
> @@ -40,6 +40,7 @@
>  #define RegC Instance=RegC
>  #define RegD Instance=RegD
>  #define RegB Instance=RegB
> +#define RegRIP Instance=RegRIP

This and ...

> @@ -3323,3 +3324,10 @@ rdmsrlist, 0xf20f01c6, None, CpuMSRLIST|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|N
>  wrmsrlist, 0xf30f01c6, None, CpuMSRLIST|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, {}
>  
>  // MSRLIST instructions end.
> +
> +// PREFETCHI instructions.
> +
> +prefetchit0, 0xf18, 0x7, CpuPREFETCHI|Cpu64, Modrm|Anysize|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { RegRIP|BaseIndex }
> +prefetchit1, 0xf18, 0x6, CpuPREFETCHI|Cpu64, Modrm|Anysize|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { RegRIP|BaseIndex }

... its use here is certainly an abuse: The meaning is that plain %rip is
allowed as an operand here. But I take it that you checked thoroughly that
there's not going to be any undue side effect, in which case this might be
acceptable. A better solution would imo be to add a CPU (or opcode, but
that's more expensive) conditional to the check in tc-i386.c.

Jan
  
H.J. Lu Oct. 25, 2022, 5:01 p.m. UTC | #5
On Tue, Oct 25, 2022 at 8:52 AM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 25.10.2022 15:03, Cui, Lili wrote:
> > @@ -6363,6 +6363,13 @@ check_VecOperands (const insn_template *t)
> >           i.types[op].bitfield.disp8 = 0;
> >         }
> >      }
> > +  /* Check if IP-relative addressing requirements can be satisfied.  */
> > +  for (op = 0; op < t->operands; op++)
> > +    {
> > +      if (t->operand_types[op].bitfield.instance == RegRIP
> > +       && !(i.base_reg && i.base_reg->reg_num == RegIP))
> > +     as_warn (_("only support RIP-relative address"));
> > +    }
>
> I don't think this function should be checking legacy encoded non-vector
> insn properties. I guess this wants moving into the caller; ideally you'd
> find an existing loop over all operands where could stick this. This
> check, after all, can be done any time after template matching, even as
> late as e.g. in build_modrm_byte().

This is a special case for instruction prefetch.  We can simply check

  if (i.tm.cpu_flags.bitfield.cpuprefetchi
      && !(i.base_reg && i.base_reg->reg_num == RegIP))

> > --- a/opcodes/i386-opc.tbl
> > +++ b/opcodes/i386-opc.tbl
> > @@ -40,6 +40,7 @@
> >  #define RegC Instance=RegC
> >  #define RegD Instance=RegD
> >  #define RegB Instance=RegB
> > +#define RegRIP Instance=RegRIP
>
> This and ...
>
> > @@ -3323,3 +3324,10 @@ rdmsrlist, 0xf20f01c6, None, CpuMSRLIST|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|N
> >  wrmsrlist, 0xf30f01c6, None, CpuMSRLIST|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, {}
> >
> >  // MSRLIST instructions end.
> > +
> > +// PREFETCHI instructions.
> > +
> > +prefetchit0, 0xf18, 0x7, CpuPREFETCHI|Cpu64, Modrm|Anysize|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { RegRIP|BaseIndex }
> > +prefetchit1, 0xf18, 0x6, CpuPREFETCHI|Cpu64, Modrm|Anysize|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { RegRIP|BaseIndex }
>
> ... its use here is certainly an abuse: The meaning is that plain %rip is
> allowed as an operand here. But I take it that you checked thoroughly that
> there's not going to be any undue side effect, in which case this might be
> acceptable. A better solution would imo be to add a CPU (or opcode, but
> that's more expensive) conditional to the check in tc-i386.c.
>
> Jan
  
Frager, Neal via Binutils Oct. 26, 2022, 1:42 p.m. UTC | #6
> >
> > I don't think this function should be checking legacy encoded
> > non-vector insn properties. I guess this wants moving into the caller;
> > ideally you'd find an existing loop over all operands where could
> > stick this. This check, after all, can be done any time after template
> > matching, even as late as e.g. in build_modrm_byte().
> 
> This is a special case for instruction prefetch.  We can simply check
> 
>   if (i.tm.cpu_flags.bitfield.cpuprefetchi
>       && !(i.base_reg && i.base_reg->reg_num == RegIP))
> 
Done, thanks.

On 25.10.2022 15:03, Cui, Lili wrote:
>>> +    {
>>> +      if (ins->intel_syntax)
>>> +	ins->mnemonicendp = stpcpy (ins->obuf, "nop   ");
>>> +      else
>>> +	ins->mnemonicendp = stpcpy (ins->obuf, "nopl  ");
>>
>> Why "nopl"? There's no NP ahead of the opcode (and you also don't go 
>> through prefix_table[]), so I expect operand size should be expressed 
>> here correctly.
> I changed it to nop.
>
>But that still doesn't correctly express operand size. It needs to be nopl / nopq / nopw depending on operand size prefix and REX.W.
>IOW no different than how this opcode would (hopefully) disassemble before your change.
>
Hi Jan,
Changed it like this. I referenced nopQ, but I don't understand that actually we don't have a 66 prefix, but set DFLAG for it.

+      if (ins->intel_syntax)
+       {
+         ins->mnemonicendp = stpcpy (ins->obuf, "nop   ");
+       }
+      else
+       {
+         if (ins->rex & REX_W)
+           ins->mnemonicendp = stpcpy (ins->obuf, "nopq  ");
+         else
+           {
+             if (sizeflag & DFLAG)
+               ins->mnemonicendp = stpcpy (ins->obuf, "nopl  ");
+             else
+               ins->mnemonicendp = stpcpy (ins->obuf, "nopw  ");
+             ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
+           }
+       }

gas/ChangeLog:

	* NEWS: Add support for Intel PREFETCHI instruction.
	* config/tc-i386.c (load_insn_p): Use prefetch* to fold all prefetches.
	(md_assemble): Add warning for illegal input of PREFETCHI.
	* doc/c-i386.texi: Document .prefetchi.
	* testsuite/gas/i386/i386.exp: Run PREFETCHI tests.
	* testsuite/gas/i386/x86-64-lfence-load.d: Add PREFETCHI.
	* testsuite/gas/i386/x86-64-lfence-load.s: Likewise.
	* testsuite/gas/i386/x86-64-prefetch.d: New test.
	* testsuite/gas/i386/x86-64-prefetchi-intel.d: Likewise.
	* testsuite/gas/i386/x86-64-prefetchi-inval-register.d: Likewise..
	* testsuite/gas/i386/x86-64-prefetchi-inval-register.s: Likewise.
	* testsuite/gas/i386/x86-64-prefetchi-warn.l: Likewise.
	* testsuite/gas/i386/x86-64-prefetchi-warn.s: Likewise.
	* testsuite/gas/i386/x86-64-prefetchi.d: Likewise.
	* testsuite/gas/i386/x86-64-prefetchi.s: Likewise.

opcodes/ChangeLog:

	* i386-dis.c (reg_table): Add MOD_0F18_REG_6 and MOD_0F18_REG_7
	(x86_64_table): Add X86_64_0F18_REG_6_MOD_0 and X86_64_0F18_REG_7_MOD_0.
	(mod_table): Add MOD_0F18_REG_6 and MOD_0F18_REG_7.
	(prefix_table): Add PREFIX_0F18_REG_6_MOD_0_X86_64 and
	PREFIX_0F18_REG_7_MOD_0_X86_64.
	(PREFETCHI_Fixup): New.
	* i386-gen.c (cpu_flag_init): Add CPU_PREFETCHI_FLAGS.
	(cpu_flags): Add CpuPREFETCHI.
	* i386-opc.h (CpuPREFETCHI): New.
	(i386_cpu_flags): Add cpuprefetchi.
	* i386-opc.tbl: Add Intel PREFETCHI instructions.
	* i386-init.h: Regenerated.
	* i386-tbl.h: Likewise.
---
 gas/NEWS                                      |  2 +
 gas/config/tc-i386.c                          | 14 +++-
 gas/doc/c-i386.texi                           |  3 +-
 gas/testsuite/gas/i386/i386.exp               |  4 +
 gas/testsuite/gas/i386/x86-64-lfence-load.d   |  2 +
 gas/testsuite/gas/i386/x86-64-lfence-load.s   |  2 +
 .../gas/i386/x86-64-prefetchi-intel.d         | 16 ++++
 .../i386/x86-64-prefetchi-inval-register.d    | 13 ++++
 .../i386/x86-64-prefetchi-inval-register.s    |  9 +++
 .../gas/i386/x86-64-prefetchi-warn.l          |  5 ++
 .../gas/i386/x86-64-prefetchi-warn.s          | 11 +++
 gas/testsuite/gas/i386/x86-64-prefetchi.d     | 15 ++++
 gas/testsuite/gas/i386/x86-64-prefetchi.s     | 14 ++++
 opcodes/i386-dis.c                            | 77 ++++++++++++++++++-
 opcodes/i386-gen.c                            |  3 +
 opcodes/i386-opc.h                            |  3 +
 opcodes/i386-opc.tbl                          |  7 ++
 17 files changed, 193 insertions(+), 7 deletions(-)
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi-intel.d
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.d
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.s
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi-warn.l
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi-warn.s
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi.d
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi.s

diff --git a/gas/NEWS b/gas/NEWS
index 961449545d..5eb479f5a1 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -1,5 +1,7 @@
 -*- text -*-
 
+* Add support for Intel PREFETCHI instructions.
+
 * Add support for Intel AMX-FP16 instructions.
 
 * Add support for Intel MSRLIST instructions.
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index c1623f216e..d0bbf100e6 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -1102,6 +1102,7 @@ static const arch_entry cpu_arch[] =
   SUBARCH (rao_int, RAO_INT, RAO_INT, false),
   SUBARCH (wrmsrns, WRMSRNS, WRMSRNS, false),
   SUBARCH (msrlist, MSRLIST, MSRLIST, false),
+  SUBARCH (prefetchi, PREFETCHI, PREFETCHI, false),
 };
 
 #undef SUBARCH
@@ -4520,9 +4521,8 @@ load_insn_p (void)
 
   if (!any_vex_p)
     {
-      /* Anysize insns: lea, invlpg, clflush, prefetchnta, prefetcht0,
-	 prefetcht1, prefetcht2, prefetchtw, bndmk, bndcl, bndcu, bndcn,
-	 bndstx, bndldx, prefetchwt1, clflushopt, clwb, cldemote.  */
+      /* Anysize insns: lea, invlpg, clflush, prefetch*, bndmk, bndcl, bndcu,
+	 bndcn, bndstx, bndldx, clflushopt, clwb, cldemote.  */
       if (i.tm.opcode_modifier.anysize)
 	return 0;
 
@@ -5057,9 +5057,15 @@ md_assemble (char *line)
   if (!process_suffix ())
     return;
 
-  /* Update operand types and check extended states.  */
+  /* 1. Update operand types and check extended states. 
+     2. Check IP-relative addressing for prefetchi.  */
   for (j = 0; j < i.operands; j++)
     {
+      /* Check if IP-relative addressing requirements can be satisfied.  */
+      if (i.tm.cpu_flags.bitfield.cpuprefetchi
+	  && !(i.base_reg && i.base_reg->reg_num == RegIP))
+	as_warn (_("only support RIP-relative address"));
+
       i.types[j] = operand_type_and (i.types[j], i.tm.operand_types[j]);
       switch (i.tm.operand_types[j].bitfield.class)
 	{
diff --git a/gas/doc/c-i386.texi b/gas/doc/c-i386.texi
index b33f17c698..fae902c034 100644
--- a/gas/doc/c-i386.texi
+++ b/gas/doc/c-i386.texi
@@ -201,6 +201,7 @@ accept various extension mnemonics.  For example,
 @code{rao_int},
 @code{wrmsrns},
 @code{msrlist},
+@code{prefetchi},
 @code{amx_int8},
 @code{amx_bf16},
 @code{amx_fp16},
@@ -1496,7 +1497,7 @@ supported on the CPU specified.  The choices for @var{cpu_type} are:
 @item @samp{.clwb} @tab @samp{.rdpid} @tab @samp{.ptwrite} @tab @samp{.ibt}
 @item @samp{.avx_ifma} @tab @samp{.avx_vnni_int8} @tab @samp{.avx_ne_convert}
 @item @samp{.cmpccxadd} @tab @samp{.rao_int} @tab @samp{.wrmsrns}
-@item @samp{.msrlist}
+@item @samp{.msrlist} @tab @samp{.prefetchi}
 @item @samp{.wbnoinvd} @tab @samp{.pconfig} @tab @samp{.waitpkg} @tab @samp{.cldemote}
 @item @samp{.shstk} @tab @samp{.gfni} @tab @samp{.vaes} @tab @samp{.vpclmulqdq}
 @item @samp{.movdiri} @tab @samp{.movdir64b} @tab @samp{.enqcmd} @tab @samp{.tsxldtrk}
diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp
index 9f5fa7f612..2081339dc9 100644
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -1209,6 +1209,10 @@ if [gas_64_check] then {
     run_dump_test "x86-64-tdx"
     run_dump_test "x86-64-tsxldtrk"
     run_dump_test "x86-64-hreset"
+    run_dump_test "x86-64-prefetchi"
+    run_dump_test "x86-64-prefetchi-intel"
+    run_dump_test "x86-64-prefetchi-inval-register"
+    run_list_test "x86-64-prefetchi-warn"
     run_dump_test "x86-64-vp2intersect"
     run_dump_test "x86-64-vp2intersect-intel"
     run_list_test "x86-64-vp2intersect-inval-bcast"
diff --git a/gas/testsuite/gas/i386/x86-64-lfence-load.d b/gas/testsuite/gas/i386/x86-64-lfence-load.d
index 2af86fc93f..17c3b9f286 100644
--- a/gas/testsuite/gas/i386/x86-64-lfence-load.d
+++ b/gas/testsuite/gas/i386/x86-64-lfence-load.d
@@ -33,6 +33,8 @@ Disassembly of section .text:
  +[a-f0-9]+:	0f 18 55 00          	prefetcht1 0x0\(%rbp\)
  +[a-f0-9]+:	0f 18 5d 00          	prefetcht2 0x0\(%rbp\)
  +[a-f0-9]+:	0f 0d 4d 00          	prefetchw 0x0\(%rbp\)
+ +[a-f0-9]+:	0f 18 3d 78 56 34 12 	prefetchit0 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+ +[a-f0-9]+:	0f 18 35 78 56 34 12 	prefetchit1 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
  +[a-f0-9]+:	0f a1                	pop    %fs
  +[a-f0-9]+:	0f ae e8             	lfence
  +[a-f0-9]+:	9d                   	popf
diff --git a/gas/testsuite/gas/i386/x86-64-lfence-load.s b/gas/testsuite/gas/i386/x86-64-lfence-load.s
index 2a3ac6b7d2..c478082416 100644
--- a/gas/testsuite/gas/i386/x86-64-lfence-load.s
+++ b/gas/testsuite/gas/i386/x86-64-lfence-load.s
@@ -20,6 +20,8 @@ _start:
 	prefetcht1 (%rbp)
 	prefetcht2 (%rbp)
 	prefetchw (%rbp)
+	prefetchit0 0x12345678(%rip)
+	prefetchit1 0x12345678(%rip)
 	pop %fs
 	popf
 	xlatb (%rbx)
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-intel.d b/gas/testsuite/gas/i386/x86-64-prefetchi-intel.d
new file mode 100644
index 0000000000..7f72f0a1eb
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi-intel.d
@@ -0,0 +1,16 @@
+#as:
+#objdump: -dwMintel
+#name: x86-64 PREFETCHI insns (Intel disassembly)
+#source: x86-64-prefetchi.s
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <_start>:
+[ 	]*[a-f0-9]+:	0f 18 3d 78 56 34 12 	prefetchit0 BYTE PTR \[rip\+0x12345678\]        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 35 78 56 34 12 	prefetchit1 BYTE PTR \[rip\+0x12345678\]        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 3d 78 56 34 12 	prefetchit0 BYTE PTR \[rip\+0x12345678\]        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 35 78 56 34 12 	prefetchit1 BYTE PTR \[rip\+0x12345678\]        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.d b/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.d
new file mode 100644
index 0000000000..b29b1ae237
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.d
@@ -0,0 +1,13 @@
+#as:
+#objdump: -dw
+#name: x86-64 PREFETCHI INVAL REGISTER insns
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <\.text>:
+[ 	]*[a-f0-9]+:[ 	]0f 18 39[ 	]*nopl   \(%rcx\)
+[ 	]*[a-f0-9]+:[ 	]0f 18 31[ 	]*nopl   \(%rcx\)
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.s b/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.s
new file mode 100644
index 0000000000..550449a0c9
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.s
@@ -0,0 +1,9 @@
+.text
+        #prefetchit0 (%rcx) PREFETCHIT0/1 apply without RIP-relative addressing, should stay NOPs.
+        .byte 0x0f
+        .byte 0x18
+        .byte 0x39
+        #prefetchit1 (%rcx) PREFETCHIT1/1 apply without RIP-relative addressing, should stay NOPs.
+        .byte 0x0f
+        .byte 0x18
+        .byte 0x31
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-warn.l b/gas/testsuite/gas/i386/x86-64-prefetchi-warn.l
new file mode 100644
index 0000000000..4e15389463
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi-warn.l
@@ -0,0 +1,5 @@
+.*: Assembler messages:
+.*:[0-9]*: Warning: only support RIP-relative address
+.*:[0-9]*: Warning: only support RIP-relative address
+.*:[0-9]*: Warning: only support RIP-relative address
+.*:[0-9]*: Warning: only support RIP-relative address
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-warn.s b/gas/testsuite/gas/i386/x86-64-prefetchi-warn.s
new file mode 100644
index 0000000000..330ff31c75
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi-warn.s
@@ -0,0 +1,11 @@
+# Check error for ICACHE-PREFETCH 64-bit instruction
+
+	.allow_index_reg
+	.text
+_start:
+	prefetchit0     0x12345678(%rax)
+	prefetchit1     0x12345678(%rax)
+
+	.intel_syntax noprefix
+	prefetchit0     BYTE PTR [rax+0x12345678]
+	prefetchit1     BYTE PTR [rax+0x12345678]
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi.d b/gas/testsuite/gas/i386/x86-64-prefetchi.d
new file mode 100644
index 0000000000..c8ab92d147
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi.d
@@ -0,0 +1,15 @@
+#as:
+#objdump: -dw
+#name: x86-64 PREFETCHI insns
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <_start>:
+[ 	]*[a-f0-9]+:	0f 18 3d 78 56 34 12 	prefetchit0 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 35 78 56 34 12 	prefetchit1 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 3d 78 56 34 12 	prefetchit0 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 35 78 56 34 12 	prefetchit1 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi.s b/gas/testsuite/gas/i386/x86-64-prefetchi.s
new file mode 100644
index 0000000000..cc7c61e9a9
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi.s
@@ -0,0 +1,14 @@
+# Check 64bit PREFETCHI instructions
+
+	.allow_index_reg
+	.text
+_start:
+
+        prefetchit0     0x12345678(%rip)
+        prefetchit1     0x12345678(%rip)
+
+        .intel_syntax noprefix
+
+        prefetchit0     BYTE PTR [rip+0x12345678]
+        prefetchit1     BYTE PTR [rip+0x12345678]
+
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c
index 27ae8eaf46..21db1f9237 100644
--- a/opcodes/i386-dis.c
+++ b/opcodes/i386-dis.c
@@ -114,6 +114,7 @@ static void FXSAVE_Fixup (instr_info *, int, int);
 
 static void MOVSXD_Fixup (instr_info *, int, int);
 static void DistinctDest_Fixup (instr_info *, int, int);
+static void PREFETCHI_Fixup (instr_info *, int, int);
 
 /* This character is used to encode style information within the output
    buffers.  See oappend_insert_style for more details.  */
@@ -841,6 +842,8 @@ enum
   MOD_0F18_REG_1,
   MOD_0F18_REG_2,
   MOD_0F18_REG_3,
+  MOD_0F18_REG_6,
+  MOD_0F18_REG_7,
   MOD_0F1A_PREFIX_0,
   MOD_0F1B_PREFIX_0,
   MOD_0F1B_PREFIX_1,
@@ -1006,6 +1009,8 @@ enum
   PREFIX_0F11,
   PREFIX_0F12,
   PREFIX_0F16,
+  PREFIX_0F18_REG_6_MOD_0_X86_64,
+  PREFIX_0F18_REG_7_MOD_0_X86_64,
   PREFIX_0F1A,
   PREFIX_0F1B,
   PREFIX_0F1C,
@@ -1280,6 +1285,8 @@ enum
   X86_64_0F01_REG_7_MOD_3_RM_6_PREFIX_1,
   X86_64_0F01_REG_7_MOD_3_RM_6_PREFIX_3,
   X86_64_0F01_REG_7_MOD_3_RM_7_PREFIX_1,
+  X86_64_0F18_REG_6_MOD_0,
+  X86_64_0F18_REG_7_MOD_0,
   X86_64_0F24,
   X86_64_0F26,
   X86_64_0FC7_REG_6_MOD_3_PREFIX_1,
@@ -2751,8 +2758,8 @@ static const struct dis386 reg_table[][8] = {
     { MOD_TABLE (MOD_0F18_REG_3) },
     { "nopQ",		{ Ev }, 0 },
     { "nopQ",		{ Ev }, 0 },
-    { "nopQ",		{ Ev }, 0 },
-    { "nopQ",		{ Ev }, 0 },
+    { MOD_TABLE (MOD_0F18_REG_6) },
+    { MOD_TABLE (MOD_0F18_REG_7) },
   },
   /* REG_0F1C_P_0_MOD_0 */
   {
@@ -3118,6 +3125,22 @@ static const struct dis386 prefix_table[][4] = {
     { MOD_TABLE (MOD_0F16_PREFIX_2) },
   },
 
+  /* PREFIX_0F18_REG_6_MOD_0_X86_64 */
+  {
+    { "prefetchit1",	{ { PREFETCHI_Fixup, b_mode } }, 0 },
+    { "nopQ",		{ Ev }, 0 },
+    { "nopQ",		{ Ev }, 0 },
+    { "nopQ",		{ Ev }, 0 },
+  },
+
+  /* PREFIX_0F18_REG_7_MOD_0_X86_64 */
+  {
+    { "prefetchit0",	{ { PREFETCHI_Fixup, b_mode } }, 0 },
+    { "nopQ",		{ Ev }, 0 },
+    { "nopQ",		{ Ev }, 0 },
+    { "nopQ",		{ Ev }, 0 },
+  },
+
   /* PREFIX_0F1A */
   {
     { MOD_TABLE (MOD_0F1A_PREFIX_0) },
@@ -4394,6 +4417,18 @@ static const struct dis386 x86_64_table[][2] = {
     { "psmash",	{ Skip_MODRM }, 0 },
   },
 
+  /* X86_64_0F18_REG_6_MOD_0 */
+  {
+    { "nopQ",		{ Ev }, 0 },
+    { PREFIX_TABLE (PREFIX_0F18_REG_6_MOD_0_X86_64) },
+  },
+
+  /* X86_64_0F18_REG_7_MOD_0 */
+  {
+    { "nopQ",		{ Ev }, 0 },
+    { PREFIX_TABLE (PREFIX_0F18_REG_7_MOD_0_X86_64) },
+  },
+
   {
     /* X86_64_0F24 */
     { "movZ",		{ Em, Td }, 0 },
@@ -8193,6 +8228,16 @@ static const struct dis386 mod_table[][2] = {
     { "prefetcht2",	{ Mb }, 0 },
     { "nopQ",		{ Ev }, 0 },
   },
+  {
+    /* MOD_0F18_REG_6 */
+    { X86_64_TABLE (X86_64_0F18_REG_6_MOD_0) },
+    { "nopQ",		{ Ev }, 0 },
+  },
+  {
+    /* MOD_0F18_REG_7 */
+    { X86_64_TABLE (X86_64_0F18_REG_7_MOD_0) },
+    { "nopQ",		{ Ev }, 0 },
+  },
   {
     /* MOD_0F1A_PREFIX_0 */
     { "bndldx",		{ Gbnd, Mv_bnd }, 0 },
@@ -13940,3 +13985,31 @@ OP_Rounding (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
     }
   oappend (ins, "sae}");
 }
+
+static void
+PREFETCHI_Fixup (instr_info *ins, int bytemode, int sizeflag)
+{
+  if (ins->modrm.mod != 0 || ins->modrm.rm != 5)
+    {
+      if (ins->intel_syntax)
+	{
+	  ins->mnemonicendp = stpcpy (ins->obuf, "nop   ");
+	}
+      else
+	{
+	  if (ins->rex & REX_W)
+	    ins->mnemonicendp = stpcpy (ins->obuf, "nopq  ");
+	  else
+	    {
+	      if (sizeflag & DFLAG)
+		ins->mnemonicendp = stpcpy (ins->obuf, "nopl  ");
+	      else
+		ins->mnemonicendp = stpcpy (ins->obuf, "nopw  ");
+	      ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
+	    }
+	}
+      bytemode = v_mode;
+    }
+
+  OP_M (ins, bytemode, sizeflag);
+}
diff --git a/opcodes/i386-gen.c b/opcodes/i386-gen.c
index 237f147ad4..33339ba840 100644
--- a/opcodes/i386-gen.c
+++ b/opcodes/i386-gen.c
@@ -259,6 +259,8 @@ static initializer cpu_flag_init[] =
     "CpuWRMSRNS" },
   { "CPU_MSRLIST_FLAGS",
     "CpuMSRLIST" },
+  { "CPU_PREFETCHI_FLAGS",
+    "CpuPREFETCHI"},
   { "CPU_IAMCU_FLAGS",
     "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuIAMCU" },
   { "CPU_ADX_FLAGS",
@@ -677,6 +679,7 @@ static bitfield cpu_flags[] =
   BITFIELD (CpuRAO_INT),
   BITFIELD (CpuWRMSRNS),
   BITFIELD (CpuMSRLIST),
+  BITFIELD (CpuPREFETCHI),
   BITFIELD (CpuMWAITX),
   BITFIELD (CpuCLZERO),
   BITFIELD (CpuOSPKE),
diff --git a/opcodes/i386-opc.h b/opcodes/i386-opc.h
index 645abe7f34..1ed319c20b 100644
--- a/opcodes/i386-opc.h
+++ b/opcodes/i386-opc.h
@@ -223,6 +223,8 @@ enum
   CpuWRMSRNS,
   /* Intel MSRLIST Instructions support required.  */
   CpuMSRLIST,
+  /* PREFETCHI instruction required */
+  CpuPREFETCHI,
   /* mwaitx instruction required */
   CpuMWAITX,
   /* Clzero instruction required */
@@ -411,6 +413,7 @@ typedef union i386_cpu_flags
       unsigned int cpurao_int:1;
       unsigned int cpuwrmsrns:1;
       unsigned int cpumsrlist:1;
+      unsigned int cpuprefetchi:1;
       unsigned int cpumwaitx:1;
       unsigned int cpuclzero:1;
       unsigned int cpuospke:1;
diff --git a/opcodes/i386-opc.tbl b/opcodes/i386-opc.tbl
index bb5dc6799d..d63aa1dfb2 100644
--- a/opcodes/i386-opc.tbl
+++ b/opcodes/i386-opc.tbl
@@ -3323,3 +3323,10 @@ rdmsrlist, 0xf20f01c6, None, CpuMSRLIST|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|N
 wrmsrlist, 0xf30f01c6, None, CpuMSRLIST|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, {}
 
 // MSRLIST instructions end.
+
+// PREFETCHI instructions.
+
+prefetchit0, 0xf18, 0x7, CpuPREFETCHI|Cpu64, Modrm|Anysize|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { BaseIndex }
+prefetchit1, 0xf18, 0x6, CpuPREFETCHI|Cpu64, Modrm|Anysize|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { BaseIndex }
+
+// PREFETCHI instructions end.
-- 
2.17.1

Thanks,
Lili.
  
Jan Beulich Oct. 26, 2022, 1:53 p.m. UTC | #7
On 26.10.2022 15:42, Cui, Lili wrote:
> Changed it like this. I referenced nopQ, but I don't understand that actually we don't have a 66 prefix, but set DFLAG for it.

DFLAG represents absolute operand size, i.e. not relative to default
operand size (which would be flipped by a 0x66 prefix).

> +      if (ins->intel_syntax)
> +       {
> +         ins->mnemonicendp = stpcpy (ins->obuf, "nop   ");
> +       }
> +      else
> +       {
> +         if (ins->rex & REX_W)
> +           ins->mnemonicendp = stpcpy (ins->obuf, "nopq  ");

You also want "USED_REX (REX_W)" here (perhaps ahead of the if() to
match the majority of other uses).

Jan

> +         else
> +           {
> +             if (sizeflag & DFLAG)
> +               ins->mnemonicendp = stpcpy (ins->obuf, "nopl  ");
> +             else
> +               ins->mnemonicendp = stpcpy (ins->obuf, "nopw  ");
> +             ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
> +           }
> +       }
  
Frager, Neal via Binutils Oct. 27, 2022, 6:04 a.m. UTC | #8
> On 26.10.2022 15:42, Cui, Lili wrote:
> > Changed it like this. I referenced nopQ, but I don't understand that actually
> we don't have a 66 prefix, but set DFLAG for it.
> 
> DFLAG represents absolute operand size, i.e. not relative to default operand
> size (which would be flipped by a 0x66 prefix).
Got it, thanks.

> 
> > +      if (ins->intel_syntax)
> > +       {
> > +         ins->mnemonicendp = stpcpy (ins->obuf, "nop   ");
> > +       }
> > +      else
> > +       {
> > +         if (ins->rex & REX_W)
> > +           ins->mnemonicendp = stpcpy (ins->obuf, "nopq  ");
> 
> You also want "USED_REX (REX_W)" here (perhaps ahead of the if() to match
> the majority of other uses).
> 
Done, thanks.

> Jan
> 

gas/ChangeLog:

	* NEWS: Add support for Intel PREFETCHI instruction.
	* config/tc-i386.c (load_insn_p): Use prefetch* to fold all prefetches.
	(md_assemble): Add warning for illegal input of PREFETCHI.
	* doc/c-i386.texi: Document .prefetchi.
	* testsuite/gas/i386/i386.exp: Run PREFETCHI tests.
	* testsuite/gas/i386/x86-64-lfence-load.d: Add PREFETCHI.
	* testsuite/gas/i386/x86-64-lfence-load.s: Likewise.
	* testsuite/gas/i386/x86-64-prefetch.d: New test.
	* testsuite/gas/i386/x86-64-prefetchi-intel.d: Likewise.
	* testsuite/gas/i386/x86-64-prefetchi-inval-register.d: Likewise..
	* testsuite/gas/i386/x86-64-prefetchi-inval-register.s: Likewise.
	* testsuite/gas/i386/x86-64-prefetchi-warn.l: Likewise.
	* testsuite/gas/i386/x86-64-prefetchi-warn.s: Likewise.
	* testsuite/gas/i386/x86-64-prefetchi.d: Likewise.
	* testsuite/gas/i386/x86-64-prefetchi.s: Likewise.

opcodes/ChangeLog:

	* i386-dis.c (reg_table): Add MOD_0F18_REG_6 and MOD_0F18_REG_7
	(x86_64_table): Add X86_64_0F18_REG_6_MOD_0 and X86_64_0F18_REG_7_MOD_0.
	(mod_table): Add MOD_0F18_REG_6 and MOD_0F18_REG_7.
	(prefix_table): Add PREFIX_0F18_REG_6_MOD_0_X86_64 and
	PREFIX_0F18_REG_7_MOD_0_X86_64.
	(PREFETCHI_Fixup): New.
	* i386-gen.c (cpu_flag_init): Add CPU_PREFETCHI_FLAGS.
	(cpu_flags): Add CpuPREFETCHI.
	* i386-opc.h (CpuPREFETCHI): New.
	(i386_cpu_flags): Add cpuprefetchi.
	* i386-opc.tbl: Add Intel PREFETCHI instructions.
	* i386-init.h: Regenerated.
	* i386-tbl.h: Likewise.
---
 gas/NEWS                                      |  2 +
 gas/config/tc-i386.c                          | 14 +++-
 gas/doc/c-i386.texi                           |  3 +-
 gas/testsuite/gas/i386/i386.exp               |  4 +
 gas/testsuite/gas/i386/x86-64-lfence-load.d   |  2 +
 gas/testsuite/gas/i386/x86-64-lfence-load.s   |  2 +
 .../gas/i386/x86-64-prefetchi-intel.d         | 16 ++++
 .../i386/x86-64-prefetchi-inval-register.d    | 13 ++++
 .../i386/x86-64-prefetchi-inval-register.s    |  9 +++
 .../gas/i386/x86-64-prefetchi-warn.l          |  5 ++
 .../gas/i386/x86-64-prefetchi-warn.s          | 11 +++
 gas/testsuite/gas/i386/x86-64-prefetchi.d     | 15 ++++
 gas/testsuite/gas/i386/x86-64-prefetchi.s     | 14 ++++
 opcodes/i386-dis.c                            | 78 ++++++++++++++++++-
 opcodes/i386-gen.c                            |  3 +
 opcodes/i386-opc.h                            |  3 +
 opcodes/i386-opc.tbl                          |  7 ++
 17 files changed, 194 insertions(+), 7 deletions(-)
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi-intel.d
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.d
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.s
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi-warn.l
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi-warn.s
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi.d
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi.s

diff --git a/gas/NEWS b/gas/NEWS
index 961449545d..5eb479f5a1 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -1,5 +1,7 @@
 -*- text -*-
 
+* Add support for Intel PREFETCHI instructions.
+
 * Add support for Intel AMX-FP16 instructions.
 
 * Add support for Intel MSRLIST instructions.
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index c1623f216e..d0bbf100e6 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -1102,6 +1102,7 @@ static const arch_entry cpu_arch[] =
   SUBARCH (rao_int, RAO_INT, RAO_INT, false),
   SUBARCH (wrmsrns, WRMSRNS, WRMSRNS, false),
   SUBARCH (msrlist, MSRLIST, MSRLIST, false),
+  SUBARCH (prefetchi, PREFETCHI, PREFETCHI, false),
 };
 
 #undef SUBARCH
@@ -4520,9 +4521,8 @@ load_insn_p (void)
 
   if (!any_vex_p)
     {
-      /* Anysize insns: lea, invlpg, clflush, prefetchnta, prefetcht0,
-	 prefetcht1, prefetcht2, prefetchtw, bndmk, bndcl, bndcu, bndcn,
-	 bndstx, bndldx, prefetchwt1, clflushopt, clwb, cldemote.  */
+      /* Anysize insns: lea, invlpg, clflush, prefetch*, bndmk, bndcl, bndcu,
+	 bndcn, bndstx, bndldx, clflushopt, clwb, cldemote.  */
       if (i.tm.opcode_modifier.anysize)
 	return 0;
 
@@ -5057,9 +5057,15 @@ md_assemble (char *line)
   if (!process_suffix ())
     return;
 
-  /* Update operand types and check extended states.  */
+  /* 1. Update operand types and check extended states. 
+     2. Check IP-relative addressing for prefetchi.  */
   for (j = 0; j < i.operands; j++)
     {
+      /* Check if IP-relative addressing requirements can be satisfied.  */
+      if (i.tm.cpu_flags.bitfield.cpuprefetchi
+	  && !(i.base_reg && i.base_reg->reg_num == RegIP))
+	as_warn (_("only support RIP-relative address"));
+
       i.types[j] = operand_type_and (i.types[j], i.tm.operand_types[j]);
       switch (i.tm.operand_types[j].bitfield.class)
 	{
diff --git a/gas/doc/c-i386.texi b/gas/doc/c-i386.texi
index b33f17c698..fae902c034 100644
--- a/gas/doc/c-i386.texi
+++ b/gas/doc/c-i386.texi
@@ -201,6 +201,7 @@ accept various extension mnemonics.  For example,
 @code{rao_int},
 @code{wrmsrns},
 @code{msrlist},
+@code{prefetchi},
 @code{amx_int8},
 @code{amx_bf16},
 @code{amx_fp16},
@@ -1496,7 +1497,7 @@ supported on the CPU specified.  The choices for @var{cpu_type} are:
 @item @samp{.clwb} @tab @samp{.rdpid} @tab @samp{.ptwrite} @tab @samp{.ibt}
 @item @samp{.avx_ifma} @tab @samp{.avx_vnni_int8} @tab @samp{.avx_ne_convert}
 @item @samp{.cmpccxadd} @tab @samp{.rao_int} @tab @samp{.wrmsrns}
-@item @samp{.msrlist}
+@item @samp{.msrlist} @tab @samp{.prefetchi}
 @item @samp{.wbnoinvd} @tab @samp{.pconfig} @tab @samp{.waitpkg} @tab @samp{.cldemote}
 @item @samp{.shstk} @tab @samp{.gfni} @tab @samp{.vaes} @tab @samp{.vpclmulqdq}
 @item @samp{.movdiri} @tab @samp{.movdir64b} @tab @samp{.enqcmd} @tab @samp{.tsxldtrk}
diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp
index 9f5fa7f612..2081339dc9 100644
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -1209,6 +1209,10 @@ if [gas_64_check] then {
     run_dump_test "x86-64-tdx"
     run_dump_test "x86-64-tsxldtrk"
     run_dump_test "x86-64-hreset"
+    run_dump_test "x86-64-prefetchi"
+    run_dump_test "x86-64-prefetchi-intel"
+    run_dump_test "x86-64-prefetchi-inval-register"
+    run_list_test "x86-64-prefetchi-warn"
     run_dump_test "x86-64-vp2intersect"
     run_dump_test "x86-64-vp2intersect-intel"
     run_list_test "x86-64-vp2intersect-inval-bcast"
diff --git a/gas/testsuite/gas/i386/x86-64-lfence-load.d b/gas/testsuite/gas/i386/x86-64-lfence-load.d
index 2af86fc93f..17c3b9f286 100644
--- a/gas/testsuite/gas/i386/x86-64-lfence-load.d
+++ b/gas/testsuite/gas/i386/x86-64-lfence-load.d
@@ -33,6 +33,8 @@ Disassembly of section .text:
  +[a-f0-9]+:	0f 18 55 00          	prefetcht1 0x0\(%rbp\)
  +[a-f0-9]+:	0f 18 5d 00          	prefetcht2 0x0\(%rbp\)
  +[a-f0-9]+:	0f 0d 4d 00          	prefetchw 0x0\(%rbp\)
+ +[a-f0-9]+:	0f 18 3d 78 56 34 12 	prefetchit0 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+ +[a-f0-9]+:	0f 18 35 78 56 34 12 	prefetchit1 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
  +[a-f0-9]+:	0f a1                	pop    %fs
  +[a-f0-9]+:	0f ae e8             	lfence
  +[a-f0-9]+:	9d                   	popf
diff --git a/gas/testsuite/gas/i386/x86-64-lfence-load.s b/gas/testsuite/gas/i386/x86-64-lfence-load.s
index 2a3ac6b7d2..c478082416 100644
--- a/gas/testsuite/gas/i386/x86-64-lfence-load.s
+++ b/gas/testsuite/gas/i386/x86-64-lfence-load.s
@@ -20,6 +20,8 @@ _start:
 	prefetcht1 (%rbp)
 	prefetcht2 (%rbp)
 	prefetchw (%rbp)
+	prefetchit0 0x12345678(%rip)
+	prefetchit1 0x12345678(%rip)
 	pop %fs
 	popf
 	xlatb (%rbx)
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-intel.d b/gas/testsuite/gas/i386/x86-64-prefetchi-intel.d
new file mode 100644
index 0000000000..7f72f0a1eb
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi-intel.d
@@ -0,0 +1,16 @@
+#as:
+#objdump: -dwMintel
+#name: x86-64 PREFETCHI insns (Intel disassembly)
+#source: x86-64-prefetchi.s
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <_start>:
+[ 	]*[a-f0-9]+:	0f 18 3d 78 56 34 12 	prefetchit0 BYTE PTR \[rip\+0x12345678\]        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 35 78 56 34 12 	prefetchit1 BYTE PTR \[rip\+0x12345678\]        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 3d 78 56 34 12 	prefetchit0 BYTE PTR \[rip\+0x12345678\]        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 35 78 56 34 12 	prefetchit1 BYTE PTR \[rip\+0x12345678\]        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.d b/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.d
new file mode 100644
index 0000000000..b29b1ae237
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.d
@@ -0,0 +1,13 @@
+#as:
+#objdump: -dw
+#name: x86-64 PREFETCHI INVAL REGISTER insns
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <\.text>:
+[ 	]*[a-f0-9]+:[ 	]0f 18 39[ 	]*nopl   \(%rcx\)
+[ 	]*[a-f0-9]+:[ 	]0f 18 31[ 	]*nopl   \(%rcx\)
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.s b/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.s
new file mode 100644
index 0000000000..550449a0c9
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.s
@@ -0,0 +1,9 @@
+.text
+        #prefetchit0 (%rcx) PREFETCHIT0/1 apply without RIP-relative addressing, should stay NOPs.
+        .byte 0x0f
+        .byte 0x18
+        .byte 0x39
+        #prefetchit1 (%rcx) PREFETCHIT1/1 apply without RIP-relative addressing, should stay NOPs.
+        .byte 0x0f
+        .byte 0x18
+        .byte 0x31
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-warn.l b/gas/testsuite/gas/i386/x86-64-prefetchi-warn.l
new file mode 100644
index 0000000000..4e15389463
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi-warn.l
@@ -0,0 +1,5 @@
+.*: Assembler messages:
+.*:[0-9]*: Warning: only support RIP-relative address
+.*:[0-9]*: Warning: only support RIP-relative address
+.*:[0-9]*: Warning: only support RIP-relative address
+.*:[0-9]*: Warning: only support RIP-relative address
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-warn.s b/gas/testsuite/gas/i386/x86-64-prefetchi-warn.s
new file mode 100644
index 0000000000..330ff31c75
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi-warn.s
@@ -0,0 +1,11 @@
+# Check error for ICACHE-PREFETCH 64-bit instruction
+
+	.allow_index_reg
+	.text
+_start:
+	prefetchit0     0x12345678(%rax)
+	prefetchit1     0x12345678(%rax)
+
+	.intel_syntax noprefix
+	prefetchit0     BYTE PTR [rax+0x12345678]
+	prefetchit1     BYTE PTR [rax+0x12345678]
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi.d b/gas/testsuite/gas/i386/x86-64-prefetchi.d
new file mode 100644
index 0000000000..c8ab92d147
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi.d
@@ -0,0 +1,15 @@
+#as:
+#objdump: -dw
+#name: x86-64 PREFETCHI insns
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <_start>:
+[ 	]*[a-f0-9]+:	0f 18 3d 78 56 34 12 	prefetchit0 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 35 78 56 34 12 	prefetchit1 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 3d 78 56 34 12 	prefetchit0 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 35 78 56 34 12 	prefetchit1 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi.s b/gas/testsuite/gas/i386/x86-64-prefetchi.s
new file mode 100644
index 0000000000..cc7c61e9a9
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi.s
@@ -0,0 +1,14 @@
+# Check 64bit PREFETCHI instructions
+
+	.allow_index_reg
+	.text
+_start:
+
+        prefetchit0     0x12345678(%rip)
+        prefetchit1     0x12345678(%rip)
+
+        .intel_syntax noprefix
+
+        prefetchit0     BYTE PTR [rip+0x12345678]
+        prefetchit1     BYTE PTR [rip+0x12345678]
+
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c
index 27ae8eaf46..9ef3d7a6ae 100644
--- a/opcodes/i386-dis.c
+++ b/opcodes/i386-dis.c
@@ -114,6 +114,7 @@ static void FXSAVE_Fixup (instr_info *, int, int);
 
 static void MOVSXD_Fixup (instr_info *, int, int);
 static void DistinctDest_Fixup (instr_info *, int, int);
+static void PREFETCHI_Fixup (instr_info *, int, int);
 
 /* This character is used to encode style information within the output
    buffers.  See oappend_insert_style for more details.  */
@@ -841,6 +842,8 @@ enum
   MOD_0F18_REG_1,
   MOD_0F18_REG_2,
   MOD_0F18_REG_3,
+  MOD_0F18_REG_6,
+  MOD_0F18_REG_7,
   MOD_0F1A_PREFIX_0,
   MOD_0F1B_PREFIX_0,
   MOD_0F1B_PREFIX_1,
@@ -1006,6 +1009,8 @@ enum
   PREFIX_0F11,
   PREFIX_0F12,
   PREFIX_0F16,
+  PREFIX_0F18_REG_6_MOD_0_X86_64,
+  PREFIX_0F18_REG_7_MOD_0_X86_64,
   PREFIX_0F1A,
   PREFIX_0F1B,
   PREFIX_0F1C,
@@ -1280,6 +1285,8 @@ enum
   X86_64_0F01_REG_7_MOD_3_RM_6_PREFIX_1,
   X86_64_0F01_REG_7_MOD_3_RM_6_PREFIX_3,
   X86_64_0F01_REG_7_MOD_3_RM_7_PREFIX_1,
+  X86_64_0F18_REG_6_MOD_0,
+  X86_64_0F18_REG_7_MOD_0,
   X86_64_0F24,
   X86_64_0F26,
   X86_64_0FC7_REG_6_MOD_3_PREFIX_1,
@@ -2751,8 +2758,8 @@ static const struct dis386 reg_table[][8] = {
     { MOD_TABLE (MOD_0F18_REG_3) },
     { "nopQ",		{ Ev }, 0 },
     { "nopQ",		{ Ev }, 0 },
-    { "nopQ",		{ Ev }, 0 },
-    { "nopQ",		{ Ev }, 0 },
+    { MOD_TABLE (MOD_0F18_REG_6) },
+    { MOD_TABLE (MOD_0F18_REG_7) },
   },
   /* REG_0F1C_P_0_MOD_0 */
   {
@@ -3118,6 +3125,22 @@ static const struct dis386 prefix_table[][4] = {
     { MOD_TABLE (MOD_0F16_PREFIX_2) },
   },
 
+  /* PREFIX_0F18_REG_6_MOD_0_X86_64 */
+  {
+    { "prefetchit1",	{ { PREFETCHI_Fixup, b_mode } }, 0 },
+    { "nopQ",		{ Ev }, 0 },
+    { "nopQ",		{ Ev }, 0 },
+    { "nopQ",		{ Ev }, 0 },
+  },
+
+  /* PREFIX_0F18_REG_7_MOD_0_X86_64 */
+  {
+    { "prefetchit0",	{ { PREFETCHI_Fixup, b_mode } }, 0 },
+    { "nopQ",		{ Ev }, 0 },
+    { "nopQ",		{ Ev }, 0 },
+    { "nopQ",		{ Ev }, 0 },
+  },
+
   /* PREFIX_0F1A */
   {
     { MOD_TABLE (MOD_0F1A_PREFIX_0) },
@@ -4394,6 +4417,18 @@ static const struct dis386 x86_64_table[][2] = {
     { "psmash",	{ Skip_MODRM }, 0 },
   },
 
+  /* X86_64_0F18_REG_6_MOD_0 */
+  {
+    { "nopQ",		{ Ev }, 0 },
+    { PREFIX_TABLE (PREFIX_0F18_REG_6_MOD_0_X86_64) },
+  },
+
+  /* X86_64_0F18_REG_7_MOD_0 */
+  {
+    { "nopQ",		{ Ev }, 0 },
+    { PREFIX_TABLE (PREFIX_0F18_REG_7_MOD_0_X86_64) },
+  },
+
   {
     /* X86_64_0F24 */
     { "movZ",		{ Em, Td }, 0 },
@@ -8193,6 +8228,16 @@ static const struct dis386 mod_table[][2] = {
     { "prefetcht2",	{ Mb }, 0 },
     { "nopQ",		{ Ev }, 0 },
   },
+  {
+    /* MOD_0F18_REG_6 */
+    { X86_64_TABLE (X86_64_0F18_REG_6_MOD_0) },
+    { "nopQ",		{ Ev }, 0 },
+  },
+  {
+    /* MOD_0F18_REG_7 */
+    { X86_64_TABLE (X86_64_0F18_REG_7_MOD_0) },
+    { "nopQ",		{ Ev }, 0 },
+  },
   {
     /* MOD_0F1A_PREFIX_0 */
     { "bndldx",		{ Gbnd, Mv_bnd }, 0 },
@@ -13940,3 +13985,32 @@ OP_Rounding (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
     }
   oappend (ins, "sae}");
 }
+
+static void
+PREFETCHI_Fixup (instr_info *ins, int bytemode, int sizeflag)
+{
+  if (ins->modrm.mod != 0 || ins->modrm.rm != 5)
+    {
+      if (ins->intel_syntax)
+	{
+	  ins->mnemonicendp = stpcpy (ins->obuf, "nop   ");
+	}
+      else
+	{
+	  USED_REX (REX_W);
+	  if (ins->rex & REX_W)
+	    ins->mnemonicendp = stpcpy (ins->obuf, "nopq  ");
+	  else
+	    {
+	      if (sizeflag & DFLAG)
+		ins->mnemonicendp = stpcpy (ins->obuf, "nopl  ");
+	      else
+		ins->mnemonicendp = stpcpy (ins->obuf, "nopw  ");
+	      ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
+	    }
+	}
+      bytemode = v_mode;
+    }
+
+  OP_M (ins, bytemode, sizeflag);
+}
diff --git a/opcodes/i386-gen.c b/opcodes/i386-gen.c
index 237f147ad4..33339ba840 100644
--- a/opcodes/i386-gen.c
+++ b/opcodes/i386-gen.c
@@ -259,6 +259,8 @@ static initializer cpu_flag_init[] =
     "CpuWRMSRNS" },
   { "CPU_MSRLIST_FLAGS",
     "CpuMSRLIST" },
+  { "CPU_PREFETCHI_FLAGS",
+    "CpuPREFETCHI"},
   { "CPU_IAMCU_FLAGS",
     "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuIAMCU" },
   { "CPU_ADX_FLAGS",
@@ -677,6 +679,7 @@ static bitfield cpu_flags[] =
   BITFIELD (CpuRAO_INT),
   BITFIELD (CpuWRMSRNS),
   BITFIELD (CpuMSRLIST),
+  BITFIELD (CpuPREFETCHI),
   BITFIELD (CpuMWAITX),
   BITFIELD (CpuCLZERO),
   BITFIELD (CpuOSPKE),
diff --git a/opcodes/i386-opc.h b/opcodes/i386-opc.h
index 645abe7f34..1ed319c20b 100644
--- a/opcodes/i386-opc.h
+++ b/opcodes/i386-opc.h
@@ -223,6 +223,8 @@ enum
   CpuWRMSRNS,
   /* Intel MSRLIST Instructions support required.  */
   CpuMSRLIST,
+  /* PREFETCHI instruction required */
+  CpuPREFETCHI,
   /* mwaitx instruction required */
   CpuMWAITX,
   /* Clzero instruction required */
@@ -411,6 +413,7 @@ typedef union i386_cpu_flags
       unsigned int cpurao_int:1;
       unsigned int cpuwrmsrns:1;
       unsigned int cpumsrlist:1;
+      unsigned int cpuprefetchi:1;
       unsigned int cpumwaitx:1;
       unsigned int cpuclzero:1;
       unsigned int cpuospke:1;
diff --git a/opcodes/i386-opc.tbl b/opcodes/i386-opc.tbl
index bb5dc6799d..d63aa1dfb2 100644
--- a/opcodes/i386-opc.tbl
+++ b/opcodes/i386-opc.tbl
@@ -3323,3 +3323,10 @@ rdmsrlist, 0xf20f01c6, None, CpuMSRLIST|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|N
 wrmsrlist, 0xf30f01c6, None, CpuMSRLIST|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, {}
 
 // MSRLIST instructions end.
+
+// PREFETCHI instructions.
+
+prefetchit0, 0xf18, 0x7, CpuPREFETCHI|Cpu64, Modrm|Anysize|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { BaseIndex }
+prefetchit1, 0xf18, 0x6, CpuPREFETCHI|Cpu64, Modrm|Anysize|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { BaseIndex }
+
+// PREFETCHI instructions end.
-- 
2.17.1

Regards,
Lili.
  
Jan Beulich Oct. 27, 2022, 6:45 a.m. UTC | #9
On 27.10.2022 08:04, Cui, Lili wrote:> @@ -5057,9 +5057,15 @@ md_assemble (char *line)
>    if (!process_suffix ())
>      return;
>  
> -  /* Update operand types and check extended states.  */
> +  /* 1. Update operand types and check extended states. 
> +     2. Check IP-relative addressing for prefetchi.  */
>    for (j = 0; j < i.operands; j++)
>      {
> +      /* Check if IP-relative addressing requirements can be satisfied.  */
> +      if (i.tm.cpu_flags.bitfield.cpuprefetchi
> +	  && !(i.base_reg && i.base_reg->reg_num == RegIP))
> +	as_warn (_("only support RIP-relative address"));

One final suggestion:

	as_warn (_("`%s' only supports RIP-relative address"), i.tm.name);

And maybe also keep code and comment in sync as to the sequence of
things done.

Jan
  
Frager, Neal via Binutils Oct. 27, 2022, 7:01 a.m. UTC | #10
> > -  /* Update operand types and check extended states.  */
> > +  /* 1. Update operand types and check extended states.
> > +     2. Check IP-relative addressing for prefetchi.  */
> >    for (j = 0; j < i.operands; j++)
> >      {
> > +      /* Check if IP-relative addressing requirements can be satisfied.  */
> > +      if (i.tm.cpu_flags.bitfield.cpuprefetchi
> > +	  && !(i.base_reg && i.base_reg->reg_num == RegIP))
> > +	as_warn (_("only support RIP-relative address"));
> 
> One final suggestion:
> 
> 	as_warn (_("`%s' only supports RIP-relative address"), i.tm.name);
> 
Done.

> And maybe also keep code and comment in sync as to the sequence of
> things done.
> 
Changed, thanks Jan.

> Jan


gas/ChangeLog:

	* NEWS: Add support for Intel PREFETCHI instruction.
	* config/tc-i386.c (load_insn_p): Use prefetch* to fold all prefetches.
	(md_assemble): Add warning for illegal input of PREFETCHI.
	* doc/c-i386.texi: Document .prefetchi.
	* testsuite/gas/i386/i386.exp: Run PREFETCHI tests.
	* testsuite/gas/i386/x86-64-lfence-load.d: Add PREFETCHI.
	* testsuite/gas/i386/x86-64-lfence-load.s: Likewise.
	* testsuite/gas/i386/x86-64-prefetch.d: New test.
	* testsuite/gas/i386/x86-64-prefetchi-intel.d: Likewise.
	* testsuite/gas/i386/x86-64-prefetchi-inval-register.d: Likewise..
	* testsuite/gas/i386/x86-64-prefetchi-inval-register.s: Likewise.
	* testsuite/gas/i386/x86-64-prefetchi-warn.l: Likewise.
	* testsuite/gas/i386/x86-64-prefetchi-warn.s: Likewise.
	* testsuite/gas/i386/x86-64-prefetchi.d: Likewise.
	* testsuite/gas/i386/x86-64-prefetchi.s: Likewise.

opcodes/ChangeLog:

	* i386-dis.c (reg_table): Add MOD_0F18_REG_6 and MOD_0F18_REG_7
	(x86_64_table): Add X86_64_0F18_REG_6_MOD_0 and X86_64_0F18_REG_7_MOD_0.
	(mod_table): Add MOD_0F18_REG_6 and MOD_0F18_REG_7.
	(prefix_table): Add PREFIX_0F18_REG_6_MOD_0_X86_64 and
	PREFIX_0F18_REG_7_MOD_0_X86_64.
	(PREFETCHI_Fixup): New.
	* i386-gen.c (cpu_flag_init): Add CPU_PREFETCHI_FLAGS.
	(cpu_flags): Add CpuPREFETCHI.
	* i386-opc.h (CpuPREFETCHI): New.
	(i386_cpu_flags): Add cpuprefetchi.
	* i386-opc.tbl: Add Intel PREFETCHI instructions.
	* i386-init.h: Regenerated.
	* i386-tbl.h: Likewise.
---
 gas/NEWS                                      |  2 +
 gas/config/tc-i386.c                          | 14 +++-
 gas/doc/c-i386.texi                           |  3 +-
 gas/testsuite/gas/i386/i386.exp               |  4 +
 gas/testsuite/gas/i386/x86-64-lfence-load.d   |  2 +
 gas/testsuite/gas/i386/x86-64-lfence-load.s   |  2 +
 .../gas/i386/x86-64-prefetchi-intel.d         | 16 ++++
 .../i386/x86-64-prefetchi-inval-register.d    | 13 ++++
 .../i386/x86-64-prefetchi-inval-register.s    |  9 +++
 .../gas/i386/x86-64-prefetchi-warn.l          |  5 ++
 .../gas/i386/x86-64-prefetchi-warn.s          | 11 +++
 gas/testsuite/gas/i386/x86-64-prefetchi.d     | 15 ++++
 gas/testsuite/gas/i386/x86-64-prefetchi.s     | 14 ++++
 opcodes/i386-dis.c                            | 78 ++++++++++++++++++-
 opcodes/i386-gen.c                            |  3 +
 opcodes/i386-opc.h                            |  3 +
 opcodes/i386-opc.tbl                          |  7 ++
 17 files changed, 194 insertions(+), 7 deletions(-)
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi-intel.d
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.d
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.s
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi-warn.l
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi-warn.s
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi.d
 create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi.s

diff --git a/gas/NEWS b/gas/NEWS
index 961449545d..5eb479f5a1 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -1,5 +1,7 @@
 -*- text -*-
 
+* Add support for Intel PREFETCHI instructions.
+
 * Add support for Intel AMX-FP16 instructions.
 
 * Add support for Intel MSRLIST instructions.
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index c1623f216e..52993dfbd9 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -1102,6 +1102,7 @@ static const arch_entry cpu_arch[] =
   SUBARCH (rao_int, RAO_INT, RAO_INT, false),
   SUBARCH (wrmsrns, WRMSRNS, WRMSRNS, false),
   SUBARCH (msrlist, MSRLIST, MSRLIST, false),
+  SUBARCH (prefetchi, PREFETCHI, PREFETCHI, false),
 };
 
 #undef SUBARCH
@@ -4520,9 +4521,8 @@ load_insn_p (void)
 
   if (!any_vex_p)
     {
-      /* Anysize insns: lea, invlpg, clflush, prefetchnta, prefetcht0,
-	 prefetcht1, prefetcht2, prefetchtw, bndmk, bndcl, bndcu, bndcn,
-	 bndstx, bndldx, prefetchwt1, clflushopt, clwb, cldemote.  */
+      /* Anysize insns: lea, invlpg, clflush, prefetch*, bndmk, bndcl, bndcu,
+	 bndcn, bndstx, bndldx, clflushopt, clwb, cldemote.  */
       if (i.tm.opcode_modifier.anysize)
 	return 0;
 
@@ -5057,9 +5057,15 @@ md_assemble (char *line)
   if (!process_suffix ())
     return;
 
-  /* Update operand types and check extended states.  */
+  /* 1. Check IP-relative addressing for prefetchi. 
+     2. Update operand types and check extended states.  */
   for (j = 0; j < i.operands; j++)
     {
+      /* Check if IP-relative addressing requirements can be satisfied.  */
+      if (i.tm.cpu_flags.bitfield.cpuprefetchi
+	  && !(i.base_reg && i.base_reg->reg_num == RegIP))
+	as_warn (_("only support RIP-relative address"), i.tm.name);
+
       i.types[j] = operand_type_and (i.types[j], i.tm.operand_types[j]);
       switch (i.tm.operand_types[j].bitfield.class)
 	{
diff --git a/gas/doc/c-i386.texi b/gas/doc/c-i386.texi
index b33f17c698..fae902c034 100644
--- a/gas/doc/c-i386.texi
+++ b/gas/doc/c-i386.texi
@@ -201,6 +201,7 @@ accept various extension mnemonics.  For example,
 @code{rao_int},
 @code{wrmsrns},
 @code{msrlist},
+@code{prefetchi},
 @code{amx_int8},
 @code{amx_bf16},
 @code{amx_fp16},
@@ -1496,7 +1497,7 @@ supported on the CPU specified.  The choices for @var{cpu_type} are:
 @item @samp{.clwb} @tab @samp{.rdpid} @tab @samp{.ptwrite} @tab @samp{.ibt}
 @item @samp{.avx_ifma} @tab @samp{.avx_vnni_int8} @tab @samp{.avx_ne_convert}
 @item @samp{.cmpccxadd} @tab @samp{.rao_int} @tab @samp{.wrmsrns}
-@item @samp{.msrlist}
+@item @samp{.msrlist} @tab @samp{.prefetchi}
 @item @samp{.wbnoinvd} @tab @samp{.pconfig} @tab @samp{.waitpkg} @tab @samp{.cldemote}
 @item @samp{.shstk} @tab @samp{.gfni} @tab @samp{.vaes} @tab @samp{.vpclmulqdq}
 @item @samp{.movdiri} @tab @samp{.movdir64b} @tab @samp{.enqcmd} @tab @samp{.tsxldtrk}
diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp
index 9f5fa7f612..2081339dc9 100644
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -1209,6 +1209,10 @@ if [gas_64_check] then {
     run_dump_test "x86-64-tdx"
     run_dump_test "x86-64-tsxldtrk"
     run_dump_test "x86-64-hreset"
+    run_dump_test "x86-64-prefetchi"
+    run_dump_test "x86-64-prefetchi-intel"
+    run_dump_test "x86-64-prefetchi-inval-register"
+    run_list_test "x86-64-prefetchi-warn"
     run_dump_test "x86-64-vp2intersect"
     run_dump_test "x86-64-vp2intersect-intel"
     run_list_test "x86-64-vp2intersect-inval-bcast"
diff --git a/gas/testsuite/gas/i386/x86-64-lfence-load.d b/gas/testsuite/gas/i386/x86-64-lfence-load.d
index 2af86fc93f..17c3b9f286 100644
--- a/gas/testsuite/gas/i386/x86-64-lfence-load.d
+++ b/gas/testsuite/gas/i386/x86-64-lfence-load.d
@@ -33,6 +33,8 @@ Disassembly of section .text:
  +[a-f0-9]+:	0f 18 55 00          	prefetcht1 0x0\(%rbp\)
  +[a-f0-9]+:	0f 18 5d 00          	prefetcht2 0x0\(%rbp\)
  +[a-f0-9]+:	0f 0d 4d 00          	prefetchw 0x0\(%rbp\)
+ +[a-f0-9]+:	0f 18 3d 78 56 34 12 	prefetchit0 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+ +[a-f0-9]+:	0f 18 35 78 56 34 12 	prefetchit1 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
  +[a-f0-9]+:	0f a1                	pop    %fs
  +[a-f0-9]+:	0f ae e8             	lfence
  +[a-f0-9]+:	9d                   	popf
diff --git a/gas/testsuite/gas/i386/x86-64-lfence-load.s b/gas/testsuite/gas/i386/x86-64-lfence-load.s
index 2a3ac6b7d2..c478082416 100644
--- a/gas/testsuite/gas/i386/x86-64-lfence-load.s
+++ b/gas/testsuite/gas/i386/x86-64-lfence-load.s
@@ -20,6 +20,8 @@ _start:
 	prefetcht1 (%rbp)
 	prefetcht2 (%rbp)
 	prefetchw (%rbp)
+	prefetchit0 0x12345678(%rip)
+	prefetchit1 0x12345678(%rip)
 	pop %fs
 	popf
 	xlatb (%rbx)
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-intel.d b/gas/testsuite/gas/i386/x86-64-prefetchi-intel.d
new file mode 100644
index 0000000000..7f72f0a1eb
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi-intel.d
@@ -0,0 +1,16 @@
+#as:
+#objdump: -dwMintel
+#name: x86-64 PREFETCHI insns (Intel disassembly)
+#source: x86-64-prefetchi.s
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <_start>:
+[ 	]*[a-f0-9]+:	0f 18 3d 78 56 34 12 	prefetchit0 BYTE PTR \[rip\+0x12345678\]        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 35 78 56 34 12 	prefetchit1 BYTE PTR \[rip\+0x12345678\]        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 3d 78 56 34 12 	prefetchit0 BYTE PTR \[rip\+0x12345678\]        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 35 78 56 34 12 	prefetchit1 BYTE PTR \[rip\+0x12345678\]        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.d b/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.d
new file mode 100644
index 0000000000..b29b1ae237
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.d
@@ -0,0 +1,13 @@
+#as:
+#objdump: -dw
+#name: x86-64 PREFETCHI INVAL REGISTER insns
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <\.text>:
+[ 	]*[a-f0-9]+:[ 	]0f 18 39[ 	]*nopl   \(%rcx\)
+[ 	]*[a-f0-9]+:[ 	]0f 18 31[ 	]*nopl   \(%rcx\)
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.s b/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.s
new file mode 100644
index 0000000000..550449a0c9
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.s
@@ -0,0 +1,9 @@
+.text
+        #prefetchit0 (%rcx) PREFETCHIT0/1 apply without RIP-relative addressing, should stay NOPs.
+        .byte 0x0f
+        .byte 0x18
+        .byte 0x39
+        #prefetchit1 (%rcx) PREFETCHIT1/1 apply without RIP-relative addressing, should stay NOPs.
+        .byte 0x0f
+        .byte 0x18
+        .byte 0x31
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-warn.l b/gas/testsuite/gas/i386/x86-64-prefetchi-warn.l
new file mode 100644
index 0000000000..4e15389463
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi-warn.l
@@ -0,0 +1,5 @@
+.*: Assembler messages:
+.*:[0-9]*: Warning: only support RIP-relative address
+.*:[0-9]*: Warning: only support RIP-relative address
+.*:[0-9]*: Warning: only support RIP-relative address
+.*:[0-9]*: Warning: only support RIP-relative address
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-warn.s b/gas/testsuite/gas/i386/x86-64-prefetchi-warn.s
new file mode 100644
index 0000000000..330ff31c75
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi-warn.s
@@ -0,0 +1,11 @@
+# Check error for ICACHE-PREFETCH 64-bit instruction
+
+	.allow_index_reg
+	.text
+_start:
+	prefetchit0     0x12345678(%rax)
+	prefetchit1     0x12345678(%rax)
+
+	.intel_syntax noprefix
+	prefetchit0     BYTE PTR [rax+0x12345678]
+	prefetchit1     BYTE PTR [rax+0x12345678]
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi.d b/gas/testsuite/gas/i386/x86-64-prefetchi.d
new file mode 100644
index 0000000000..c8ab92d147
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi.d
@@ -0,0 +1,15 @@
+#as:
+#objdump: -dw
+#name: x86-64 PREFETCHI insns
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <_start>:
+[ 	]*[a-f0-9]+:	0f 18 3d 78 56 34 12 	prefetchit0 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 35 78 56 34 12 	prefetchit1 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 3d 78 56 34 12 	prefetchit0 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 35 78 56 34 12 	prefetchit1 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi.s b/gas/testsuite/gas/i386/x86-64-prefetchi.s
new file mode 100644
index 0000000000..cc7c61e9a9
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi.s
@@ -0,0 +1,14 @@
+# Check 64bit PREFETCHI instructions
+
+	.allow_index_reg
+	.text
+_start:
+
+        prefetchit0     0x12345678(%rip)
+        prefetchit1     0x12345678(%rip)
+
+        .intel_syntax noprefix
+
+        prefetchit0     BYTE PTR [rip+0x12345678]
+        prefetchit1     BYTE PTR [rip+0x12345678]
+
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c
index 27ae8eaf46..9ef3d7a6ae 100644
--- a/opcodes/i386-dis.c
+++ b/opcodes/i386-dis.c
@@ -114,6 +114,7 @@ static void FXSAVE_Fixup (instr_info *, int, int);
 
 static void MOVSXD_Fixup (instr_info *, int, int);
 static void DistinctDest_Fixup (instr_info *, int, int);
+static void PREFETCHI_Fixup (instr_info *, int, int);
 
 /* This character is used to encode style information within the output
    buffers.  See oappend_insert_style for more details.  */
@@ -841,6 +842,8 @@ enum
   MOD_0F18_REG_1,
   MOD_0F18_REG_2,
   MOD_0F18_REG_3,
+  MOD_0F18_REG_6,
+  MOD_0F18_REG_7,
   MOD_0F1A_PREFIX_0,
   MOD_0F1B_PREFIX_0,
   MOD_0F1B_PREFIX_1,
@@ -1006,6 +1009,8 @@ enum
   PREFIX_0F11,
   PREFIX_0F12,
   PREFIX_0F16,
+  PREFIX_0F18_REG_6_MOD_0_X86_64,
+  PREFIX_0F18_REG_7_MOD_0_X86_64,
   PREFIX_0F1A,
   PREFIX_0F1B,
   PREFIX_0F1C,
@@ -1280,6 +1285,8 @@ enum
   X86_64_0F01_REG_7_MOD_3_RM_6_PREFIX_1,
   X86_64_0F01_REG_7_MOD_3_RM_6_PREFIX_3,
   X86_64_0F01_REG_7_MOD_3_RM_7_PREFIX_1,
+  X86_64_0F18_REG_6_MOD_0,
+  X86_64_0F18_REG_7_MOD_0,
   X86_64_0F24,
   X86_64_0F26,
   X86_64_0FC7_REG_6_MOD_3_PREFIX_1,
@@ -2751,8 +2758,8 @@ static const struct dis386 reg_table[][8] = {
     { MOD_TABLE (MOD_0F18_REG_3) },
     { "nopQ",		{ Ev }, 0 },
     { "nopQ",		{ Ev }, 0 },
-    { "nopQ",		{ Ev }, 0 },
-    { "nopQ",		{ Ev }, 0 },
+    { MOD_TABLE (MOD_0F18_REG_6) },
+    { MOD_TABLE (MOD_0F18_REG_7) },
   },
   /* REG_0F1C_P_0_MOD_0 */
   {
@@ -3118,6 +3125,22 @@ static const struct dis386 prefix_table[][4] = {
     { MOD_TABLE (MOD_0F16_PREFIX_2) },
   },
 
+  /* PREFIX_0F18_REG_6_MOD_0_X86_64 */
+  {
+    { "prefetchit1",	{ { PREFETCHI_Fixup, b_mode } }, 0 },
+    { "nopQ",		{ Ev }, 0 },
+    { "nopQ",		{ Ev }, 0 },
+    { "nopQ",		{ Ev }, 0 },
+  },
+
+  /* PREFIX_0F18_REG_7_MOD_0_X86_64 */
+  {
+    { "prefetchit0",	{ { PREFETCHI_Fixup, b_mode } }, 0 },
+    { "nopQ",		{ Ev }, 0 },
+    { "nopQ",		{ Ev }, 0 },
+    { "nopQ",		{ Ev }, 0 },
+  },
+
   /* PREFIX_0F1A */
   {
     { MOD_TABLE (MOD_0F1A_PREFIX_0) },
@@ -4394,6 +4417,18 @@ static const struct dis386 x86_64_table[][2] = {
     { "psmash",	{ Skip_MODRM }, 0 },
   },
 
+  /* X86_64_0F18_REG_6_MOD_0 */
+  {
+    { "nopQ",		{ Ev }, 0 },
+    { PREFIX_TABLE (PREFIX_0F18_REG_6_MOD_0_X86_64) },
+  },
+
+  /* X86_64_0F18_REG_7_MOD_0 */
+  {
+    { "nopQ",		{ Ev }, 0 },
+    { PREFIX_TABLE (PREFIX_0F18_REG_7_MOD_0_X86_64) },
+  },
+
   {
     /* X86_64_0F24 */
     { "movZ",		{ Em, Td }, 0 },
@@ -8193,6 +8228,16 @@ static const struct dis386 mod_table[][2] = {
     { "prefetcht2",	{ Mb }, 0 },
     { "nopQ",		{ Ev }, 0 },
   },
+  {
+    /* MOD_0F18_REG_6 */
+    { X86_64_TABLE (X86_64_0F18_REG_6_MOD_0) },
+    { "nopQ",		{ Ev }, 0 },
+  },
+  {
+    /* MOD_0F18_REG_7 */
+    { X86_64_TABLE (X86_64_0F18_REG_7_MOD_0) },
+    { "nopQ",		{ Ev }, 0 },
+  },
   {
     /* MOD_0F1A_PREFIX_0 */
     { "bndldx",		{ Gbnd, Mv_bnd }, 0 },
@@ -13940,3 +13985,32 @@ OP_Rounding (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
     }
   oappend (ins, "sae}");
 }
+
+static void
+PREFETCHI_Fixup (instr_info *ins, int bytemode, int sizeflag)
+{
+  if (ins->modrm.mod != 0 || ins->modrm.rm != 5)
+    {
+      if (ins->intel_syntax)
+	{
+	  ins->mnemonicendp = stpcpy (ins->obuf, "nop   ");
+	}
+      else
+	{
+	  USED_REX (REX_W);
+	  if (ins->rex & REX_W)
+	    ins->mnemonicendp = stpcpy (ins->obuf, "nopq  ");
+	  else
+	    {
+	      if (sizeflag & DFLAG)
+		ins->mnemonicendp = stpcpy (ins->obuf, "nopl  ");
+	      else
+		ins->mnemonicendp = stpcpy (ins->obuf, "nopw  ");
+	      ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
+	    }
+	}
+      bytemode = v_mode;
+    }
+
+  OP_M (ins, bytemode, sizeflag);
+}
diff --git a/opcodes/i386-gen.c b/opcodes/i386-gen.c
index 237f147ad4..33339ba840 100644
--- a/opcodes/i386-gen.c
+++ b/opcodes/i386-gen.c
@@ -259,6 +259,8 @@ static initializer cpu_flag_init[] =
     "CpuWRMSRNS" },
   { "CPU_MSRLIST_FLAGS",
     "CpuMSRLIST" },
+  { "CPU_PREFETCHI_FLAGS",
+    "CpuPREFETCHI"},
   { "CPU_IAMCU_FLAGS",
     "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuIAMCU" },
   { "CPU_ADX_FLAGS",
@@ -677,6 +679,7 @@ static bitfield cpu_flags[] =
   BITFIELD (CpuRAO_INT),
   BITFIELD (CpuWRMSRNS),
   BITFIELD (CpuMSRLIST),
+  BITFIELD (CpuPREFETCHI),
   BITFIELD (CpuMWAITX),
   BITFIELD (CpuCLZERO),
   BITFIELD (CpuOSPKE),
diff --git a/opcodes/i386-opc.h b/opcodes/i386-opc.h
index 645abe7f34..1ed319c20b 100644
--- a/opcodes/i386-opc.h
+++ b/opcodes/i386-opc.h
@@ -223,6 +223,8 @@ enum
   CpuWRMSRNS,
   /* Intel MSRLIST Instructions support required.  */
   CpuMSRLIST,
+  /* PREFETCHI instruction required */
+  CpuPREFETCHI,
   /* mwaitx instruction required */
   CpuMWAITX,
   /* Clzero instruction required */
@@ -411,6 +413,7 @@ typedef union i386_cpu_flags
       unsigned int cpurao_int:1;
       unsigned int cpuwrmsrns:1;
       unsigned int cpumsrlist:1;
+      unsigned int cpuprefetchi:1;
       unsigned int cpumwaitx:1;
       unsigned int cpuclzero:1;
       unsigned int cpuospke:1;
diff --git a/opcodes/i386-opc.tbl b/opcodes/i386-opc.tbl
index bb5dc6799d..d63aa1dfb2 100644
--- a/opcodes/i386-opc.tbl
+++ b/opcodes/i386-opc.tbl
@@ -3323,3 +3323,10 @@ rdmsrlist, 0xf20f01c6, None, CpuMSRLIST|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|N
 wrmsrlist, 0xf30f01c6, None, CpuMSRLIST|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, {}
 
 // MSRLIST instructions end.
+
+// PREFETCHI instructions.
+
+prefetchit0, 0xf18, 0x7, CpuPREFETCHI|Cpu64, Modrm|Anysize|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { BaseIndex }
+prefetchit1, 0xf18, 0x6, CpuPREFETCHI|Cpu64, Modrm|Anysize|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { BaseIndex }
+
+// PREFETCHI instructions end.
-- 
2.17.1
Thanks,
Lili.
  
Jan Beulich Oct. 27, 2022, 7:15 a.m. UTC | #11
On 27.10.2022 09:01, Cui, Lili wrote:
>>> -  /* Update operand types and check extended states.  */
>>> +  /* 1. Update operand types and check extended states.
>>> +     2. Check IP-relative addressing for prefetchi.  */
>>>    for (j = 0; j < i.operands; j++)
>>>      {
>>> +      /* Check if IP-relative addressing requirements can be satisfied.  */
>>> +      if (i.tm.cpu_flags.bitfield.cpuprefetchi
>>> +	  && !(i.base_reg && i.base_reg->reg_num == RegIP))
>>> +	as_warn (_("only support RIP-relative address"));
>>
>> One final suggestion:
>>
>> 	as_warn (_("`%s' only supports RIP-relative address"), i.tm.name);
>>
> Done.
> 
>> And maybe also keep code and comment in sync as to the sequence of
>> things done.
>>
> Changed, thanks Jan.

Thanks to you as well. I'd like to leave approving of the change to H.J.,
though.

One final reminder: Please in the future send new versions of patches as
new (roots of) mail threads, with an incremented version identifier. In
particular when later looking for stuff, doing so often makes it easier
to follow how things evolved before being committed.

Jan
  
Frager, Neal via Binutils Oct. 27, 2022, 7:43 a.m. UTC | #12
> On 27.10.2022 09:01, Cui, Lili wrote:
> >>> -  /* Update operand types and check extended states.  */
> >>> +  /* 1. Update operand types and check extended states.
> >>> +     2. Check IP-relative addressing for prefetchi.  */
> >>>    for (j = 0; j < i.operands; j++)
> >>>      {
> >>> +      /* Check if IP-relative addressing requirements can be satisfied.  */
> >>> +      if (i.tm.cpu_flags.bitfield.cpuprefetchi
> >>> +	  && !(i.base_reg && i.base_reg->reg_num == RegIP))
> >>> +	as_warn (_("only support RIP-relative address"));
> >>
> >> One final suggestion:
> >>
> >> 	as_warn (_("`%s' only supports RIP-relative address"), i.tm.name);
> >>
> > Done.
> >
> >> And maybe also keep code and comment in sync as to the sequence of
> >> things done.
> >>
> > Changed, thanks Jan.
> 
> Thanks to you as well. I'd like to leave approving of the change to H.J., though.
> 
Ok.

> One final reminder: Please in the future send new versions of patches as
> new (roots of) mail threads, with an incremented version identifier. In
> particular when later looking for stuff, doing so often makes it easier to
> follow how things evolved before being committed.
> 
Good advice, I will follow it. Thanks.

Lili
> Jan
  
Frager, Neal via Binutils Oct. 28, 2022, 9:03 a.m. UTC | #13
> On 27.10.2022 09:01, Cui, Lili wrote:
> >>> -  /* Update operand types and check extended states.  */
> >>> +  /* 1. Update operand types and check extended states.
> >>> +     2. Check IP-relative addressing for prefetchi.  */
> >>>    for (j = 0; j < i.operands; j++)
> >>>      {
> >>> +      /* Check if IP-relative addressing requirements can be satisfied.  */
> >>> +      if (i.tm.cpu_flags.bitfield.cpuprefetchi
> >>> +	  && !(i.base_reg && i.base_reg->reg_num == RegIP))
> >>> +	as_warn (_("only support RIP-relative address"));
> >>
> >> One final suggestion:
> >>
> >> 	as_warn (_("`%s' only supports RIP-relative address"), i.tm.name);
> >>
> > Done.
> >
> >> And maybe also keep code and comment in sync as to the sequence of
> >> things done.
> >>
> > Changed, thanks Jan.
> 
> Thanks to you as well. I'd like to leave approving of the change to H.J., though.
> 
H.J, Could please help take a look, thanks.

Lili.

> One final reminder: Please in the future send new versions of patches as
> new (roots of) mail threads, with an incremented version identifier. In
> particular when later looking for stuff, doing so often makes it easier to
> follow how things evolved before being committed.
> 
> Jan
  
H.J. Lu Oct. 28, 2022, 3:54 p.m. UTC | #14
On Thu, Oct 27, 2022 at 12:01 AM Cui, Lili <lili.cui@intel.com> wrote:
>
> > > -  /* Update operand types and check extended states.  */
> > > +  /* 1. Update operand types and check extended states.
> > > +     2. Check IP-relative addressing for prefetchi.  */
> > >    for (j = 0; j < i.operands; j++)
> > >      {
> > > +      /* Check if IP-relative addressing requirements can be satisfied.  */
> > > +      if (i.tm.cpu_flags.bitfield.cpuprefetchi
> > > +     && !(i.base_reg && i.base_reg->reg_num == RegIP))
> > > +   as_warn (_("only support RIP-relative address"));
> >
> > One final suggestion:
> >
> >       as_warn (_("`%s' only supports RIP-relative address"), i.tm.name);
> >
> Done.
>
> > And maybe also keep code and comment in sync as to the sequence of
> > things done.
> >
> Changed, thanks Jan.
>
> > Jan
>
>
> gas/ChangeLog:
>
>         * NEWS: Add support for Intel PREFETCHI instruction.
>         * config/tc-i386.c (load_insn_p): Use prefetch* to fold all prefetches.
>         (md_assemble): Add warning for illegal input of PREFETCHI.
>         * doc/c-i386.texi: Document .prefetchi.
>         * testsuite/gas/i386/i386.exp: Run PREFETCHI tests.
>         * testsuite/gas/i386/x86-64-lfence-load.d: Add PREFETCHI.
>         * testsuite/gas/i386/x86-64-lfence-load.s: Likewise.
>         * testsuite/gas/i386/x86-64-prefetch.d: New test.
>         * testsuite/gas/i386/x86-64-prefetchi-intel.d: Likewise.
>         * testsuite/gas/i386/x86-64-prefetchi-inval-register.d: Likewise..
>         * testsuite/gas/i386/x86-64-prefetchi-inval-register.s: Likewise.
>         * testsuite/gas/i386/x86-64-prefetchi-warn.l: Likewise.
>         * testsuite/gas/i386/x86-64-prefetchi-warn.s: Likewise.
>         * testsuite/gas/i386/x86-64-prefetchi.d: Likewise.
>         * testsuite/gas/i386/x86-64-prefetchi.s: Likewise.
>
> opcodes/ChangeLog:
>
>         * i386-dis.c (reg_table): Add MOD_0F18_REG_6 and MOD_0F18_REG_7
>         (x86_64_table): Add X86_64_0F18_REG_6_MOD_0 and X86_64_0F18_REG_7_MOD_0.
>         (mod_table): Add MOD_0F18_REG_6 and MOD_0F18_REG_7.
>         (prefix_table): Add PREFIX_0F18_REG_6_MOD_0_X86_64 and
>         PREFIX_0F18_REG_7_MOD_0_X86_64.
>         (PREFETCHI_Fixup): New.
>         * i386-gen.c (cpu_flag_init): Add CPU_PREFETCHI_FLAGS.
>         (cpu_flags): Add CpuPREFETCHI.
>         * i386-opc.h (CpuPREFETCHI): New.
>         (i386_cpu_flags): Add cpuprefetchi.
>         * i386-opc.tbl: Add Intel PREFETCHI instructions.
>         * i386-init.h: Regenerated.
>         * i386-tbl.h: Likewise.
> ---
>  gas/NEWS                                      |  2 +
>  gas/config/tc-i386.c                          | 14 +++-
>  gas/doc/c-i386.texi                           |  3 +-
>  gas/testsuite/gas/i386/i386.exp               |  4 +
>  gas/testsuite/gas/i386/x86-64-lfence-load.d   |  2 +
>  gas/testsuite/gas/i386/x86-64-lfence-load.s   |  2 +
>  .../gas/i386/x86-64-prefetchi-intel.d         | 16 ++++
>  .../i386/x86-64-prefetchi-inval-register.d    | 13 ++++
>  .../i386/x86-64-prefetchi-inval-register.s    |  9 +++
>  .../gas/i386/x86-64-prefetchi-warn.l          |  5 ++
>  .../gas/i386/x86-64-prefetchi-warn.s          | 11 +++
>  gas/testsuite/gas/i386/x86-64-prefetchi.d     | 15 ++++
>  gas/testsuite/gas/i386/x86-64-prefetchi.s     | 14 ++++
>  opcodes/i386-dis.c                            | 78 ++++++++++++++++++-
>  opcodes/i386-gen.c                            |  3 +
>  opcodes/i386-opc.h                            |  3 +
>  opcodes/i386-opc.tbl                          |  7 ++
>  17 files changed, 194 insertions(+), 7 deletions(-)
>  create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi-intel.d
>  create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.d
>  create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.s
>  create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi-warn.l
>  create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi-warn.s
>  create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi.d
>  create mode 100644 gas/testsuite/gas/i386/x86-64-prefetchi.s
>
> diff --git a/gas/NEWS b/gas/NEWS
> index 961449545d..5eb479f5a1 100644
> --- a/gas/NEWS
> +++ b/gas/NEWS
> @@ -1,5 +1,7 @@
>  -*- text -*-
>
> +* Add support for Intel PREFETCHI instructions.
> +
>  * Add support for Intel AMX-FP16 instructions.
>
>  * Add support for Intel MSRLIST instructions.
> diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
> index c1623f216e..52993dfbd9 100644
> --- a/gas/config/tc-i386.c
> +++ b/gas/config/tc-i386.c
> @@ -1102,6 +1102,7 @@ static const arch_entry cpu_arch[] =
>    SUBARCH (rao_int, RAO_INT, RAO_INT, false),
>    SUBARCH (wrmsrns, WRMSRNS, WRMSRNS, false),
>    SUBARCH (msrlist, MSRLIST, MSRLIST, false),
> +  SUBARCH (prefetchi, PREFETCHI, PREFETCHI, false),
>  };
>
>  #undef SUBARCH
> @@ -4520,9 +4521,8 @@ load_insn_p (void)
>
>    if (!any_vex_p)
>      {
> -      /* Anysize insns: lea, invlpg, clflush, prefetchnta, prefetcht0,
> -        prefetcht1, prefetcht2, prefetchtw, bndmk, bndcl, bndcu, bndcn,
> -        bndstx, bndldx, prefetchwt1, clflushopt, clwb, cldemote.  */
> +      /* Anysize insns: lea, invlpg, clflush, prefetch*, bndmk, bndcl, bndcu,
> +        bndcn, bndstx, bndldx, clflushopt, clwb, cldemote.  */
>        if (i.tm.opcode_modifier.anysize)
>         return 0;
>
> @@ -5057,9 +5057,15 @@ md_assemble (char *line)
>    if (!process_suffix ())
>      return;
>
> -  /* Update operand types and check extended states.  */
> +  /* 1. Check IP-relative addressing for prefetchi.
> +     2. Update operand types and check extended states.  */
>    for (j = 0; j < i.operands; j++)
>      {
> +      /* Check if IP-relative addressing requirements can be satisfied.  */
> +      if (i.tm.cpu_flags.bitfield.cpuprefetchi
> +         && !(i.base_reg && i.base_reg->reg_num == RegIP))
> +       as_warn (_("only support RIP-relative address"), i.tm.name);

Please move this check before the loop.   OK with this change.

>        i.types[j] = operand_type_and (i.types[j], i.tm.operand_types[j]);
>        switch (i.tm.operand_types[j].bitfield.class)
>         {
> diff --git a/gas/doc/c-i386.texi b/gas/doc/c-i386.texi
> index b33f17c698..fae902c034 100644
> --- a/gas/doc/c-i386.texi
> +++ b/gas/doc/c-i386.texi
> @@ -201,6 +201,7 @@ accept various extension mnemonics.  For example,
>  @code{rao_int},
>  @code{wrmsrns},
>  @code{msrlist},
> +@code{prefetchi},
>  @code{amx_int8},
>  @code{amx_bf16},
>  @code{amx_fp16},
> @@ -1496,7 +1497,7 @@ supported on the CPU specified.  The choices for @var{cpu_type} are:
>  @item @samp{.clwb} @tab @samp{.rdpid} @tab @samp{.ptwrite} @tab @samp{.ibt}
>  @item @samp{.avx_ifma} @tab @samp{.avx_vnni_int8} @tab @samp{.avx_ne_convert}
>  @item @samp{.cmpccxadd} @tab @samp{.rao_int} @tab @samp{.wrmsrns}
> -@item @samp{.msrlist}
> +@item @samp{.msrlist} @tab @samp{.prefetchi}
>  @item @samp{.wbnoinvd} @tab @samp{.pconfig} @tab @samp{.waitpkg} @tab @samp{.cldemote}
>  @item @samp{.shstk} @tab @samp{.gfni} @tab @samp{.vaes} @tab @samp{.vpclmulqdq}
>  @item @samp{.movdiri} @tab @samp{.movdir64b} @tab @samp{.enqcmd} @tab @samp{.tsxldtrk}
> diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp
> index 9f5fa7f612..2081339dc9 100644
> --- a/gas/testsuite/gas/i386/i386.exp
> +++ b/gas/testsuite/gas/i386/i386.exp
> @@ -1209,6 +1209,10 @@ if [gas_64_check] then {
>      run_dump_test "x86-64-tdx"
>      run_dump_test "x86-64-tsxldtrk"
>      run_dump_test "x86-64-hreset"
> +    run_dump_test "x86-64-prefetchi"
> +    run_dump_test "x86-64-prefetchi-intel"
> +    run_dump_test "x86-64-prefetchi-inval-register"
> +    run_list_test "x86-64-prefetchi-warn"
>      run_dump_test "x86-64-vp2intersect"
>      run_dump_test "x86-64-vp2intersect-intel"
>      run_list_test "x86-64-vp2intersect-inval-bcast"
> diff --git a/gas/testsuite/gas/i386/x86-64-lfence-load.d b/gas/testsuite/gas/i386/x86-64-lfence-load.d
> index 2af86fc93f..17c3b9f286 100644
> --- a/gas/testsuite/gas/i386/x86-64-lfence-load.d
> +++ b/gas/testsuite/gas/i386/x86-64-lfence-load.d
> @@ -33,6 +33,8 @@ Disassembly of section .text:
>   +[a-f0-9]+:   0f 18 55 00             prefetcht1 0x0\(%rbp\)
>   +[a-f0-9]+:   0f 18 5d 00             prefetcht2 0x0\(%rbp\)
>   +[a-f0-9]+:   0f 0d 4d 00             prefetchw 0x0\(%rbp\)
> + +[a-f0-9]+:   0f 18 3d 78 56 34 12    prefetchit0 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
> + +[a-f0-9]+:   0f 18 35 78 56 34 12    prefetchit1 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
>   +[a-f0-9]+:   0f a1                   pop    %fs
>   +[a-f0-9]+:   0f ae e8                lfence
>   +[a-f0-9]+:   9d                      popf
> diff --git a/gas/testsuite/gas/i386/x86-64-lfence-load.s b/gas/testsuite/gas/i386/x86-64-lfence-load.s
> index 2a3ac6b7d2..c478082416 100644
> --- a/gas/testsuite/gas/i386/x86-64-lfence-load.s
> +++ b/gas/testsuite/gas/i386/x86-64-lfence-load.s
> @@ -20,6 +20,8 @@ _start:
>         prefetcht1 (%rbp)
>         prefetcht2 (%rbp)
>         prefetchw (%rbp)
> +       prefetchit0 0x12345678(%rip)
> +       prefetchit1 0x12345678(%rip)
>         pop %fs
>         popf
>         xlatb (%rbx)
> diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-intel.d b/gas/testsuite/gas/i386/x86-64-prefetchi-intel.d
> new file mode 100644
> index 0000000000..7f72f0a1eb
> --- /dev/null
> +++ b/gas/testsuite/gas/i386/x86-64-prefetchi-intel.d
> @@ -0,0 +1,16 @@
> +#as:
> +#objdump: -dwMintel
> +#name: x86-64 PREFETCHI insns (Intel disassembly)
> +#source: x86-64-prefetchi.s
> +
> +.*: +file format .*
> +
> +
> +Disassembly of section .text:
> +
> +0+ <_start>:
> +[      ]*[a-f0-9]+:    0f 18 3d 78 56 34 12    prefetchit0 BYTE PTR \[rip\+0x12345678\]        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
> +[      ]*[a-f0-9]+:    0f 18 35 78 56 34 12    prefetchit1 BYTE PTR \[rip\+0x12345678\]        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
> +[      ]*[a-f0-9]+:    0f 18 3d 78 56 34 12    prefetchit0 BYTE PTR \[rip\+0x12345678\]        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
> +[      ]*[a-f0-9]+:    0f 18 35 78 56 34 12    prefetchit1 BYTE PTR \[rip\+0x12345678\]        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
> +#pass
> diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.d b/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.d
> new file mode 100644
> index 0000000000..b29b1ae237
> --- /dev/null
> +++ b/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.d
> @@ -0,0 +1,13 @@
> +#as:
> +#objdump: -dw
> +#name: x86-64 PREFETCHI INVAL REGISTER insns
> +
> +.*: +file format .*
> +
> +
> +Disassembly of section .text:
> +
> +0+ <\.text>:
> +[      ]*[a-f0-9]+:[   ]0f 18 39[      ]*nopl   \(%rcx\)
> +[      ]*[a-f0-9]+:[   ]0f 18 31[      ]*nopl   \(%rcx\)
> +#pass
> diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.s b/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.s
> new file mode 100644
> index 0000000000..550449a0c9
> --- /dev/null
> +++ b/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.s
> @@ -0,0 +1,9 @@
> +.text
> +        #prefetchit0 (%rcx) PREFETCHIT0/1 apply without RIP-relative addressing, should stay NOPs.
> +        .byte 0x0f
> +        .byte 0x18
> +        .byte 0x39
> +        #prefetchit1 (%rcx) PREFETCHIT1/1 apply without RIP-relative addressing, should stay NOPs.
> +        .byte 0x0f
> +        .byte 0x18
> +        .byte 0x31
> diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-warn.l b/gas/testsuite/gas/i386/x86-64-prefetchi-warn.l
> new file mode 100644
> index 0000000000..4e15389463
> --- /dev/null
> +++ b/gas/testsuite/gas/i386/x86-64-prefetchi-warn.l
> @@ -0,0 +1,5 @@
> +.*: Assembler messages:
> +.*:[0-9]*: Warning: only support RIP-relative address
> +.*:[0-9]*: Warning: only support RIP-relative address
> +.*:[0-9]*: Warning: only support RIP-relative address
> +.*:[0-9]*: Warning: only support RIP-relative address
> diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-warn.s b/gas/testsuite/gas/i386/x86-64-prefetchi-warn.s
> new file mode 100644
> index 0000000000..330ff31c75
> --- /dev/null
> +++ b/gas/testsuite/gas/i386/x86-64-prefetchi-warn.s
> @@ -0,0 +1,11 @@
> +# Check error for ICACHE-PREFETCH 64-bit instruction
> +
> +       .allow_index_reg
> +       .text
> +_start:
> +       prefetchit0     0x12345678(%rax)
> +       prefetchit1     0x12345678(%rax)
> +
> +       .intel_syntax noprefix
> +       prefetchit0     BYTE PTR [rax+0x12345678]
> +       prefetchit1     BYTE PTR [rax+0x12345678]
> diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi.d b/gas/testsuite/gas/i386/x86-64-prefetchi.d
> new file mode 100644
> index 0000000000..c8ab92d147
> --- /dev/null
> +++ b/gas/testsuite/gas/i386/x86-64-prefetchi.d
> @@ -0,0 +1,15 @@
> +#as:
> +#objdump: -dw
> +#name: x86-64 PREFETCHI insns
> +
> +.*: +file format .*
> +
> +
> +Disassembly of section .text:
> +
> +0+ <_start>:
> +[      ]*[a-f0-9]+:    0f 18 3d 78 56 34 12    prefetchit0 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
> +[      ]*[a-f0-9]+:    0f 18 35 78 56 34 12    prefetchit1 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
> +[      ]*[a-f0-9]+:    0f 18 3d 78 56 34 12    prefetchit0 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
> +[      ]*[a-f0-9]+:    0f 18 35 78 56 34 12    prefetchit1 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
> +#pass
> diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi.s b/gas/testsuite/gas/i386/x86-64-prefetchi.s
> new file mode 100644
> index 0000000000..cc7c61e9a9
> --- /dev/null
> +++ b/gas/testsuite/gas/i386/x86-64-prefetchi.s
> @@ -0,0 +1,14 @@
> +# Check 64bit PREFETCHI instructions
> +
> +       .allow_index_reg
> +       .text
> +_start:
> +
> +        prefetchit0     0x12345678(%rip)
> +        prefetchit1     0x12345678(%rip)
> +
> +        .intel_syntax noprefix
> +
> +        prefetchit0     BYTE PTR [rip+0x12345678]
> +        prefetchit1     BYTE PTR [rip+0x12345678]
> +
> diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c
> index 27ae8eaf46..9ef3d7a6ae 100644
> --- a/opcodes/i386-dis.c
> +++ b/opcodes/i386-dis.c
> @@ -114,6 +114,7 @@ static void FXSAVE_Fixup (instr_info *, int, int);
>
>  static void MOVSXD_Fixup (instr_info *, int, int);
>  static void DistinctDest_Fixup (instr_info *, int, int);
> +static void PREFETCHI_Fixup (instr_info *, int, int);
>
>  /* This character is used to encode style information within the output
>     buffers.  See oappend_insert_style for more details.  */
> @@ -841,6 +842,8 @@ enum
>    MOD_0F18_REG_1,
>    MOD_0F18_REG_2,
>    MOD_0F18_REG_3,
> +  MOD_0F18_REG_6,
> +  MOD_0F18_REG_7,
>    MOD_0F1A_PREFIX_0,
>    MOD_0F1B_PREFIX_0,
>    MOD_0F1B_PREFIX_1,
> @@ -1006,6 +1009,8 @@ enum
>    PREFIX_0F11,
>    PREFIX_0F12,
>    PREFIX_0F16,
> +  PREFIX_0F18_REG_6_MOD_0_X86_64,
> +  PREFIX_0F18_REG_7_MOD_0_X86_64,
>    PREFIX_0F1A,
>    PREFIX_0F1B,
>    PREFIX_0F1C,
> @@ -1280,6 +1285,8 @@ enum
>    X86_64_0F01_REG_7_MOD_3_RM_6_PREFIX_1,
>    X86_64_0F01_REG_7_MOD_3_RM_6_PREFIX_3,
>    X86_64_0F01_REG_7_MOD_3_RM_7_PREFIX_1,
> +  X86_64_0F18_REG_6_MOD_0,
> +  X86_64_0F18_REG_7_MOD_0,
>    X86_64_0F24,
>    X86_64_0F26,
>    X86_64_0FC7_REG_6_MOD_3_PREFIX_1,
> @@ -2751,8 +2758,8 @@ static const struct dis386 reg_table[][8] = {
>      { MOD_TABLE (MOD_0F18_REG_3) },
>      { "nopQ",          { Ev }, 0 },
>      { "nopQ",          { Ev }, 0 },
> -    { "nopQ",          { Ev }, 0 },
> -    { "nopQ",          { Ev }, 0 },
> +    { MOD_TABLE (MOD_0F18_REG_6) },
> +    { MOD_TABLE (MOD_0F18_REG_7) },
>    },
>    /* REG_0F1C_P_0_MOD_0 */
>    {
> @@ -3118,6 +3125,22 @@ static const struct dis386 prefix_table[][4] = {
>      { MOD_TABLE (MOD_0F16_PREFIX_2) },
>    },
>
> +  /* PREFIX_0F18_REG_6_MOD_0_X86_64 */
> +  {
> +    { "prefetchit1",   { { PREFETCHI_Fixup, b_mode } }, 0 },
> +    { "nopQ",          { Ev }, 0 },
> +    { "nopQ",          { Ev }, 0 },
> +    { "nopQ",          { Ev }, 0 },
> +  },
> +
> +  /* PREFIX_0F18_REG_7_MOD_0_X86_64 */
> +  {
> +    { "prefetchit0",   { { PREFETCHI_Fixup, b_mode } }, 0 },
> +    { "nopQ",          { Ev }, 0 },
> +    { "nopQ",          { Ev }, 0 },
> +    { "nopQ",          { Ev }, 0 },
> +  },
> +
>    /* PREFIX_0F1A */
>    {
>      { MOD_TABLE (MOD_0F1A_PREFIX_0) },
> @@ -4394,6 +4417,18 @@ static const struct dis386 x86_64_table[][2] = {
>      { "psmash",        { Skip_MODRM }, 0 },
>    },
>
> +  /* X86_64_0F18_REG_6_MOD_0 */
> +  {
> +    { "nopQ",          { Ev }, 0 },
> +    { PREFIX_TABLE (PREFIX_0F18_REG_6_MOD_0_X86_64) },
> +  },
> +
> +  /* X86_64_0F18_REG_7_MOD_0 */
> +  {
> +    { "nopQ",          { Ev }, 0 },
> +    { PREFIX_TABLE (PREFIX_0F18_REG_7_MOD_0_X86_64) },
> +  },
> +
>    {
>      /* X86_64_0F24 */
>      { "movZ",          { Em, Td }, 0 },
> @@ -8193,6 +8228,16 @@ static const struct dis386 mod_table[][2] = {
>      { "prefetcht2",    { Mb }, 0 },
>      { "nopQ",          { Ev }, 0 },
>    },
> +  {
> +    /* MOD_0F18_REG_6 */
> +    { X86_64_TABLE (X86_64_0F18_REG_6_MOD_0) },
> +    { "nopQ",          { Ev }, 0 },
> +  },
> +  {
> +    /* MOD_0F18_REG_7 */
> +    { X86_64_TABLE (X86_64_0F18_REG_7_MOD_0) },
> +    { "nopQ",          { Ev }, 0 },
> +  },
>    {
>      /* MOD_0F1A_PREFIX_0 */
>      { "bndldx",                { Gbnd, Mv_bnd }, 0 },
> @@ -13940,3 +13985,32 @@ OP_Rounding (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
>      }
>    oappend (ins, "sae}");
>  }
> +
> +static void
> +PREFETCHI_Fixup (instr_info *ins, int bytemode, int sizeflag)
> +{
> +  if (ins->modrm.mod != 0 || ins->modrm.rm != 5)
> +    {
> +      if (ins->intel_syntax)
> +       {
> +         ins->mnemonicendp = stpcpy (ins->obuf, "nop   ");
> +       }
> +      else
> +       {
> +         USED_REX (REX_W);
> +         if (ins->rex & REX_W)
> +           ins->mnemonicendp = stpcpy (ins->obuf, "nopq  ");
> +         else
> +           {
> +             if (sizeflag & DFLAG)
> +               ins->mnemonicendp = stpcpy (ins->obuf, "nopl  ");
> +             else
> +               ins->mnemonicendp = stpcpy (ins->obuf, "nopw  ");
> +             ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
> +           }
> +       }
> +      bytemode = v_mode;
> +    }
> +
> +  OP_M (ins, bytemode, sizeflag);
> +}
> diff --git a/opcodes/i386-gen.c b/opcodes/i386-gen.c
> index 237f147ad4..33339ba840 100644
> --- a/opcodes/i386-gen.c
> +++ b/opcodes/i386-gen.c
> @@ -259,6 +259,8 @@ static initializer cpu_flag_init[] =
>      "CpuWRMSRNS" },
>    { "CPU_MSRLIST_FLAGS",
>      "CpuMSRLIST" },
> +  { "CPU_PREFETCHI_FLAGS",
> +    "CpuPREFETCHI"},
>    { "CPU_IAMCU_FLAGS",
>      "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuIAMCU" },
>    { "CPU_ADX_FLAGS",
> @@ -677,6 +679,7 @@ static bitfield cpu_flags[] =
>    BITFIELD (CpuRAO_INT),
>    BITFIELD (CpuWRMSRNS),
>    BITFIELD (CpuMSRLIST),
> +  BITFIELD (CpuPREFETCHI),
>    BITFIELD (CpuMWAITX),
>    BITFIELD (CpuCLZERO),
>    BITFIELD (CpuOSPKE),
> diff --git a/opcodes/i386-opc.h b/opcodes/i386-opc.h
> index 645abe7f34..1ed319c20b 100644
> --- a/opcodes/i386-opc.h
> +++ b/opcodes/i386-opc.h
> @@ -223,6 +223,8 @@ enum
>    CpuWRMSRNS,
>    /* Intel MSRLIST Instructions support required.  */
>    CpuMSRLIST,
> +  /* PREFETCHI instruction required */
> +  CpuPREFETCHI,
>    /* mwaitx instruction required */
>    CpuMWAITX,
>    /* Clzero instruction required */
> @@ -411,6 +413,7 @@ typedef union i386_cpu_flags
>        unsigned int cpurao_int:1;
>        unsigned int cpuwrmsrns:1;
>        unsigned int cpumsrlist:1;
> +      unsigned int cpuprefetchi:1;
>        unsigned int cpumwaitx:1;
>        unsigned int cpuclzero:1;
>        unsigned int cpuospke:1;
> diff --git a/opcodes/i386-opc.tbl b/opcodes/i386-opc.tbl
> index bb5dc6799d..d63aa1dfb2 100644
> --- a/opcodes/i386-opc.tbl
> +++ b/opcodes/i386-opc.tbl
> @@ -3323,3 +3323,10 @@ rdmsrlist, 0xf20f01c6, None, CpuMSRLIST|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|N
>  wrmsrlist, 0xf30f01c6, None, CpuMSRLIST|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, {}
>
>  // MSRLIST instructions end.
> +
> +// PREFETCHI instructions.
> +
> +prefetchit0, 0xf18, 0x7, CpuPREFETCHI|Cpu64, Modrm|Anysize|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { BaseIndex }
> +prefetchit1, 0xf18, 0x6, CpuPREFETCHI|Cpu64, Modrm|Anysize|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { BaseIndex }
> +
> +// PREFETCHI instructions end.
> --
> 2.17.1
> Thanks,
> Lili.
>
>

Thanks.
  
Frager, Neal via Binutils Oct. 31, 2022, 1:23 p.m. UTC | #15
> > -  /* Update operand types and check extended states.  */
> > +  /* 1. Check IP-relative addressing for prefetchi.
> > +     2. Update operand types and check extended states.  */
> >    for (j = 0; j < i.operands; j++)
> >      {
> > +      /* Check if IP-relative addressing requirements can be satisfied.  */
> > +      if (i.tm.cpu_flags.bitfield.cpuprefetchi
> > +         && !(i.base_reg && i.base_reg->reg_num == RegIP))
> > +       as_warn (_("only support RIP-relative address"), i.tm.name);
> 
> Please move this check before the loop.   OK with this change.
> 
Done, I checked in this patch.

Thanks,
Lili.
  
Mike Frysinger Oct. 31, 2022, 2:45 p.m. UTC | #16
On 27 Oct 2022 07:01, Cui, Lili via Binutils wrote:
> +	as_warn (_("only support RIP-relative address"), i.tm.name);

this doesn't compile
  CC       config/tc-i386.o
In file included from ../../../gas/as.h:133,
                 from ../../../gas/config/tc-i386.c:28:
../../../gas/config/tc-i386.c: In function ‘md_assemble’:
../../../gas/asintl.h:54:20: error: too many arguments for format [-Werror=format-extra-args]
   54 | # define _(String) (String)
      |                    ^~~~~~~~
../../../gas/config/tc-i386.c:5039:14: note: in expansion of macro ‘_’
 5039 |     as_warn (_("only support RIP-relative address"), i.tm.name);
      |              ^
-mike
  
H.J. Lu Oct. 31, 2022, 4:25 p.m. UTC | #17
On Mon, Oct 31, 2022 at 9:10 AM Mike Frysinger via Binutils
<binutils@sourceware.org> wrote:
>
> On 27 Oct 2022 07:01, Cui, Lili via Binutils wrote:
> > +     as_warn (_("only support RIP-relative address"), i.tm.name);
>
> this doesn't compile
>   CC       config/tc-i386.o
> In file included from ../../../gas/as.h:133,
>                  from ../../../gas/config/tc-i386.c:28:
> ../../../gas/config/tc-i386.c: In function ‘md_assemble’:
> ../../../gas/asintl.h:54:20: error: too many arguments for format [-Werror=format-extra-args]
>    54 | # define _(String) (String)
>       |                    ^~~~~~~~
> ../../../gas/config/tc-i386.c:5039:14: note: in expansion of macro ‘_’
>  5039 |     as_warn (_("only support RIP-relative address"), i.tm.name);
>       |              ^
> -mike

It has been fixed.
  

Patch

diff --git a/gas/NEWS b/gas/NEWS
index 961449545d..5eb479f5a1 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -1,5 +1,7 @@ 
 -*- text -*-
 
+* Add support for Intel PREFETCHI instructions.
+
 * Add support for Intel AMX-FP16 instructions.
 
 * Add support for Intel MSRLIST instructions.
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 73aa2c66aa..65dd5de935 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -1102,6 +1102,7 @@  static const arch_entry cpu_arch[] =
   SUBARCH (wrmsrns, WRMSRNS, ANY_WRMSRNS, false),
   SUBARCH (msrlist, MSRLIST, ANY_MSRLIST, false),
   SUBARCH (amx_fp16, AMX_FP16, ANY_AMX_FP16, false),
+  SUBARCH (prefetchi, PREFETCHI, ANY_PREFETCHI, false),
 };
 
 #undef SUBARCH
@@ -4522,7 +4523,8 @@  load_insn_p (void)
     {
       /* Anysize insns: lea, invlpg, clflush, prefetchnta, prefetcht0,
 	 prefetcht1, prefetcht2, prefetchtw, bndmk, bndcl, bndcu, bndcn,
-	 bndstx, bndldx, prefetchwt1, clflushopt, clwb, cldemote.  */
+	 bndstx, bndldx, prefetchwt1, clflushopt, clwb, cldemote, prefetchit0
+	 prefetchit1.  */
       if (i.tm.opcode_modifier.anysize)
 	return 0;
 
diff --git a/gas/doc/c-i386.texi b/gas/doc/c-i386.texi
index dc7e281e6d..1cf4e6b9d8 100644
--- a/gas/doc/c-i386.texi
+++ b/gas/doc/c-i386.texi
@@ -221,6 +221,7 @@  accept various extension mnemonics.  For example,
 @code{wrmsrns},
 @code{msrlist},
 @code{amx_fp16},
+@code{prefetchi},
 @code{noavx512f},
 @code{noavx512cd},
 @code{noavx512er},
@@ -249,6 +250,7 @@  accept various extension mnemonics.  For example,
 @code{nowrmsrns},
 @code{nomsrlist},
 @code{noamx_fp16},
+@code{noprefetchi},
 @code{noenqcmd},
 @code{noserialize},
 @code{notsxldtrk},
@@ -1551,7 +1553,7 @@  supported on the CPU specified.  The choices for @var{cpu_type} are:
 @item @samp{.clwb} @tab @samp{.rdpid} @tab @samp{.ptwrite} @tab @samp{.ibt}
 @item @samp{.avx_ifma} @tab @samp{.avx_vnni_int8} @tab @samp{.avx_ne_convert}
 @item @samp{.cmpccxadd} @tab @samp{.raoint} @tab @samp{.wrmsrns}
-@item @samp{.msrlist} @tab @samp{.amx_fp16}
+@item @samp{.msrlist} @tab @samp{.amx_fp16} @tab @samp{.prefetchi}
 @item @samp{.wbnoinvd} @tab @samp{.pconfig} @tab @samp{.waitpkg} @tab @samp{.cldemote}
 @item @samp{.shstk} @tab @samp{.gfni} @tab @samp{.vaes} @tab @samp{.vpclmulqdq}
 @item @samp{.movdiri} @tab @samp{.movdir64b} @tab @samp{.enqcmd} @tab @samp{.tsxldtrk}
diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp
index 9f5fa7f612..80bd2835ca 100644
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -1209,6 +1209,9 @@  if [gas_64_check] then {
     run_dump_test "x86-64-tdx"
     run_dump_test "x86-64-tsxldtrk"
     run_dump_test "x86-64-hreset"
+    run_dump_test "x86-64-prefetchi"
+    run_dump_test "x86-64-prefetchi-intel"
+    run_dump_test "x86-64-prefetchi-inval-register"
     run_dump_test "x86-64-vp2intersect"
     run_dump_test "x86-64-vp2intersect-intel"
     run_list_test "x86-64-vp2intersect-inval-bcast"
diff --git a/gas/testsuite/gas/i386/x86-64-lfence-load.d b/gas/testsuite/gas/i386/x86-64-lfence-load.d
index 2af86fc93f..17c3b9f286 100644
--- a/gas/testsuite/gas/i386/x86-64-lfence-load.d
+++ b/gas/testsuite/gas/i386/x86-64-lfence-load.d
@@ -33,6 +33,8 @@  Disassembly of section .text:
  +[a-f0-9]+:	0f 18 55 00          	prefetcht1 0x0\(%rbp\)
  +[a-f0-9]+:	0f 18 5d 00          	prefetcht2 0x0\(%rbp\)
  +[a-f0-9]+:	0f 0d 4d 00          	prefetchw 0x0\(%rbp\)
+ +[a-f0-9]+:	0f 18 3d 78 56 34 12 	prefetchit0 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+ +[a-f0-9]+:	0f 18 35 78 56 34 12 	prefetchit1 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
  +[a-f0-9]+:	0f a1                	pop    %fs
  +[a-f0-9]+:	0f ae e8             	lfence
  +[a-f0-9]+:	9d                   	popf
diff --git a/gas/testsuite/gas/i386/x86-64-lfence-load.s b/gas/testsuite/gas/i386/x86-64-lfence-load.s
index 2a3ac6b7d2..c478082416 100644
--- a/gas/testsuite/gas/i386/x86-64-lfence-load.s
+++ b/gas/testsuite/gas/i386/x86-64-lfence-load.s
@@ -20,6 +20,8 @@  _start:
 	prefetcht1 (%rbp)
 	prefetcht2 (%rbp)
 	prefetchw (%rbp)
+	prefetchit0 0x12345678(%rip)
+	prefetchit1 0x12345678(%rip)
 	pop %fs
 	popf
 	xlatb (%rbx)
diff --git a/gas/testsuite/gas/i386/x86-64-lockbad-1.l b/gas/testsuite/gas/i386/x86-64-lockbad-1.l
index 6469991605..24b13d9f46 100644
--- a/gas/testsuite/gas/i386/x86-64-lockbad-1.l
+++ b/gas/testsuite/gas/i386/x86-64-lockbad-1.l
@@ -39,10 +39,10 @@ 
 .*:44: Error: .*
 .*:45: Error: .*
 .*:46: Error: .*
-.*:49: Error: .*
-.*:50: Error: .*
+.*:47: Error: .*
+.*:48: Error: .*
+.*:51: Error: .*
 .*:52: Error: .*
-.*:53: Error: .*
 .*:54: Error: .*
 .*:55: Error: .*
 .*:56: Error: .*
@@ -69,8 +69,8 @@ 
 .*:77: Error: .*
 .*:78: Error: .*
 .*:79: Error: .*
+.*:80: Error: .*
 .*:81: Error: .*
-.*:82: Error: .*
 .*:83: Error: .*
 .*:84: Error: .*
 .*:85: Error: .*
@@ -79,6 +79,10 @@ 
 .*:88: Error: .*
 .*:89: Error: .*
 .*:90: Error: .*
+.*:91: Error: .*
+.*:92: Error: .*
+.*:93: Error: .*
+.*:94: Error: .*
 GAS LISTING .*
 
 
@@ -128,50 +132,54 @@  GAS LISTING .*
 [ 	]*44[ 	]+lock wrmsrns
 [ 	]*45[ 	]+lock rdmsrlist
 [ 	]*46[ 	]+lock wrmsrlist
-[ 	]*47[ 	]+
-[ 	]*48[ 	]+\.intel_syntax noprefix
-[ 	]*49[ 	]+lock mov eax,ebx
-[ 	]*50[ 	]+lock mov eax,DWORD PTR \[rbx\]
-[ 	]*51[ 	]+
-[ 	]*52[ 	]+lock add eax,ebx
-[ 	]*53[ 	]+lock add ebx,0x64
-[ 	]*54[ 	]+lock adc eax,ebx
-[ 	]*55[ 	]+lock adc ebx,0x64
-[ 	]*56[ 	]+lock and eax,ebx
-[ 	]*57[ 	]+lock and ebx,0x64
+[ 	]*47[ 	]+lock prefetchit0 0x12345678\(%rip\)
+[ 	]*48[ 	]+lock prefetchit1 0x12345678\(%rip\)
+[ 	]*49[ 	]+
+[ 	]*50[ 	]+\.intel_syntax noprefix
+[ 	]*51[ 	]+lock mov eax,ebx
+[ 	]*52[ 	]+lock mov eax,DWORD PTR \[rbx\]
+[ 	]*53[ 	]+
+[ 	]*54[ 	]+lock add eax,ebx
+[ 	]*55[ 	]+lock add ebx,0x64
+[ 	]*56[ 	]+lock adc eax,ebx
+[ 	]*57[ 	]+lock adc ebx,0x64
 GAS LISTING .*
 
 
-[ 	]*58[ 	]+lock btc ebx,eax
-[ 	]*59[ 	]+lock btc ebx,0x64
-[ 	]*60[ 	]+lock btr ebx,eax
-[ 	]*61[ 	]+lock btr ebx,0x64
-[ 	]*62[ 	]+lock bts ebx,eax
-[ 	]*63[ 	]+lock bts ebx,0x64
-[ 	]*64[ 	]+lock cmpxchg ebx,eax
-[ 	]*65[ 	]+lock dec ebx
-[ 	]*66[ 	]+lock inc ebx
-[ 	]*67[ 	]+lock neg ebx
-[ 	]*68[ 	]+lock not ebx
-[ 	]*69[ 	]+lock or eax,ebx
-[ 	]*70[ 	]+lock or ebx,0x64
-[ 	]*71[ 	]+lock sbb eax,ebx
-[ 	]*72[ 	]+lock sbb ebx,0x64
-[ 	]*73[ 	]+lock sub eax,ebx
-[ 	]*74[ 	]+lock sub ebx,0x64
-[ 	]*75[ 	]+lock xadd ebx,eax
-[ 	]*76[ 	]+lock xchg ebx,eax
-[ 	]*77[ 	]+lock xchg ebx,eax
-[ 	]*78[ 	]+lock xor eax,ebx
-[ 	]*79[ 	]+lock xor ebx,0x64
-[ 	]*80[ 	]+
-[ 	]*81[ 	]+lock add eax,DWORD PTR \[rbx\]
-[ 	]*82[ 	]+lock adc eax,DWORD PTR \[rbx\]
-[ 	]*83[ 	]+lock and eax,DWORD PTR \[rbx\]
-[ 	]*84[ 	]+lock or eax,DWORD PTR \[rbx\]
-[ 	]*85[ 	]+lock sbb eax,DWORD PTR \[rbx\]
-[ 	]*86[ 	]+lock sub eax,DWORD PTR \[rbx\]
-[ 	]*87[ 	]+lock xor eax,DWORD PTR \[rbx\]
-[ 	]*88[ 	]+lock wrmsrns
-[ 	]*89[ 	]+lock rdmsrlist
-[ 	]*90[ 	]+lock wrmsrlist
+[ 	]*58[ 	]+lock and eax,ebx
+[ 	]*59[ 	]+lock and ebx,0x64
+[ 	]*60[ 	]+lock btc ebx,eax
+[ 	]*61[ 	]+lock btc ebx,0x64
+[ 	]*62[ 	]+lock btr ebx,eax
+[ 	]*63[ 	]+lock btr ebx,0x64
+[ 	]*64[ 	]+lock bts ebx,eax
+[ 	]*65[ 	]+lock bts ebx,0x64
+[ 	]*66[ 	]+lock cmpxchg ebx,eax
+[ 	]*67[ 	]+lock dec ebx
+[ 	]*68[ 	]+lock inc ebx
+[ 	]*69[ 	]+lock neg ebx
+[ 	]*70[ 	]+lock not ebx
+[ 	]*71[ 	]+lock or eax,ebx
+[ 	]*72[ 	]+lock or ebx,0x64
+[ 	]*73[ 	]+lock sbb eax,ebx
+[ 	]*74[ 	]+lock sbb ebx,0x64
+[ 	]*75[ 	]+lock sub eax,ebx
+[ 	]*76[ 	]+lock sub ebx,0x64
+[ 	]*77[ 	]+lock xadd ebx,eax
+[ 	]*78[ 	]+lock xchg ebx,eax
+[ 	]*79[ 	]+lock xchg ebx,eax
+[ 	]*80[ 	]+lock xor eax,ebx
+[ 	]*81[ 	]+lock xor ebx,0x64
+[ 	]*82[ 	]+
+[ 	]*83[ 	]+lock add eax,DWORD PTR \[rbx\]
+[ 	]*84[ 	]+lock adc eax,DWORD PTR \[rbx\]
+[ 	]*85[ 	]+lock and eax,DWORD PTR \[rbx\]
+[ 	]*86[ 	]+lock or eax,DWORD PTR \[rbx\]
+[ 	]*87[ 	]+lock sbb eax,DWORD PTR \[rbx\]
+[ 	]*88[ 	]+lock sub eax,DWORD PTR \[rbx\]
+[ 	]*89[ 	]+lock xor eax,DWORD PTR \[rbx\]
+[ 	]*90[ 	]+lock wrmsrns
+[ 	]*91[ 	]+lock rdmsrlist
+[ 	]*92[ 	]+lock wrmsrlist
+[ 	]*93[ 	]+lock prefetchit0 BYTE PTR \[rip\+0x12345678\]
+[ 	]*94[ 	]+lock prefetchit1 BYTE PTR \[rip\+0x12345678\]
diff --git a/gas/testsuite/gas/i386/x86-64-lockbad-1.s b/gas/testsuite/gas/i386/x86-64-lockbad-1.s
index fcea969fb9..cdd4721793 100644
--- a/gas/testsuite/gas/i386/x86-64-lockbad-1.s
+++ b/gas/testsuite/gas/i386/x86-64-lockbad-1.s
@@ -44,6 +44,8 @@  foo:
 	lock wrmsrns
 	lock rdmsrlist
 	lock wrmsrlist
+	lock prefetchit0 0x12345678(%rip)
+	lock prefetchit1 0x12345678(%rip)
 
 	.intel_syntax noprefix
 	lock mov eax,ebx
@@ -88,3 +90,5 @@  foo:
 	lock wrmsrns
 	lock rdmsrlist
 	lock wrmsrlist
+	lock prefetchit0 BYTE PTR [rip+0x12345678]
+	lock prefetchit1 BYTE PTR [rip+0x12345678]
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-intel.d b/gas/testsuite/gas/i386/x86-64-prefetchi-intel.d
new file mode 100644
index 0000000000..7f72f0a1eb
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi-intel.d
@@ -0,0 +1,16 @@ 
+#as:
+#objdump: -dwMintel
+#name: x86-64 PREFETCHI insns (Intel disassembly)
+#source: x86-64-prefetchi.s
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <_start>:
+[ 	]*[a-f0-9]+:	0f 18 3d 78 56 34 12 	prefetchit0 BYTE PTR \[rip\+0x12345678\]        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 35 78 56 34 12 	prefetchit1 BYTE PTR \[rip\+0x12345678\]        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 3d 78 56 34 12 	prefetchit0 BYTE PTR \[rip\+0x12345678\]        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 35 78 56 34 12 	prefetchit1 BYTE PTR \[rip\+0x12345678\]        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.d b/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.d
new file mode 100644
index 0000000000..b29b1ae237
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.d
@@ -0,0 +1,13 @@ 
+#as:
+#objdump: -dw
+#name: x86-64 PREFETCHI INVAL REGISTER insns
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <\.text>:
+[ 	]*[a-f0-9]+:[ 	]0f 18 39[ 	]*nopl   \(%rcx\)
+[ 	]*[a-f0-9]+:[ 	]0f 18 31[ 	]*nopl   \(%rcx\)
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.s b/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.s
new file mode 100644
index 0000000000..550449a0c9
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi-inval-register.s
@@ -0,0 +1,9 @@ 
+.text
+        #prefetchit0 (%rcx) PREFETCHIT0/1 apply without RIP-relative addressing, should stay NOPs.
+        .byte 0x0f
+        .byte 0x18
+        .byte 0x39
+        #prefetchit1 (%rcx) PREFETCHIT1/1 apply without RIP-relative addressing, should stay NOPs.
+        .byte 0x0f
+        .byte 0x18
+        .byte 0x31
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi.d b/gas/testsuite/gas/i386/x86-64-prefetchi.d
new file mode 100644
index 0000000000..c8ab92d147
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi.d
@@ -0,0 +1,15 @@ 
+#as:
+#objdump: -dw
+#name: x86-64 PREFETCHI insns
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <_start>:
+[ 	]*[a-f0-9]+:	0f 18 3d 78 56 34 12 	prefetchit0 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 35 78 56 34 12 	prefetchit1 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 3d 78 56 34 12 	prefetchit0 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+[ 	]*[a-f0-9]+:	0f 18 35 78 56 34 12 	prefetchit1 0x12345678\(%rip\)        # [0-9a-f]+ <_start\+0x[0-9a-f]+>
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-prefetchi.s b/gas/testsuite/gas/i386/x86-64-prefetchi.s
new file mode 100644
index 0000000000..cc7c61e9a9
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefetchi.s
@@ -0,0 +1,14 @@ 
+# Check 64bit PREFETCHI instructions
+
+	.allow_index_reg
+	.text
+_start:
+
+        prefetchit0     0x12345678(%rip)
+        prefetchit1     0x12345678(%rip)
+
+        .intel_syntax noprefix
+
+        prefetchit0     BYTE PTR [rip+0x12345678]
+        prefetchit1     BYTE PTR [rip+0x12345678]
+
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c
index be25d3f612..8e799aa3bb 100644
--- a/opcodes/i386-dis.c
+++ b/opcodes/i386-dis.c
@@ -114,6 +114,7 @@  static void FXSAVE_Fixup (instr_info *, int, int);
 
 static void MOVSXD_Fixup (instr_info *, int, int);
 static void DistinctDest_Fixup (instr_info *, int, int);
+static void PREFETCHI_Fixup (instr_info *, int, int);
 
 /* This character is used to encode style information within the output
    buffers.  See oappend_insert_style for more details.  */
@@ -841,6 +842,8 @@  enum
   MOD_0F18_REG_1,
   MOD_0F18_REG_2,
   MOD_0F18_REG_3,
+  MOD_0F18_REG_6,
+  MOD_0F18_REG_7,
   MOD_0F1A_PREFIX_0,
   MOD_0F1B_PREFIX_0,
   MOD_0F1B_PREFIX_1,
@@ -1297,6 +1300,8 @@  enum
   X86_64_0F01_REG_7_MOD_3_RM_6_PREFIX_1,
   X86_64_0F01_REG_7_MOD_3_RM_6_PREFIX_3,
   X86_64_0F01_REG_7_MOD_3_RM_7_PREFIX_1,
+  X86_64_MOD_0F18_REG_6,
+  X86_64_MOD_0F18_REG_7,
   X86_64_0F24,
   X86_64_0F26,
   X86_64_0FC7_REG_6_MOD_3_PREFIX_1,
@@ -2768,8 +2773,8 @@  static const struct dis386 reg_table[][8] = {
     { MOD_TABLE (MOD_0F18_REG_3) },
     { "nopQ",		{ Ev }, 0 },
     { "nopQ",		{ Ev }, 0 },
-    { "nopQ",		{ Ev }, 0 },
-    { "nopQ",		{ Ev }, 0 },
+    { MOD_TABLE (MOD_0F18_REG_6) },
+    { MOD_TABLE (MOD_0F18_REG_7) },
   },
   /* REG_0F1C_P_0_MOD_0 */
   {
@@ -4414,6 +4419,18 @@  static const struct dis386 x86_64_table[][2] = {
     { "psmash",	{ Skip_MODRM }, 0 },
   },
 
+  /* X86_64_MOD_0F18_REG_6 */
+  {
+    { "nopQ",		{ Ev }, 0 },
+    { "prefetchit1",    { { PREFETCHI_Fixup, b_mode } }, 0 },
+  },
+
+  /* X86_64_MOD_0F18_REG_7 */
+  {
+    { "nopQ",		{ Ev }, 0 },
+    { "prefetchit0",    { { PREFETCHI_Fixup, b_mode } }, 0 },
+  },
+
   {
     /* X86_64_0F24 */
     { "movZ",		{ Em, Td }, 0 },
@@ -8213,6 +8230,16 @@  static const struct dis386 mod_table[][2] = {
     { "prefetcht2",	{ Mb }, 0 },
     { "nopQ",		{ Ev }, 0 },
   },
+  {
+    /* MOD_0F18_REG_6 */
+    { X86_64_TABLE (X86_64_MOD_0F18_REG_6) },
+    { "nopQ",		{ Ev }, 0 },
+  },
+  {
+    /* MOD_0F18_REG_7 */
+    { X86_64_TABLE (X86_64_MOD_0F18_REG_7) },
+    { "nopQ",		{ Ev }, 0 },
+  },
   {
     /* MOD_0F1A_PREFIX_0 */
     { "bndldx",		{ Gbnd, Mv_bnd }, 0 },
@@ -14021,3 +14048,18 @@  OP_Rounding (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
     }
   oappend (ins, "sae}");
 }
+
+static void
+PREFETCHI_Fixup (instr_info *ins, int bytemode, int sizeflag)
+{
+  if (ins->modrm.mod != 0 || ins->modrm.rm != 5)
+    {
+      if (ins->intel_syntax)
+	ins->mnemonicendp = stpcpy (ins->obuf, "nop   ");
+      else
+	ins->mnemonicendp = stpcpy (ins->obuf, "nopl  ");
+      bytemode = v_mode;
+    }
+
+  OP_M (ins, bytemode, sizeflag);
+}
diff --git a/opcodes/i386-gen.c b/opcodes/i386-gen.c
index d10b462548..1e61d3f735 100644
--- a/opcodes/i386-gen.c
+++ b/opcodes/i386-gen.c
@@ -261,6 +261,8 @@  static initializer cpu_flag_init[] =
     "CpuMSRLIST" },
   { "CPU_AMX_FP16_FLAGS",
     "CpuAMX_FP16" },
+  { "CPU_PREFETCHI_FLAGS",
+    "CpuPREFETCHI"},
   { "CPU_IAMCU_FLAGS",
     "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuIAMCU" },
   { "CPU_ADX_FLAGS",
@@ -471,6 +473,8 @@  static initializer cpu_flag_init[] =
     "CpuMSRLIST" },
   { "CPU_ANY_AMX_FP16_FLAGS",
     "CpuAMX_FP16" },
+  { "CPU_ANY_PREFETCHI_FLAGS",
+    "CpuPREFETCHI" },
 };
 
 static initializer operand_type_init[] =
@@ -680,6 +684,7 @@  static bitfield cpu_flags[] =
   BITFIELD (CpuWRMSRNS),
   BITFIELD (CpuMSRLIST),
   BITFIELD (CpuAMX_FP16),
+  BITFIELD (CpuPREFETCHI),
   BITFIELD (CpuMWAITX),
   BITFIELD (CpuCLZERO),
   BITFIELD (CpuOSPKE),
diff --git a/opcodes/i386-opc.h b/opcodes/i386-opc.h
index 0dec14e365..f2cb673be4 100644
--- a/opcodes/i386-opc.h
+++ b/opcodes/i386-opc.h
@@ -225,6 +225,8 @@  enum
   CpuMSRLIST,
   /* AMX-FP16 instructions required */
   CpuAMX_FP16,
+  /* PREFETCHI instruction required */
+  CpuPREFETCHI,
   /* mwaitx instruction required */
   CpuMWAITX,
   /* Clzero instruction required */
@@ -412,6 +414,7 @@  typedef union i386_cpu_flags
       unsigned int cpuwrmsrns:1;
       unsigned int cpumsrlist:1;
       unsigned int cpuamx_fp16:1;
+      unsigned int cpuprefetchi:1;
       unsigned int cpumwaitx:1;
       unsigned int cpuclzero:1;
       unsigned int cpuospke:1;
diff --git a/opcodes/i386-opc.tbl b/opcodes/i386-opc.tbl
index 95bb2fc1fd..4755b02ed5 100644
--- a/opcodes/i386-opc.tbl
+++ b/opcodes/i386-opc.tbl
@@ -3345,3 +3345,10 @@  wrmsrlist, 0xf30f01c6, None, CpuMSRLIST|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|N
 tdpfp16ps, 0xf25c, None, CpuAMX_FP16|Cpu64, Modrm|Vex128|Space0F38|VexVVVV=1|VexW0|SwapSources|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { RegTMM, RegTMM, RegTMM }
 
 // AMX-FP16 instructions end.
+
+// PREFETCHI instructions.
+
+prefetchit0, 0xf18, 0x7, CpuPREFETCHI|Cpu64, Modrm|Anysize|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { BaseIndex }
+prefetchit1, 0xf18, 0x6, CpuPREFETCHI|Cpu64, Modrm|Anysize|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { BaseIndex }
+
+// PREFETCHI instructions end.