[binutils-gdb/binutils-2_46-branch] x86: refine special casing of insns with MSR as immediate

Jan Beulich jbeulich@sourceware.org
Fri Apr 17 06:33:21 GMT 2026


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=155188ea10a78d18416b8c0f62e17da66d8385a7

commit 155188ea10a78d18416b8c0f62e17da66d8385a7
Author: Jan Beulich <jbeulich@suse.com>
Date:   Fri Apr 17 08:06:39 2026 +0200

    x86: refine special casing of insns with MSR as immediate
    
    PR gas/34028
    
    i.op[].imms is legitimate to de-reference only when the operand actually
    is an immediate. The pointer happens to be non-NULL for most other operand
    kinds (i.e. a deref is UB, but would likely not fault), just not for
    memory operands without displacement.
    
    Leverage that the to-be-special-cased insns all only have just a single
    immediate, and leverage further that after the immediately preceding
    swapping of operands valid immediates will come first. Hence the
    conditional can be adjusted to satisfy the criteria above, and no loop is
    needed at all.
    
    With the conditional changed, leverage the property also in optimize_imm()
    itself, reducing the number of loop iterations.

Diff:
---
 gas/config/tc-i386.c                           | 11 +++++------
 gas/testsuite/gas/i386/x86-64-msr_imm-inval.l  |  4 +++-
 gas/testsuite/gas/i386/x86-64-msr_imm-inval.s  |  2 ++
 gas/testsuite/gas/i386/x86-64-user_msr-inval.l |  4 +++-
 gas/testsuite/gas/i386/x86-64-user_msr-inval.s |  2 ++
 5 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index ca4523fe2cd..0b98509e0d6 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -7303,7 +7303,9 @@ i386_assemble (char *line)
 	  && i.imm_operands && i.operands > i.imm_operands))
       swap_2_operands (0, 1);
 
-  if (i.imm_operands)
+  /* All legitimate immediates are placed first now.  Others, if any, will be
+     rejected by match_template() anyway.  */
+  if (operand_type_check (i.types[0], imm))
     {
       /* 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
@@ -7313,10 +7315,7 @@ i386_assemble (char *line)
       if (is_cpu(current_templates.start, CpuUSER_MSR)
 	  || t->mnem_off == MN_rdmsr
 	  || t->mnem_off == MN_wrmsrns)
-	{
-	  for (j = 0; j < i.imm_operands; j++)
-	    i.types[j] = smallest_imm_type (i.op[j].imms->X_add_number);
-	}
+	i.types[0] = smallest_imm_type (i.op[0].imms->X_add_number);
       else
 	optimize_imm ();
     }
@@ -8520,7 +8519,7 @@ optimize_imm (void)
 	       && current_templates.start->mnem_off != MN_jmpabs))
     guess_suffix = LONG_MNEM_SUFFIX;
 
-  for (op = i.operands; --op >= 0;)
+  for (op = i.imm_operands; --op >= 0;)
     if (operand_type_check (i.types[op], imm))
       {
 	switch (i.op[op].imms->X_op)
diff --git a/gas/testsuite/gas/i386/x86-64-msr_imm-inval.l b/gas/testsuite/gas/i386/x86-64-msr_imm-inval.l
index 6825a145984..bbafdb47844 100644
--- a/gas/testsuite/gas/i386/x86-64-msr_imm-inval.l
+++ b/gas/testsuite/gas/i386/x86-64-msr_imm-inval.l
@@ -1,5 +1,7 @@
 .* Assembler messages:
 .*:5: Error: operand type mismatch for `rdmsr'
 .*:6: Error: operand type mismatch for `rdmsr'
-.*:7: Error: operand type mismatch for `wrmsrns'
+.*:7: Error: operand type mismatch for `rdmsr'
 .*:8: Error: operand type mismatch for `wrmsrns'
+.*:9: Error: operand type mismatch for `wrmsrns'
+.*:10: 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
index e12e5be392f..6a245bcbcf6 100644
--- a/gas/testsuite/gas/i386/x86-64-msr_imm-inval.s
+++ b/gas/testsuite/gas/i386/x86-64-msr_imm-inval.s
@@ -4,5 +4,7 @@
 _start:
 	rdmsr  $5151515151515151, %r12
 	rdmsr  $-515151, %r12
+	rdmsr  (%rax), $0
 	wrmsrns  %r12, $5151515151515151
 	wrmsrns  %r12, $-515151
+	wrmsrns  $0, (%rax)
diff --git a/gas/testsuite/gas/i386/x86-64-user_msr-inval.l b/gas/testsuite/gas/i386/x86-64-user_msr-inval.l
index 9eb3044e16e..59383063c89 100644
--- a/gas/testsuite/gas/i386/x86-64-user_msr-inval.l
+++ b/gas/testsuite/gas/i386/x86-64-user_msr-inval.l
@@ -3,7 +3,9 @@
 .*:6: Error: operand type mismatch for `urdmsr'
 .*:7: Error: operand type mismatch for `urdmsr'
 .*:8: Error: operand type mismatch for `urdmsr'
-.*:9: Error: operand type mismatch for `uwrmsr'
+.*:9: Error: operand type mismatch for `urdmsr'
 .*:10: Error: operand type mismatch for `uwrmsr'
 .*:11: Error: operand type mismatch for `uwrmsr'
 .*:12: Error: operand type mismatch for `uwrmsr'
+.*:13: Error: operand type mismatch for `uwrmsr'
+.*:14: Error: operand type mismatch for `uwrmsr'
diff --git a/gas/testsuite/gas/i386/x86-64-user_msr-inval.s b/gas/testsuite/gas/i386/x86-64-user_msr-inval.s
index e7b6d6eea83..ac22391baa3 100644
--- a/gas/testsuite/gas/i386/x86-64-user_msr-inval.s
+++ b/gas/testsuite/gas/i386/x86-64-user_msr-inval.s
@@ -6,7 +6,9 @@ _start:
 	urdmsr	$-32767, %r14
 	urdmsr	$-2147483648, %r14
 	urdmsr	$0x7fffffffffffffff, %r14
+	urdmsr	(%rax), $0
 	uwrmsr	%r12, $-1
 	uwrmsr	%r12, $-32767
 	uwrmsr	%r12, $-2147483648
 	uwrmsr	%r12, $0x7fffffffffffffff
+	uwrmsr	$0, (%rax)


More information about the Binutils-cvs mailing list