[binutils-gdb] x86-64: fix handling of PUSH/POP of segment register

Jan Beulich jbeulich@sourceware.org
Fri Sep 20 08:18:00 GMT 2019


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

commit 3f9aad111cea2f25877d0a6b404956769c14faee
Author: Jan Beulich <jbeulich@suse.com>
Date:   Fri Sep 20 10:18:15 2019 +0200

    x86-64: fix handling of PUSH/POP of segment register
    
    Commit 21df382b91 ("x86: fold SReg{2,3}") went too far: Folding 64-bit
    PUSH/POP templates into non-64-bit ones isn't correct, due to the
    different operand widths, and hence suffixes permitted. Restore the
    separate templates.
    
    Add tests of PUSH/POP with q suffix and %fs/%gs operands to the
    testsuite. While doing so also add PUSHF/POPF ones _without_ suffix.

Diff:
---
 gas/ChangeLog                          |  9 +++++++++
 gas/config/tc-i386.c                   |  4 ++--
 gas/testsuite/gas/i386/x86-64-opcode.d |  6 ++++++
 gas/testsuite/gas/i386/x86-64-opcode.s | 10 ++++++++--
 opcodes/ChangeLog                      |  7 +++++++
 opcodes/i386-opc.tbl                   |  6 ++++--
 opcodes/i386-tbl.h                     | 30 ++++++++++++++++++++++++++++--
 7 files changed, 64 insertions(+), 8 deletions(-)

diff --git a/gas/ChangeLog b/gas/ChangeLog
index b4234f0..bcd2f9a 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,12 @@
+2018-09-20  Jan Beulich  <jbeulich@suse.com>
+
+	PR gas/25012
+	* config/tc-i386.c (process_operands): Adjust handling of
+	PUSH/POP of segment registers.
+	* testsuite/gas/i386/x86-64-opcode.s: Add PUSHq/POPq case with
+	%fs/%gs operands. Add PUSHF/POPF case without suffix.
+	* testsuite/gas/i386/x86-64-opcode.d: Adjust expectations.
+
 2019-09-19  Matthew Malcomson  <matthew.malcomson@arm.com>
 
 	* NEWS: Add SVE2 and TME entries.
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index fec69c1..349b36d 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -7010,14 +7010,14 @@ duplicate:
 	  if (flag_code != CODE_64BIT
 	      ? i.tm.base_opcode == POP_SEG_SHORT
 		&& i.op[0].regs->reg_num == 1
-	      : (i.tm.base_opcode | 1) == POP_SEG_SHORT
+	      : (i.tm.base_opcode | 1) == POP_SEG386_SHORT
 		&& i.op[0].regs->reg_num < 4)
 	    {
 	      as_bad (_("you can't `%s %s%s'"),
 		      i.tm.name, register_prefix, i.op[0].regs->reg_name);
 	      return 0;
 	    }
-	  if ( i.op[0].regs->reg_num > 3 )
+	  if ( i.op[0].regs->reg_num > 3 && i.tm.opcode_length == 1 )
 	    {
 	      i.tm.base_opcode ^= POP_SEG_SHORT ^ POP_SEG386_SHORT;
 	      i.tm.opcode_length = 2;
diff --git a/gas/testsuite/gas/i386/x86-64-opcode.d b/gas/testsuite/gas/i386/x86-64-opcode.d
index 35829f4..d8a1e44 100644
--- a/gas/testsuite/gas/i386/x86-64-opcode.d
+++ b/gas/testsuite/gas/i386/x86-64-opcode.d
@@ -255,13 +255,19 @@ Disassembly of section .text:
 [ 	]*[a-f0-9]+:	41 8f 00             	popq   \(%r8\)
 [ 	]*[a-f0-9]+:	8f 00                	popq   \(%rax\)
 [ 	]*[a-f0-9]+:	0f a1                	popq   %fs
+[ 	]*[a-f0-9]+:	0f a1                	popq   %fs
+[ 	]*[a-f0-9]+:	0f a9                	popq   %gs
 [ 	]*[a-f0-9]+:	0f a9                	popq   %gs
 [ 	]*[a-f0-9]+:	9d                   	popfq  
+[ 	]*[a-f0-9]+:	9d                   	popfq  
 [ 	]*[a-f0-9]+:	41 ff 30             	pushq  \(%r8\)
 [ 	]*[a-f0-9]+:	ff 30                	pushq  \(%rax\)
 [ 	]*[a-f0-9]+:	0f a0                	pushq  %fs
+[ 	]*[a-f0-9]+:	0f a0                	pushq  %fs
+[ 	]*[a-f0-9]+:	0f a8                	pushq  %gs
 [ 	]*[a-f0-9]+:	0f a8                	pushq  %gs
 [ 	]*[a-f0-9]+:	9c                   	pushfq 
+[ 	]*[a-f0-9]+:	9c                   	pushfq 
 [ 	]*[a-f0-9]+:	0f 77                	emms   
 [ 	]*[a-f0-9]+:	0f 0e                	femms  
 [ 	]*[a-f0-9]+:	0f 08                	invd   
diff --git a/gas/testsuite/gas/i386/x86-64-opcode.s b/gas/testsuite/gas/i386/x86-64-opcode.s
index 8d4a6ed..caee124 100644
--- a/gas/testsuite/gas/i386/x86-64-opcode.s
+++ b/gas/testsuite/gas/i386/x86-64-opcode.s
@@ -323,15 +323,21 @@
 	POPq (%r8)		      #	 --  --	 -- 41	 8F 00				 ; REX to access upper reg.
 	POPq (%rax)		      #	 --  --	 -- --	 8F 00
 	POP %fs			      #	 --  --	 -- --	 0F A1
+	POPq %fs		      #	 --  --	 -- --	 0F A1
 	POP %gs			      #	 --  --	 -- --	 0F A9
-	POPFQ			      #	 --  --	 -- --	 9D
+	POPq %gs		      #	 --  --	 -- --	 0F A9
+	POPF			      #	 --  --	 -- --	 9D
+	POPFq			      #	 --  --	 -- --	 9D
 
 	# PUSH
 	PUSHq (%r8)		      #	 --  --	 -- 41	 FF 30				 ; REX to access upper reg.
 	PUSHq (%rax)		      #	 --  --	 -- --	 FF 30
 	PUSH %fs		      #	 --  --	 -- --	 0F A0
+	PUSHq %fs		      #	 --  --	 -- --	 0F A0
 	PUSH %gs		      #	 --  --	 -- --	 0F A8
-	PUSHFQ			      #	 --  --	 -- --	 9C
+	PUSHq %gs		      #	 --  --	 -- --	 0F A8
+	PUSHF			      #	 --  --	 -- --	 9C
+	PUSHFq			      #	 --  --	 -- --	 9C
 
 
 
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
index 0d8abcd..0043d4e 100644
--- a/opcodes/ChangeLog
+++ b/opcodes/ChangeLog
@@ -1,3 +1,10 @@
+2018-09-20  Jan Beulich  <jbeulich@suse.com>
+
+	PR gas/25012
+	* i386-opc.tbl (push, pop): Re-instate distinct Cpu64 templates
+	with SReg operand.
+	* i386-tbl.h: Re-generate.
+
 2019-09-18  Alan Modra  <amodra@gmail.com>
 
 	* arc-ext.c: Update throughout for bfd section macro changes.
diff --git a/opcodes/i386-opc.tbl b/opcodes/i386-opc.tbl
index af2b600..256ff04 100644
--- a/opcodes/i386-opc.tbl
+++ b/opcodes/i386-opc.tbl
@@ -116,22 +116,24 @@ push, 1, 0x50, None, 1, CpuNo64, ShortForm|DefaultSize|No_bSuf|No_sSuf|No_qSuf|N
 push, 1, 0xff, 0x6, 1, CpuNo64, Modrm|DefaultSize|No_bSuf|No_sSuf|No_qSuf|No_ldSuf, { Reg16|Reg32|Word|Dword|Unspecified|BaseIndex }
 push, 1, 0x6a, None, 1, Cpu186|CpuNo64, DefaultSize|No_bSuf|No_sSuf|No_qSuf|No_ldSuf, { Imm8S }
 push, 1, 0x68, None, 1, Cpu186|CpuNo64, DefaultSize|No_bSuf|No_sSuf|No_qSuf|No_ldSuf, { Imm16|Imm32 }
-push, 1, 0x6, None, 1, 0, ShortForm|DefaultSize|No_bSuf|No_sSuf|No_qSuf|No_ldSuf, { SReg }
+push, 1, 0x6, None, 1, CpuNo64, ShortForm|DefaultSize|No_bSuf|No_sSuf|No_qSuf|No_ldSuf, { SReg }
 // In 64bit mode, the operand size is implicitly 64bit.
 push, 1, 0x50, None, 1, Cpu64, ShortForm|DefaultSize|No_bSuf|No_lSuf|No_sSuf|No_ldSuf|NoRex64, { Reg16|Reg64 }
 push, 1, 0xff, 0x6, 1, Cpu64, Modrm|DefaultSize|No_bSuf|No_lSuf|No_sSuf|No_ldSuf|NoRex64, { Reg16|Reg64|Word|Qword|Unspecified|BaseIndex }
 push, 1, 0x6a, None, 1, Cpu64, DefaultSize|No_bSuf|No_lSuf|No_sSuf|No_ldSuf|NoRex64, { Imm8S }
 push, 1, 0x68, None, 1, Cpu64, DefaultSize|No_bSuf|No_lSuf|No_sSuf|No_ldSuf|NoRex64, { Imm16|Imm32S }
+push, 1, 0xfa0, None, 2, Cpu64, ShortForm|DefaultSize|No_bSuf|No_lSuf|No_sSuf|No_ldSuf|NoRex64, { SReg }
 
 pusha, 0, 0x60, None, 1, Cpu186|CpuNo64, DefaultSize|No_bSuf|No_sSuf|No_qSuf|No_ldSuf, { 0 }
 
 // Pop instructions.
 pop, 1, 0x58, None, 1, CpuNo64, ShortForm|DefaultSize|No_bSuf|No_sSuf|No_qSuf|No_ldSuf, { Reg16|Reg32 }
 pop, 1, 0x8f, 0x0, 1, CpuNo64, Modrm|DefaultSize|No_bSuf|No_sSuf|No_qSuf|No_ldSuf, { Reg16|Reg32|Word|Dword|Unspecified|BaseIndex }
-pop, 1, 0x7, None, 1, 0, ShortForm|DefaultSize|No_bSuf|No_sSuf|No_qSuf|No_ldSuf, { SReg }
+pop, 1, 0x7, None, 1, CpuNo64, ShortForm|DefaultSize|No_bSuf|No_sSuf|No_qSuf|No_ldSuf, { SReg }
 // In 64bit mode, the operand size is implicitly 64bit.
 pop, 1, 0x58, None, 1, Cpu64, ShortForm|DefaultSize|No_bSuf|No_lSuf|No_sSuf|No_ldSuf|NoRex64, { Reg16|Reg64 }
 pop, 1, 0x8f, 0x0, 1, Cpu64, Modrm|DefaultSize|No_bSuf|No_lSuf|No_sSuf|No_ldSuf|NoRex64, { Reg16|Reg64|Word|Qword|Unspecified|BaseIndex }
+pop, 1, 0xfa1, None, 2, Cpu64, ShortForm|DefaultSize|No_bSuf|No_lSuf|No_sSuf|No_ldSuf|NoRex64, { SReg }
 
 popa, 0, 0x61, None, 1, Cpu186|CpuNo64, DefaultSize|No_bSuf|No_sSuf|No_qSuf|No_ldSuf, { 0 }
 
diff --git a/opcodes/i386-tbl.h b/opcodes/i386-tbl.h
index 307415e..89c752e 100644
--- a/opcodes/i386-tbl.h
+++ b/opcodes/i386-tbl.h
@@ -635,7 +635,7 @@ const insn_template i386_optab[] =
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0 } },
+        0, 0, 0, 0, 0, 0, 0, 1, 0 } },
     { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1,
       1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -694,6 +694,19 @@ const insn_template i386_optab[] =
       0 },
     { { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0,
 	  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } } },
+  { "push", 1, 0xfa0, None, 2,
+    { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 1, 0, 0 } },
+    { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0,
+      1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+      0 },
+    { { { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } } },
   { "pusha", 0, 0x60, None, 1,
     { { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -739,7 +752,7 @@ const insn_template i386_optab[] =
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0 } },
+        0, 0, 0, 0, 0, 0, 0, 1, 0 } },
     { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1,
       1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -772,6 +785,19 @@ const insn_template i386_optab[] =
       0 },
     { { { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0,
 	  0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0 } } } },
+  { "pop", 1, 0xfa1, None, 2,
+    { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 1, 0, 0 } },
+    { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0,
+      1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+      0 },
+    { { { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } } },
   { "popa", 0, 0x61, None, 1,
     { { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,



More information about the Binutils-cvs mailing list