[v3] Support x86 Intel MSR_IMM

Message ID 20241113030708.921141-1-lin1.hu@intel.com
State New
Headers
Series [v3] Support x86 Intel MSR_IMM |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm fail Patch failed to apply
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 fail Patch failed to apply

Commit Message

Hu, Lin1 Nov. 13, 2024, 3:07 a.m. UTC
  OK, changes have been made according to your comments.

BRs,
Lin

gas/ChangeLog:

	* NEWS: Support x86 Intel MSR_IMM.
	* config/tc-i386.c (cpu_arch): Add MSR_IMM.
	(cpu_flags_match): Add MSR_IMM to APX_F related processing.
	(i386_assemble): WRMSRNS's first operand is imm32, so add
	MN_wrmsrns like MN_uwrmsr.
	* doc/c-i386.texi: Document .msr_imm.
	* testsuite/gas/i386/i386.exp: Run MSR_IMM tests.
	* testsuite/gas/i386/x86-64.exp: Ditto.
	* testsuite/gas/i386/msr_imm-inval.l: New test.
	* testsuite/gas/i386/msr_imm-inval.s: Ditto.
	* testsuite/gas/i386/x86-64-msr_imm-intel.d: Ditto.
	* testsuite/gas/i386/x86-64-msr_imm.d: Ditto.
	* testsuite/gas/i386/x86-64-msr_imm.s: Ditto.

opcodes/ChangeLog:

	* i386-dis.c: Add REG_VEX_MAP7_F6_L_0_W_0,
	PREFIX_VEX_MAP7_F6_L_0_W_0_R_0_X86_64,
	X86_64_VEX_MAP7_F6_L_0_W_0_R_0,
	VEX_LEN_MAP7_F6,
	VEX_W_MAP7_F6_L_0.
	(reg_table): New entry for MSR_IMM.
	(prefix_table): Ditto.
	(x86_64_table): Ditto.
	(vex_len_table): Ditto.
	(vex_w_table): Ditto.
	(map7_f6_opcode): New variable for MAP7.
	(get_valid_dis386): Support MAP7.
	* i386-gen.c (cpu_flags): Add MSR_IMM.
	* i386-init.h: Regenerated.
	* i386-mnem.h: Ditto.
	* i386-opc.h (i386_cpu_flags): Add cpumsr_imm.
	* i386-opc.tbl: Add MSR_IMM instructions.
	* i386-tbl.h: Regenerated.
---
 gas/NEWS                                      |    2 +
 gas/config/tc-i386.c                          |   25 +-
 gas/doc/c-i386.texi                           |    3 +-
 gas/testsuite/gas/i386/i386.exp               |    1 +
 gas/testsuite/gas/i386/msr_imm-inval.l        |    3 +
 gas/testsuite/gas/i386/msr_imm-inval.s        |    6 +
 gas/testsuite/gas/i386/x86-64-msr_imm-intel.d |   35 +
 gas/testsuite/gas/i386/x86-64-msr_imm-inval.l |    5 +
 gas/testsuite/gas/i386/x86-64-msr_imm-inval.s |    8 +
 gas/testsuite/gas/i386/x86-64-msr_imm.d       |   35 +
 gas/testsuite/gas/i386/x86-64-msr_imm.s       |   30 +
 gas/testsuite/gas/i386/x86-64.exp             |    3 +
 opcodes/i386-dis.c                            |   41 +-
 opcodes/i386-gen.c                            |    3 +
 opcodes/i386-init.h                           |  802 ++++++------
 opcodes/i386-opc.h                            |    3 +
 opcodes/i386-opc.tbl                          |    8 +
 opcodes/i386-tbl.h                            | 1084 +++++++++--------
 18 files changed, 1156 insertions(+), 941 deletions(-)
 create mode 100644 gas/testsuite/gas/i386/msr_imm-inval.l
 create mode 100644 gas/testsuite/gas/i386/msr_imm-inval.s
 create mode 100644 gas/testsuite/gas/i386/x86-64-msr_imm-intel.d
 create mode 100644 gas/testsuite/gas/i386/x86-64-msr_imm-inval.l
 create mode 100644 gas/testsuite/gas/i386/x86-64-msr_imm-inval.s
 create mode 100644 gas/testsuite/gas/i386/x86-64-msr_imm.d
 create mode 100644 gas/testsuite/gas/i386/x86-64-msr_imm.s
  

Comments

Jan Beulich Nov. 13, 2024, 10:57 a.m. UTC | #1
On 13.11.2024 04:07, Hu, Lin1 wrote:
> OK, changes have been made according to your comments.

Thank you.

> gas/ChangeLog:
> 
> 	* NEWS: Support x86 Intel MSR_IMM.
> 	* config/tc-i386.c (cpu_arch): Add MSR_IMM.
> 	(cpu_flags_match): Add MSR_IMM to APX_F related processing.
> 	(i386_assemble): WRMSRNS's first operand is imm32, so add
> 	MN_wrmsrns like MN_uwrmsr.
> 	* doc/c-i386.texi: Document .msr_imm.
> 	* testsuite/gas/i386/i386.exp: Run MSR_IMM tests.
> 	* testsuite/gas/i386/x86-64.exp: Ditto.
> 	* testsuite/gas/i386/msr_imm-inval.l: New test.
> 	* testsuite/gas/i386/msr_imm-inval.s: Ditto.
> 	* testsuite/gas/i386/x86-64-msr_imm-intel.d: Ditto.
> 	* testsuite/gas/i386/x86-64-msr_imm.d: Ditto.
> 	* testsuite/gas/i386/x86-64-msr_imm.s: Ditto.
> 
> opcodes/ChangeLog:
> 
> 	* i386-dis.c: Add REG_VEX_MAP7_F6_L_0_W_0,
> 	PREFIX_VEX_MAP7_F6_L_0_W_0_R_0_X86_64,
> 	X86_64_VEX_MAP7_F6_L_0_W_0_R_0,
> 	VEX_LEN_MAP7_F6,
> 	VEX_W_MAP7_F6_L_0.
> 	(reg_table): New entry for MSR_IMM.
> 	(prefix_table): Ditto.
> 	(x86_64_table): Ditto.
> 	(vex_len_table): Ditto.
> 	(vex_w_table): Ditto.
> 	(map7_f6_opcode): New variable for MAP7.
> 	(get_valid_dis386): Support MAP7.
> 	* i386-gen.c (cpu_flags): Add MSR_IMM.
> 	* i386-init.h: Regenerated.
> 	* i386-mnem.h: Ditto.
> 	* i386-opc.h (i386_cpu_flags): Add cpumsr_imm.
> 	* i386-opc.tbl: Add MSR_IMM instructions.
> 	* i386-tbl.h: Regenerated.

Okay.

Jan
  

Patch

diff --git a/gas/NEWS b/gas/NEWS
index 84e88ad287d..017154b9e12 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -1,5 +1,7 @@ 
 -*- text -*-
 
+* Add support for the x86 Intel MSR_IMM instructions.
+
 * Add support for Intel AVX10.2 instructions.
 
 * Add support for the x86 Zhaoxin GMI instructions.
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 74e80774112..56d738f2489 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -1221,6 +1221,7 @@  static const arch_entry cpu_arch[] =
   SUBARCH (apx_f, APX_F, APX_F, false),
   VECARCH (avx10.2, AVX10_2, ANY_AVX10_2, set),
   SUBARCH (gmi, GMI, GMI, false),
+  SUBARCH (msr_imm, MSR_IMM, MSR_IMM, false),
 };
 
 #undef SUBARCH
@@ -2233,7 +2234,8 @@  cpu_flags_match (const insn_template *t)
 	  && (any.bitfield.cpubmi || any.bitfield.cpubmi2
 	      || any.bitfield.cpuavx512f || any.bitfield.cpuavx512bw
 	      || any.bitfield.cpuavx512dq || any.bitfield.cpuamx_tile
-	      || any.bitfield.cpucmpccxadd || any.bitfield.cpuuser_msr))
+	      || any.bitfield.cpucmpccxadd || any.bitfield.cpuuser_msr
+	      || any.bitfield.cpumsr_imm))
 	{
 	  /* These checks (verifying that APX_F() was properly used in the
 	     opcode table entry) make sure there's no need for an "else" to
@@ -4037,7 +4039,8 @@  install_template (const insn_template *t)
       if ((maybe_cpu (t, CpuCMPCCXADD) || maybe_cpu (t, CpuAMX_TILE)
 	   || maybe_cpu (t, CpuAVX512F) || maybe_cpu (t, CpuAVX512DQ)
 	   || maybe_cpu (t, CpuAVX512BW) || maybe_cpu (t, CpuBMI)
-	   || maybe_cpu (t, CpuBMI2) || maybe_cpu (t, CpuUSER_MSR))
+	   || maybe_cpu (t, CpuBMI2) || maybe_cpu (t, CpuUSER_MSR)
+	   || maybe_cpu (t, CpuMSR_IMM))
 	  && maybe_cpu (t, CpuAPX_F))
 	{
 	  if (need_evex_encoding (t))
@@ -6990,18 +6993,20 @@  i386_assemble (char *line)
      because of the swapping above) in the incoming set of operands.  */
   if ((i.imm_operands == 2
        && (t->mnem_off == MN_extrq || t->mnem_off == MN_insertq))
-      || (t->mnem_off == MN_uwrmsr && i.imm_operands
-	  && i.operands > i.imm_operands))
+      || ((t->mnem_off == MN_uwrmsr || t->mnem_off == MN_wrmsrns)
+	  && i.imm_operands && i.operands > i.imm_operands))
       swap_2_operands (0, 1);
 
   if (i.imm_operands)
     {
-      /* For USER_MSR instructions, imm32 stands for the name of an model specific
-	 register (MSR). That's an unsigned quantity, whereas all other insns with
-	 32-bit immediate and 64-bit operand size use sign-extended
-	 immediates (imm32s). Therefore these insns are special-cased, bypassing
-	 the normal handling of immediates here.  */
-      if (is_cpu(current_templates.start, CpuUSER_MSR))
+      /* For USER_MSR and MSR_IMM instructions, imm32 stands for the name of a
+	 model specific register (MSR). That's an unsigned quantity, whereas all
+	 other insns with 32-bit immediate and 64-bit operand size use
+	 sign-extended immediates (imm32s). Therefore these insns are
+	 special-cased, bypassing the normal handling of immediates here.  */
+      if (is_cpu(current_templates.start, CpuUSER_MSR)
+	  || t->mnem_off == MN_rdmsr
+	  || t->mnem_off == MN_wrmsrns)
 	{
 	  for (j = 0; j < i.operands; j++)
 	    {
diff --git a/gas/doc/c-i386.texi b/gas/doc/c-i386.texi
index 952ddbc7377..adcc1711665 100644
--- a/gas/doc/c-i386.texi
+++ b/gas/doc/c-i386.texi
@@ -218,6 +218,7 @@  accept various extension mnemonics.  For example,
 @code{avx10.1/256},
 @code{avx10.1/128},
 @code{user_msr},
+@code{msr_imm},
 @code{apx_f},
 @code{avx10.2},
 @code{avx10.2/512},
@@ -1694,7 +1695,7 @@  supported on the CPU specified.  The choices for @var{cpu_type} are:
 @item @samp{.cmpccxadd} @tab @samp{.wrmsrns} @tab @samp{.msrlist}
 @item @samp{.avx_ne_convert} @tab @samp{.rao_int} @tab @samp{.fred} @tab @samp{.lkgs}
 @item @samp{.avx_vnni_int16} @tab @samp{.sha512} @tab @samp{.sm3} @tab @samp{.sm4}
-@item @samp{.pbndkb} @tab @samp{.user_msr} @tab @samp{.avx10.2}
+@item @samp{.pbndkb} @tab @samp{.user_msr} @tab @samp{.msr_imm} @tab @samp{.avx10.2}
 @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 795083d11db..6e6a134a0fe 100644
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -519,6 +519,7 @@  if [gas_32_check] then {
     run_dump_test "sm4-intel"
     run_list_test "pbndkb-inval"
     run_list_test "user_msr-inval"
+    run_list_test "msr_imm-inval"
     run_list_test "apx-push2pop2-inval"
     run_dump_test "avx10_2-rounding"
     run_dump_test "avx10_2-rounding-intel"
diff --git a/gas/testsuite/gas/i386/msr_imm-inval.l b/gas/testsuite/gas/i386/msr_imm-inval.l
new file mode 100644
index 00000000000..409319d0dff
--- /dev/null
+++ b/gas/testsuite/gas/i386/msr_imm-inval.l
@@ -0,0 +1,3 @@ 
+.* Assembler messages:
+.*:5: Error: unsupported instruction `rdmsr'
+.*:6: Error: unsupported instruction `wrmsrns'
diff --git a/gas/testsuite/gas/i386/msr_imm-inval.s b/gas/testsuite/gas/i386/msr_imm-inval.s
new file mode 100644
index 00000000000..08a0d8e4fe7
--- /dev/null
+++ b/gas/testsuite/gas/i386/msr_imm-inval.s
@@ -0,0 +1,6 @@ 
+# Check Illegal 32bit MSR_IMM instructions
+
+	.text
+_start:
+	rdmsr	 $51515151, %eax
+	wrmsrns  %eax, $51515151
diff --git a/gas/testsuite/gas/i386/x86-64-msr_imm-intel.d b/gas/testsuite/gas/i386/x86-64-msr_imm-intel.d
new file mode 100644
index 00000000000..b09748068ad
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-msr_imm-intel.d
@@ -0,0 +1,35 @@ 
+#as:
+#objdump: -dw -Mintel
+#name: x86_64 MSR_IMM insns (Intel disassembly)
+#source: x86-64-msr_imm.s
+
+.*: +file format .*
+
+Disassembly of section \.text:
+
+0+ <_start>:
+\s*[a-f0-9]+:\s*c4 c7 7b f6 c4 0f 0f 12 03\s+rdmsr  r12,0x3120f0f
+\s*[a-f0-9]+:\s*c4 e7 7b f6 c0 0f 0f 12 03\s+rdmsr  rax,0x3120f0f
+\s*[a-f0-9]+:\s*c4 c7 7b f6 c4 7f 00 00 00\s+rdmsr  r12,0x7f
+\s*[a-f0-9]+:\s*c4 c7 7b f6 c4 ff 7f 00 00\s+rdmsr  r12,0x7fff
+\s*[a-f0-9]+:\s*c4 c7 7b f6 c4 00 00 00 80\s+rdmsr  r12,0x80000000
+\s*[a-f0-9]+:\s*62 df 7f 08 f6 c0 0f 0f 12 03\s+rdmsr  r24,0x3120f0f
+\s*[a-f0-9]+:\s*c4 c7 7a f6 c4 0f 0f 12 03\s+wrmsrns 0x3120f0f,r12
+\s*[a-f0-9]+:\s*c4 e7 7a f6 c0 0f 0f 12 03\s+wrmsrns 0x3120f0f,rax
+\s*[a-f0-9]+:\s*c4 c7 7a f6 c4 7f 00 00 00\s+wrmsrns 0x7f,r12
+\s*[a-f0-9]+:\s*c4 c7 7a f6 c4 ff 7f 00 00\s+wrmsrns 0x7fff,r12
+\s*[a-f0-9]+:\s*c4 c7 7a f6 c4 00 00 00 80\s+wrmsrns 0x80000000,r12
+\s*[a-f0-9]+:\s*62 df 7e 08 f6 c0 0f 0f 12 03\s+wrmsrns 0x3120f0f,r24
+\s*[a-f0-9]+:\s*c4 c7 7b f6 c4 0f 0f 12 03\s+rdmsr  r12,0x3120f0f
+\s*[a-f0-9]+:\s*c4 e7 7b f6 c0 0f 0f 12 03\s+rdmsr  rax,0x3120f0f
+\s*[a-f0-9]+:\s*c4 c7 7b f6 c4 7f 00 00 00\s+rdmsr  r12,0x7f
+\s*[a-f0-9]+:\s*c4 c7 7b f6 c4 ff 7f 00 00\s+rdmsr  r12,0x7fff
+\s*[a-f0-9]+:\s*c4 c7 7b f6 c4 00 00 00 80\s+rdmsr  r12,0x80000000
+\s*[a-f0-9]+:\s*62 df 7f 08 f6 c0 0f 0f 12 03\s+rdmsr  r24,0x3120f0f
+\s*[a-f0-9]+:\s*c4 c7 7a f6 c4 0f 0f 12 03\s+wrmsrns 0x3120f0f,r12
+\s*[a-f0-9]+:\s*c4 e7 7a f6 c0 0f 0f 12 03\s+wrmsrns 0x3120f0f,rax
+\s*[a-f0-9]+:\s*c4 c7 7a f6 c4 7f 00 00 00\s+wrmsrns 0x7f,r12
+\s*[a-f0-9]+:\s*c4 c7 7a f6 c4 ff 7f 00 00\s+wrmsrns 0x7fff,r12
+\s*[a-f0-9]+:\s*c4 c7 7a f6 c4 00 00 00 80\s+wrmsrns 0x80000000,r12
+\s*[a-f0-9]+:\s*62 df 7e 08 f6 c0 0f 0f 12 03\s+wrmsrns 0x3120f0f,r24
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-msr_imm-inval.l b/gas/testsuite/gas/i386/x86-64-msr_imm-inval.l
new file mode 100644
index 00000000000..6825a145984
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-msr_imm-inval.l
@@ -0,0 +1,5 @@ 
+.* Assembler messages:
+.*:5: Error: operand type mismatch for `rdmsr'
+.*:6: Error: operand type mismatch for `rdmsr'
+.*:7: Error: operand type mismatch for `wrmsrns'
+.*:8: Error: operand type mismatch for `wrmsrns'
diff --git a/gas/testsuite/gas/i386/x86-64-msr_imm-inval.s b/gas/testsuite/gas/i386/x86-64-msr_imm-inval.s
new file mode 100644
index 00000000000..e12e5be392f
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-msr_imm-inval.s
@@ -0,0 +1,8 @@ 
+# Check Illegal 64bit MSR_IMM instructions
+
+	.text
+_start:
+	rdmsr  $5151515151515151, %r12
+	rdmsr  $-515151, %r12
+	wrmsrns  %r12, $5151515151515151
+	wrmsrns  %r12, $-515151
diff --git a/gas/testsuite/gas/i386/x86-64-msr_imm.d b/gas/testsuite/gas/i386/x86-64-msr_imm.d
new file mode 100644
index 00000000000..1409fa240c0
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-msr_imm.d
@@ -0,0 +1,35 @@ 
+#as:
+#objdump: -dw
+#name: x86_64 MSR_IMM insns
+#source: x86-64-msr_imm.s
+
+.*: +file format .*
+
+Disassembly of section \.text:
+
+0+ <_start>:
+\s*[a-f0-9]+:\s*c4 c7 7b f6 c4 0f 0f 12 03\s+rdmsr\s+\$0x3120f0f,%r12
+\s*[a-f0-9]+:\s*c4 e7 7b f6 c0 0f 0f 12 03\s+rdmsr\s+\$0x3120f0f,%rax
+\s*[a-f0-9]+:\s*c4 c7 7b f6 c4 7f 00 00 00\s+rdmsr\s+\$0x7f,%r12
+\s*[a-f0-9]+:\s*c4 c7 7b f6 c4 ff 7f 00 00\s+rdmsr\s+\$0x7fff,%r12
+\s*[a-f0-9]+:\s*c4 c7 7b f6 c4 00 00 00 80\s+rdmsr\s+\$0x80000000,%r12
+\s*[a-f0-9]+:\s*62 df 7f 08 f6 c0 0f 0f 12 03\s+rdmsr\s+\$0x3120f0f,%r24
+\s*[a-f0-9]+:\s*c4 c7 7a f6 c4 0f 0f 12 03\s+wrmsrns\s+%r12,\$0x3120f0f
+\s*[a-f0-9]+:\s*c4 e7 7a f6 c0 0f 0f 12 03\s+wrmsrns\s+%rax,\$0x3120f0f
+\s*[a-f0-9]+:\s*c4 c7 7a f6 c4 7f 00 00 00\s+wrmsrns\s+%r12,\$0x7f
+\s*[a-f0-9]+:\s*c4 c7 7a f6 c4 ff 7f 00 00\s+wrmsrns\s+%r12,\$0x7fff
+\s*[a-f0-9]+:\s*c4 c7 7a f6 c4 00 00 00 80\s+wrmsrns\s+%r12,\$0x80000000
+\s*[a-f0-9]+:\s*62 df 7e 08 f6 c0 0f 0f 12 03\s+wrmsrns\s+%r24,\$0x3120f0f
+\s*[a-f0-9]+:\s*c4 c7 7b f6 c4 0f 0f 12 03\s+rdmsr\s+\$0x3120f0f,%r12
+\s*[a-f0-9]+:\s*c4 e7 7b f6 c0 0f 0f 12 03\s+rdmsr\s+\$0x3120f0f,%rax
+\s*[a-f0-9]+:\s*c4 c7 7b f6 c4 7f 00 00 00\s+rdmsr\s+\$0x7f,%r12
+\s*[a-f0-9]+:\s*c4 c7 7b f6 c4 ff 7f 00 00\s+rdmsr\s+\$0x7fff,%r12
+\s*[a-f0-9]+:\s*c4 c7 7b f6 c4 00 00 00 80\s+rdmsr\s+\$0x80000000,%r12
+\s*[a-f0-9]+:\s*62 df 7f 08 f6 c0 0f 0f 12 03\s+rdmsr\s+\$0x3120f0f,%r24
+\s*[a-f0-9]+:\s*c4 c7 7a f6 c4 0f 0f 12 03\s+wrmsrns\s+%r12,\$0x3120f0f
+\s*[a-f0-9]+:\s*c4 e7 7a f6 c0 0f 0f 12 03\s+wrmsrns\s+%rax,\$0x3120f0f
+\s*[a-f0-9]+:\s*c4 c7 7a f6 c4 7f 00 00 00\s+wrmsrns\s+%r12,\$0x7f
+\s*[a-f0-9]+:\s*c4 c7 7a f6 c4 ff 7f 00 00\s+wrmsrns\s+%r12,\$0x7fff
+\s*[a-f0-9]+:\s*c4 c7 7a f6 c4 00 00 00 80\s+wrmsrns\s+%r12,\$0x80000000
+\s*[a-f0-9]+:\s*62 df 7e 08 f6 c0 0f 0f 12 03\s+wrmsrns\s+%r24,\$0x3120f0f
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-msr_imm.s b/gas/testsuite/gas/i386/x86-64-msr_imm.s
new file mode 100644
index 00000000000..dee94a10333
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-msr_imm.s
@@ -0,0 +1,30 @@ 
+# Check 64bit MSR_IMM instructions
+
+	.text
+_start:
+	rdmsr $51515151, %r12
+	rdmsr $51515151, %rax
+	rdmsr $0x7f, %r12
+	rdmsr $0x7fff, %r12
+	rdmsr $0x80000000, %r12
+	rdmsr $51515151, %r24
+	wrmsrns %r12, $51515151
+	wrmsrns %rax, $51515151
+	wrmsrns %r12, $0x7f
+	wrmsrns %r12, $0x7fff
+	wrmsrns %r12, $0x80000000
+	wrmsrns %r24, $51515151
+
+	.intel_syntax noprefix
+	rdmsr r12, 51515151
+	rdmsr rax, 51515151
+	rdmsr r12, 0x7f
+	rdmsr r12, 0x7fff
+	rdmsr r12, 0x80000000
+	rdmsr r24, 51515151
+	wrmsrns 51515151, r12
+	wrmsrns 51515151, rax
+	wrmsrns 0x7f, r12
+	wrmsrns 0x7fff, r12
+	wrmsrns 0x80000000, r12
+	wrmsrns 51515151, r24
diff --git a/gas/testsuite/gas/i386/x86-64.exp b/gas/testsuite/gas/i386/x86-64.exp
index 4ca89eb3b13..bf51874d020 100644
--- a/gas/testsuite/gas/i386/x86-64.exp
+++ b/gas/testsuite/gas/i386/x86-64.exp
@@ -498,6 +498,9 @@  run_dump_test "x86-64-pbndkb-intel"
 run_dump_test "x86-64-user_msr"
 run_dump_test "x86-64-user_msr-intel"
 run_list_test "x86-64-user_msr-inval"
+run_dump_test "x86-64-msr_imm"
+run_dump_test "x86-64-msr_imm-intel"
+run_list_test "x86-64-msr_imm-inval"
 run_dump_test "x86-64-avx10_2-rounding"
 run_dump_test "x86-64-avx10_2-rounding-intel"
 run_dump_test "x86-64-avx10_2-evex-promote"
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c
index 4e1123339ef..e4b741cded3 100644
--- a/opcodes/i386-dis.c
+++ b/opcodes/i386-dis.c
@@ -902,6 +902,7 @@  enum
   REG_VEX_0FAE,
   REG_VEX_0F3849_X86_64_L_0_W_0_M_1_P_0,
   REG_VEX_0F38F3_L_0_P_0,
+  REG_VEX_MAP7_F6_L_0_W_0,
   REG_VEX_MAP7_F8_L_0_W_0,
 
   REG_XOP_09_01_L_0,
@@ -1151,6 +1152,7 @@  enum
   PREFIX_VEX_0F38F6_L_0,
   PREFIX_VEX_0F38F7_L_0,
   PREFIX_VEX_0F3AF0_L_0,
+  PREFIX_VEX_MAP7_F6_L_0_W_0_R_0_X86_64,
   PREFIX_VEX_MAP7_F8_L_0_W_0_R_0_X86_64,
 
   PREFIX_EVEX_0F2E,
@@ -1348,6 +1350,7 @@  enum
   X86_64_VEX_0F386C,
   X86_64_VEX_0F38Ex,
 
+  X86_64_VEX_MAP7_F6_L_0_W_0_R_0,
   X86_64_VEX_MAP7_F8_L_0_W_0_R_0,
   
   X86_64_EVEX_MAP5_6C_W_1_P_1,
@@ -1467,6 +1470,7 @@  enum
   VEX_LEN_0F3ADE_W_0,
   VEX_LEN_0F3ADF,
   VEX_LEN_0F3AF0,
+  VEX_LEN_MAP7_F6,
   VEX_LEN_MAP7_F8,
   VEX_LEN_XOP_08_85,
   VEX_LEN_XOP_08_86,
@@ -1633,6 +1637,7 @@  enum
   VEX_W_0F3ACE,
   VEX_W_0F3ACF,
   VEX_W_0F3ADE,
+  VEX_W_MAP7_F6_L_0,
   VEX_W_MAP7_F8_L_0,
 
   VEX_W_XOP_08_85_L_0,
@@ -3004,6 +3009,10 @@  static const struct dis386 reg_table[][8] = {
     { "%NFblsmskS",		{ VexGdq, Edq }, 0 },
     { "%NFblsiS",		{ VexGdq, Edq }, 0 },
   },
+  /* REG_VEX_MAP7_F6_L_0_W_0 */
+  {
+    { X86_64_TABLE (X86_64_VEX_MAP7_F6_L_0_W_0_R_0) },
+  },
   /* REG_VEX_MAP7_F8_L_0_W_0 */
   {
     { X86_64_TABLE (X86_64_VEX_MAP7_F8_L_0_W_0_R_0) },
@@ -4212,12 +4221,20 @@  static const struct dis386 prefix_table[][4] = {
     { "%XErorxS",		{ Gdq, Edq, Ib }, 0 },
   },
 
+  /* PREFIX_VEX_MAP7_F6_L_0_W_0_R_0_X86_64 */
+  {
+    { Bad_Opcode },
+    { "wrmsrns",	{ Skip_MODRM, Id, Rq }, 0 },
+    { Bad_Opcode },
+    { "rdmsr",		{ Rq, Id }, 0 },
+  },
+
   /* PREFIX_VEX_MAP7_F8_L_0_W_0_R_0_X86_64 */
   {
     { Bad_Opcode },
-    { "uwrmsr", { Skip_MODRM, Id, Rq }, 0 },
+    { "uwrmsr",	{ Skip_MODRM, Id, Rq }, 0 },
     { Bad_Opcode },
-    { "urdmsr", { Rq, Id }, 0 },
+    { "urdmsr",	{ Rq, Id }, 0 },
   },
 
 #include "i386-dis-evex-prefix.h"
@@ -4576,6 +4593,12 @@  static const struct dis386 x86_64_table[][2] = {
     { "%XEcmp%CCxadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
   },
 
+  /* X86_64_VEX_MAP7_F6_L_0_W_0_R_0 */
+  {
+    { Bad_Opcode },
+    { PREFIX_TABLE (PREFIX_VEX_MAP7_F6_L_0_W_0_R_0_X86_64) },
+  },
+
   /* X86_64_VEX_MAP7_F8_L_0_W_0_R_0 */
   {
     { Bad_Opcode },
@@ -7335,6 +7358,11 @@  static const struct dis386 vex_len_table[][2] = {
     { PREFIX_TABLE (PREFIX_VEX_0F3AF0_L_0) },
   },
 
+  /* VEX_LEN_MAP7_F6 */
+  {
+    { VEX_W_TABLE (VEX_W_MAP7_F6_L_0) },
+  },
+
   /* VEX_LEN_MAP7_F8 */
   {
     { VEX_W_TABLE (VEX_W_MAP7_F8_L_0) },
@@ -7946,6 +7974,10 @@  static const struct dis386 vex_w_table[][2] = {
     /* VEX_W_0F3ADE */
     { VEX_LEN_TABLE (VEX_LEN_0F3ADE_W_0) },
   },
+  {
+    /* VEX_W_MAP7_F6_L_0 */
+    { REG_TABLE (REG_VEX_MAP7_F6_L_0_W_0) },
+  },
   {
     /* VEX_W_MAP7_F8_L_0 */
     { REG_TABLE (REG_VEX_MAP7_F8_L_0_W_0) },
@@ -8691,6 +8723,7 @@  static const struct dis386 bad_opcode = { "(bad)", { XX }, 0 };
 /* Fetch error indicator.  */
 static const struct dis386 err_opcode = { NULL, { XX }, 0 };
 
+static const struct dis386 map7_f6_opcode = { VEX_LEN_TABLE (VEX_LEN_MAP7_F6) };
 static const struct dis386 map7_f8_opcode = { VEX_LEN_TABLE (VEX_LEN_MAP7_F8) };
 
 /* Get a pointer to struct dis386 with a valid name.  */
@@ -9004,6 +9037,8 @@  get_valid_dis386 (const struct dis386 *dp, instr_info *ins)
       ins->condition_code = vindex & 0xf;
       if (vex_table_index != VEX_MAP7)
 	dp = &vex_table[vex_table_index][vindex];
+      else if (vindex == 0xf6)
+	dp = &map7_f6_opcode;
       else if (vindex == 0xf8)
 	dp = &map7_f8_opcode;
       else
@@ -9165,6 +9200,8 @@  get_valid_dis386 (const struct dis386 *dp, instr_info *ins)
 	dp = &evex_table[vex_table_index][vindex];
       else if (vindex == 0xf8)
 	dp = &map7_f8_opcode;
+      else if (vindex == 0xf6)
+	dp = &map7_f6_opcode;
       else
 	dp = &bad_opcode;
       ins->end_codep = ins->codep;
diff --git a/opcodes/i386-gen.c b/opcodes/i386-gen.c
index 1a0eeb9bb5e..e124b782fe9 100644
--- a/opcodes/i386-gen.c
+++ b/opcodes/i386-gen.c
@@ -279,6 +279,8 @@  static const dependency isa_dependencies[] =
     "64" },
   { "USER_MSR",
     "64" },
+  { "MSR_IMM",
+    "64" },
   { "APX_F",
     "XSAVE|64" },
 };
@@ -404,6 +406,7 @@  static bitfield cpu_flags[] =
   BITFIELD (FRED),
   BITFIELD (LKGS),
   BITFIELD (USER_MSR),
+  BITFIELD (MSR_IMM),
   BITFIELD (APX_F),
   BITFIELD (AVX10_2),
   BITFIELD (MWAITX),
diff --git a/opcodes/i386-opc.h b/opcodes/i386-opc.h
index 736e899f5ad..c8f9d53dc1e 100644
--- a/opcodes/i386-opc.h
+++ b/opcodes/i386-opc.h
@@ -227,6 +227,8 @@  enum i386_cpu
   CpuLKGS,
   /* Intel USER_MSR Instruction support required.  */
   CpuUSER_MSR,
+  /* Intel MSR_IMM Instructions support required.  */
+  CpuMSR_IMM,
   /* Intel AVX10.2 Instructions support required.  */
   CpuAVX10_2,
   /* mwaitx instruction required */
@@ -482,6 +484,7 @@  typedef union i386_cpu_flags
       unsigned int cpufred:1;
       unsigned int cpulkgs:1;
       unsigned int cpuuser_msr:1;
+      unsigned int cpumsr_imm:1;
       unsigned int cpuavx10_2:1;
       unsigned int cpumwaitx:1;
       unsigned int cpuclzero:1;
diff --git a/opcodes/i386-opc.tbl b/opcodes/i386-opc.tbl
index 43f27166c5c..1e530bf6a7c 100644
--- a/opcodes/i386-opc.tbl
+++ b/opcodes/i386-opc.tbl
@@ -3420,6 +3420,14 @@  uwrmsr, 0xf3f8/0, APX_F(USER_MSR), Modrm|Vex128|xVexMap7|EVex128|VexW0|NoSuf, {
 
 // USER_MSR instructions end.
 
+// MSR_IMM instructions.
+
+rdmsr, 0xf2f6/0, APX_F(MSR_IMM), Modrm|Vex128|xVexMap7|EVex128|VexW0|NoSuf, { Imm32, Reg64 }
+// See uwrmsr for the unusual Imm32.
+wrmsrns, 0xf3f6/0, APX_F(MSR_IMM), Modrm|Vex128|xVexMap7|EVex128|VexW0|NoSuf, { Imm32, Reg64 }
+
+// MSR_IMM instructions end.
+
 // APX Push2/Pop2 instructions.
 //PUSH2/POP2 pushes/pops 2 GPRs at a time to/from the stack. So 2 GPRs are both
 //Dst/Src, here the V register is used to encode the Operand 1 (Intel format).