This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] x86-64: enhance handling of (multiple) REX prefixes


Having found that x86-64 Linux has ill uses of rex64 prefixes in
inline assembly like __asm__("rex64 ; fxsave %0" ...), which in case
of the fxsave operand itself requiring use of some other REX form
results in two REX prefixes emitted, resulting in the operation no
longer being carried out with 64-bit operand size, I tried to prepare
a patch for that when I found that the assembler needlessly rejects
a (compiler generated) construct like "rex64/fxsave (%r12)". Thus this
patch separates treatment of rex64 (and plain rex) from that of the
other forms.

Built and tested on x86_64-unknown-linux-gnu and i386-pc-linux-gnu.

Jan

gas/
2005-11-21  Jan Beulich  <jbeulich@novell.com>

	* config/tc-i386.c (add_prefix): More fine-grained handling of
	REX prefixes. Or new prefix value into i.prefix instead of
	assigning.

gas/testsuite/
2005-11-21  Jan Beulich  <jbeulich@novell.com>

	* gas/i386/rex.[sd]: New.
	* gas/i386/i386.exp: Run new test.

---
/home/jbeulich/src/binutils/mainline/2005-11-16/gas/config/tc-i386.c	2005-11-16
08:52:46.000000000 +0100
+++ 2005-11-16/gas/config/tc-i386.c	2005-11-21 11:48:00.067458832
+0100
@@ -730,55 +730,66 @@ add_prefix (prefix)
      unsigned int prefix;
 {
   int ret = 1;
-  int q;
+  unsigned int q;
 
   if (prefix >= REX_OPCODE && prefix < REX_OPCODE + 16
       && flag_code == CODE_64BIT)
-    q = REX_PREFIX;
+    {
+      if ((i.prefix[REX_PREFIX] & prefix & REX_MODE64)
+	  || ((i.prefix[REX_PREFIX] & (REX_EXTX | REX_EXTY | REX_EXTZ))
+	      && (prefix & (REX_EXTX | REX_EXTY | REX_EXTZ))))
+	ret = 0;
+      q = REX_PREFIX;
+    }
   else
-    switch (prefix)
-      {
-      default:
-	abort ();
+    {
+      switch (prefix)
+	{
+	default:
+	  abort ();
 
-      case CS_PREFIX_OPCODE:
-      case DS_PREFIX_OPCODE:
-      case ES_PREFIX_OPCODE:
-      case FS_PREFIX_OPCODE:
-      case GS_PREFIX_OPCODE:
-      case SS_PREFIX_OPCODE:
-	q = SEG_PREFIX;
-	break;
+	case CS_PREFIX_OPCODE:
+	case DS_PREFIX_OPCODE:
+	case ES_PREFIX_OPCODE:
+	case FS_PREFIX_OPCODE:
+	case GS_PREFIX_OPCODE:
+	case SS_PREFIX_OPCODE:
+	  q = SEG_PREFIX;
+	  break;
 
-      case REPNE_PREFIX_OPCODE:
-      case REPE_PREFIX_OPCODE:
-	ret = 2;
-	/* fall thru */
-      case LOCK_PREFIX_OPCODE:
-	q = LOCKREP_PREFIX;
-	break;
+	case REPNE_PREFIX_OPCODE:
+	case REPE_PREFIX_OPCODE:
+	  ret = 2;
+	  /* fall thru */
+	case LOCK_PREFIX_OPCODE:
+	  q = LOCKREP_PREFIX;
+	  break;
 
-      case FWAIT_OPCODE:
-	q = WAIT_PREFIX;
-	break;
+	case FWAIT_OPCODE:
+	  q = WAIT_PREFIX;
+	  break;
 
-      case ADDR_PREFIX_OPCODE:
-	q = ADDR_PREFIX;
-	break;
+	case ADDR_PREFIX_OPCODE:
+	  q = ADDR_PREFIX;
+	  break;
 
-      case DATA_PREFIX_OPCODE:
-	q = DATA_PREFIX;
-	break;
-      }
+	case DATA_PREFIX_OPCODE:
+	  q = DATA_PREFIX;
+	  break;
+	}
+      if (i.prefix[q] != 0)
+	ret = 0;
+    }
 
-  if (i.prefix[q] != 0)
+  if (ret)
     {
-      as_bad (_("same type of prefix used twice"));
-      return 0;
+      if (!i.prefix[q])
+	++i.prefixes;
+      i.prefix[q] |= prefix;
     }
+  else
+    as_bad (_("same type of prefix used twice"));
 
-  i.prefixes += 1;
-  i.prefix[q] = prefix;
   return ret;
 }
 
---
/home/jbeulich/src/binutils/mainline/2005-11-16/gas/testsuite/gas/i386/i386.exp	2005-11-07
08:48:26.000000000 +0100
+++ 2005-11-16/gas/testsuite/gas/i386/i386.exp	2005-11-21
12:19:47.000000000 +0100
@@ -132,6 +132,21 @@ if [expr ([istarget "i*86-*-*"] || [ista
     run_dump_test "x86-64-vmx"
     run_dump_test "immed64"
 
+    if { ![istarget "*-*-aix*"]
+      && ![istarget "*-*-beos*"]
+      && ![istarget "*-*-*bsd*"]
+      && ![istarget "*-*-chaos*"]
+      && ![istarget "*-*-kaos*"]
+      && ![istarget "*-*-lynx*"]
+      && ![istarget "*-*-moss*"]
+      && ![istarget "*-*-nto-qnx*"]
+      && ![istarget "*-*-rtems*"]
+      && ![istarget "*-*-sco*"]
+      && ![istarget "*-*-solaris*"]
+      && ![istarget "*-*-sysv*"] } then {
+	run_dump_test "rex"
+    }
+
     # For ELF targets verify that @unwind works.
     if { ([istarget "*-*-elf*"] || [istarget "*-*-linux*"]
 	  || [istarget "*-*-solaris2.*"])
---
/home/jbeulich/src/binutils/mainline/2005-11-16/gas/testsuite/gas/i386/rex.d	1970-01-01
01:00:00.000000000 +0100
+++ 2005-11-16/gas/testsuite/gas/i386/rex.d	2005-11-21
11:21:12.000000000 +0100
@@ -0,0 +1,17 @@
+#objdump: -dw
+#name: x86-64 manual rex prefix use
+
+.*: +file format elf64-x86-64
+
+Disassembly of section .text:
+
+0+ <_start>:
+[	 ]*[0-9a-f]+:[	 ]+40 0f ae 00[	 ]+rex fxsavel?[	
]+\(%rax\)
+[	 ]*[0-9a-f]+:[	 ]+48 0f ae 00[	 ]+(rex64 )?fxsaveq?[	
]+\(%rax\)
+[	 ]*[0-9a-f]+:[	 ]+41 0f ae 00[	 ]+fxsavel?[	 ]+\(%r8\)
+[	 ]*[0-9a-f]+:[	 ]+49 0f ae 00[	 ]+(rex64Z? )?fxsaveq?[	
]+\(%r8\)
+[	 ]*[0-9a-f]+:[	 ]+42 0f ae 04 05 00 00 00 00[	 ]+fxsavel?[	
]+(0x0)?\(,%r8(,1)?\)
+[	 ]*[0-9a-f]+:[	 ]+4a 0f ae 04 05 00 00 00 00[	 ]+(rex64Y?
)?fxsaveq?[	 ]+(0x0)?\(,%r8(,1)?\)
+[	 ]*[0-9a-f]+:[	 ]+43 0f ae 04 00[	 ]+fxsavel?[	
]+\(%r8,%r8(,1)?\)
+[	 ]*[0-9a-f]+:[	 ]+4b 0f ae 04 00[	 ]+(rex64(YZ)?
)?fxsaveq?[	 ]+\(%r8,%r8(,1)?\)
+#pass
---
/home/jbeulich/src/binutils/mainline/2005-11-16/gas/testsuite/gas/i386/rex.s	1970-01-01
01:00:00.000000000 +0100
+++ 2005-11-16/gas/testsuite/gas/i386/rex.s	2005-11-21
11:12:07.000000000 +0100
@@ -0,0 +1,11 @@
+ .text
+
+_start:
+	rex/fxsave (%rax)
+	rex64/fxsave (%rax)
+	rex/fxsave (%r8)
+	rex64/fxsave (%r8)
+	rex/fxsave (,%r8)
+	rex64/fxsave (,%r8)
+	rex/fxsave (%r8,%r8)
+	rex64/fxsave (%r8,%r8)

Attachment: binutils-mainline-x86_64-rex.patch
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]