[PATCH] x86-64 corrections

Jan Beulich JBeulich@novell.com
Fri Jul 2 12:41:00 GMT 2004


This is an update to the earlier sent out patch that wasn't accepted for
the
reason of the FSF copyright assignment not yet in place.

Note that when applying this together with the earlier posted Intel
syntax
patch, then there is going to be a failure in the intelbad gas test
introduced
with the Intel syntax patch. This can be addressed by simply adding an
error
expectation for line 7 to testsuite/gas/i386/intelbad.l.

Jan

gas:
2004-07-02 Jan Beulich <jbeulich@novell.com>

	* config/tc-i386.c (optimize_imm): Adjust immediates to only
those
	permissible for the selected instruction suffix.
	(match_template): Don't permit 64-bit general purpose operands
in
	32-bit mode.
	(finalize_imm): Permit 64-bit immediates.
	(build_modrm_byte): Don't treat 32-bit addressing in 64-bit
mode
	specially except for the width of the used base and/or index
registers.
	For 32-bit displacements, use sign-extended relocations only
when
	using 64-bit addressing.
	Force zero displacement on rip-relative addressing when there is
no
	other displacement.
	(i386_index_check): Don't treat 32-bit addressing in 64-bit
mode
	specially except for the width of the used base and/or index
	registers.
	(parse_register): Disallow Reg64 registers in 32-bit mode.
	* testsuite/gas/i386/x86-64-addr32.[ds]: New test for x86-64
	32-bit addressing in 64-bit mode.
	* testsuite/gas/i386/x86-64-rip.[ds]: New test for x86-64
	rip-relative addressing.
	* testsuite/gas/i386/i386.exp: Run the two new tests.

opcodes:
2004-07-02 Jan Beulich <jbeulich@novell.com>

	* i386-dis.c (OP_E): Show rip-relative addressing in 64-bit
mode
	regardless of address size prefix in effect.
	(ptr_reg): Size or address registers does not depend on rex64,
but on
	the presence of an address size override.
	(OP_MMX): Use rex.x only for xmm registers.
	(OP_EM): Use rex.z only for xmm registers.

diff -Naur
/home/jbeulich/src/binutils/mainline/2004-07-02.08.43/gas/config/tc-i386.c
2004-07-02.08.43-fixes/gas/config/tc-i386.c
---
/home/jbeulich/src/binutils/mainline/2004-07-02.08.43/gas/config/tc-i386.c	2004-06-28
16:51:56.000000000 +0200
+++ 2004-07-02.08.43-fixes/gas/config/tc-i386.c	2004-07-02
11:16:11.482954688 +0200
@@ -1922,15 +1922,13 @@
 		i.types[op] = Imm64 | Imm32S;
 		break;
 	      case LONG_MNEM_SUFFIX:
-		i.types[op] = Imm32 | Imm64;
+		i.types[op] = Imm32;
 		break;
 	      case WORD_MNEM_SUFFIX:
-		i.types[op] = Imm16 | Imm32 | Imm64;
-		break;
+		i.types[op] = Imm16;
 		break;
 	      case BYTE_MNEM_SUFFIX:
-		i.types[op] = Imm8 | Imm8S | Imm16 | Imm32S | Imm32;
-		break;
+		i.types[op] = Imm8 | Imm8S;
 		break;
 	      }
 	    break;
@@ -2018,9 +2016,18 @@
 			      : (i.suffix == LONG_DOUBLE_MNEM_SUFFIX
 				 ? No_xSuf : 0))))));
 
-  for (t = current_templates->start;
-       t < current_templates->end;
-       t++)
+  t = current_templates->start;
+  if (i.suffix == QWORD_MNEM_SUFFIX
+      && flag_code != CODE_64BIT
+      && (!intel_syntax
+	  || (!(t->opcode_modifier & IgnoreSize)
+	      && !intel_float_operand(t->name)))
+      && (!(t->operand_types[0] & (RegMMX|RegXMM))
+	  || !(t->operand_types[t->operands > 1] & (RegMMX|RegXMM)))
+      && (t->base_opcode != 0x0fc7
+	  || t->extension_opcode != 1 /* cmpxchg8b */))
+    t = current_templates->end;
+  for (; t < current_templates->end; t++)
     {
       /* Must have right number of operands.  */
       if (i.operands != t->operands)
@@ -2504,7 +2511,7 @@
   unsigned int overlap0, overlap1, overlap2;
 
   overlap0 = i.types[0] & i.tm.operand_types[0];
-  if ((overlap0 & (Imm8 | Imm8S | Imm16 | Imm32 | Imm32S))
+  if ((overlap0 & (Imm8 | Imm8S | Imm16 | Imm32 | Imm32S | Imm64))
       && overlap0 != Imm8 && overlap0 != Imm8S
       && overlap0 != Imm16 && overlap0 != Imm32S
       && overlap0 != Imm32 && overlap0 != Imm64)
@@ -2537,7 +2544,7 @@
   i.types[0] = overlap0;
 
   overlap1 = i.types[1] & i.tm.operand_types[1];
-  if ((overlap1 & (Imm8 | Imm8S | Imm16 | Imm32S | Imm32))
+  if ((overlap1 & (Imm8 | Imm8S | Imm16 | Imm32S | Imm32 | Imm64))
       && overlap1 != Imm8 && overlap1 != Imm8S
       && overlap1 != Imm16 && overlap1 != Imm32S
       && overlap1 != Imm32 && overlap1 != Imm64)
@@ -2733,21 +2740,7 @@
 	      if (i.index_reg == 0)
 		{
 		  /* Operand is just <disp>  */
-		  if ((flag_code == CODE_16BIT) ^ (i.prefix[ADDR_PREFIX]
!= 0)
-		      && (flag_code != CODE_64BIT))
-		    {
-		      i.rm.regmem = NO_BASE_REGISTER_16;
-		      i.types[op] &= ~Disp;
-		      i.types[op] |= Disp16;
-		    }
-		  else if (flag_code != CODE_64BIT
-			   || (i.prefix[ADDR_PREFIX] != 0))
-		    {
-		      i.rm.regmem = NO_BASE_REGISTER;
-		      i.types[op] &= ~Disp;
-		      i.types[op] |= Disp32;
-		    }
-		  else
+		  if (flag_code == CODE_64BIT)
 		    {
 		      /* 64bit mode overwrites the 32bit absolute
 			 addressing by RIP relative addressing and
@@ -2756,8 +2749,17 @@
 		      i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
 		      i.sib.base = NO_BASE_REGISTER;
 		      i.sib.index = NO_INDEX_REGISTER;
-		      i.types[op] &= ~Disp;
-		      i.types[op] |= Disp32S;
+		      i.types[op] = ((i.prefix[ADDR_PREFIX] == 0) ?
Disp32S : Disp32);
+		    }
+		  else if ((flag_code == CODE_16BIT) ^
(i.prefix[ADDR_PREFIX] != 0))
+		    {
+		      i.rm.regmem = NO_BASE_REGISTER_16;
+		      i.types[op] = Disp16;
+		    }
+		  else
+		    {
+		      i.rm.regmem = NO_BASE_REGISTER;
+		      i.types[op] = Disp32;
 		    }
 		}
 	      else /* !i.base_reg && i.index_reg  */
@@ -2782,6 +2784,8 @@
 	      i.types[op] &= ~Disp;
 	      i.types[op] |= Disp32S;
 	      i.flags[op] = Operand_PCrel;
+	      if (! i.disp_operands)
+		   fake_zero_displacement = 1;
 	    }
 	  else if (i.base_reg->reg_type & Reg16)
 	    {
@@ -2818,10 +2822,7 @@
 	      if (flag_code == CODE_64BIT
 		  && (i.types[op] & Disp))
 		{
-		  if (i.types[op] & Disp8)
-		    i.types[op] = Disp8 | Disp32S;
-		  else
-		    i.types[op] = Disp32S;
+		  i.types[op] = (i.types[op] & Disp8) |
(i.prefix[ADDR_PREFIX] == 0 ? Disp32S : Disp32);
 		}
 	      i.rm.regmem = i.base_reg->reg_num;
 	      if ((i.base_reg->reg_flags & RegRex) != 0)
@@ -4001,28 +4002,16 @@
   ok = 1;
   if (flag_code == CODE_64BIT)
     {
-      if (i.prefix[ADDR_PREFIX] == 0)
-	{
-	  /* 64bit checks.  */
-	  if ((i.base_reg
-	       && ((i.base_reg->reg_type & Reg64) == 0)
-		   && (i.base_reg->reg_type != BaseIndex
-		       || i.index_reg))
-	      || (i.index_reg
-		  && ((i.index_reg->reg_type & (Reg64 | BaseIndex))
-		      != (Reg64 | BaseIndex))))
-	    ok = 0;
-	}
-      else
-	{
-	  /* 32bit checks.  */
-	  if ((i.base_reg
-	       && (i.base_reg->reg_type & (Reg32 | RegRex)) != Reg32)
-	      || (i.index_reg
-		  && ((i.index_reg->reg_type & (Reg32 | BaseIndex |
RegRex))
-		      != (Reg32 | BaseIndex))))
-	    ok = 0;
-	}
+      unsigned RegXX = (i.prefix[ADDR_PREFIX] == 0 ? Reg64 : Reg32);
+
+      if ((i.base_reg
+	   && ((i.base_reg->reg_type & RegXX) == 0)
+		&& (i.base_reg->reg_type != BaseIndex
+		    || i.index_reg))
+	  || (i.index_reg
+	      && ((i.index_reg->reg_type & (RegXX | BaseIndex))
+		  != (RegXX | BaseIndex))))
+	ok = 0;
     }
   else
     {
@@ -4055,8 +4044,7 @@
   if (!ok)
     {
 #if INFER_ADDR_PREFIX
-      if (flag_code != CODE_64BIT
-	  && i.prefix[ADDR_PREFIX] == 0 && stackop_size != '\0')
+      if (i.prefix[ADDR_PREFIX] == 0)
 	{
 	  i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE;
 	  i.prefixes += 1;
@@ -4065,7 +4053,7 @@
 	     FIXME.  There doesn't seem to be any real need for
separate
 	     Disp16 and Disp32 flags.  The same goes for Imm16 and
Imm32.
 	     Removing them would probably clean up the code quite a lot.
 */
-	  if (i.types[this_operand] & (Disp16 | Disp32))
+	  if (flag_code != CODE_64BIT && (i.types[this_operand] &
(Disp16 | Disp32)))
 	     i.types[this_operand] ^= (Disp16 | Disp32);
 	  fudged = 1;
 	  goto tryprefix;
@@ -4078,9 +4066,8 @@
 	as_bad (_("`%s' is not a valid %s bit base/index expression"),
 		operand_string,
 		flag_code_names[flag_code]);
-      return 0;
     }
-  return 1;
+  return ok;
 }
 
 /* Parse OPERAND_STRING into the i386_insn structure I.  Returns
non-zero
@@ -4904,7 +4891,7 @@
     }
 
   if (r != NULL
-      && (r->reg_flags & (RegRex64 | RegRex)) != 0
+      && ((r->reg_flags & (RegRex64 | RegRex)) | (r->reg_type &
Reg64)) != 0
       && flag_code != CODE_64BIT)
     {
       return (const reg_entry *) NULL;
diff -Naur
/home/jbeulich/src/binutils/mainline/2004-07-02.08.43/gas/testsuite/gas/i386/i386.exp
2004-07-02.08.43-fixes/gas/testsuite/gas/i386/i386.exp
---
/home/jbeulich/src/binutils/mainline/2004-07-02.08.43/gas/testsuite/gas/i386/i386.exp	2004-05-12
05:06:10.000000000 +0200
+++
2004-07-02.08.43-fixes/gas/testsuite/gas/i386/i386.exp	2004-07-02
11:16:11.483954536 +0200
@@ -105,7 +105,9 @@
     set ASFLAGS "$ASFLAGS --64"
 
     run_dump_test "x86_64"
+    run_dump_test "x86-64-addr32"
     run_dump_test "x86-64-opcode"
+    run_dump_test "x86-64-rip"
     run_list_test "x86-64-inval" "-al"
 
     set ASFLAGS "$old_ASFLAGS"
diff -Naur
/home/jbeulich/src/binutils/mainline/2004-07-02.08.43/gas/testsuite/gas/i386/x86-64-addr32.d
2004-07-02.08.43-fixes/gas/testsuite/gas/i386/x86-64-addr32.d
---
/home/jbeulich/src/binutils/mainline/2004-07-02.08.43/gas/testsuite/gas/i386/x86-64-addr32.d	1970-01-01
01:00:00.000000000 +0100
+++
2004-07-02.08.43-fixes/gas/testsuite/gas/i386/x86-64-addr32.d	2004-06-02
14:45:09.000000000 +0200
@@ -0,0 +1,13 @@
+#as: -J
+#objdump: -drw
+#name: x86-64 32-bit addressing
+
+.*: +file format elf64-x86-64
+
+Disassembly of section .text:
+
+0+000 <.text>:
+[	 ]*0:[	 ]+67 48 8d 80 00 00 00 00[	 ]+addr32[	 ]+lea[	
]+0x0\(%[re]ax\),%rax.*
+[	 ]*8:[	 ]+67 49 8d 80 00 00 00 00[	 ]+addr32[	 ]+lea[	
]+0x0\(%r8d?\),%rax.*
+[	 ]*10:[	 ]+67 48 8d 05 00 00 00 00[	 ]+addr32[	 ]+lea[	
]+0\(%[re]ip\),%rax.*
+[	 ]*18:[	 ]+67 48 8d 04 25 00 00 00 00[	 ]+addr32[	 ]+lea[	
]+0x0,%rax.*
diff -Naur
/home/jbeulich/src/binutils/mainline/2004-07-02.08.43/gas/testsuite/gas/i386/x86-64-addr32.s
2004-07-02.08.43-fixes/gas/testsuite/gas/i386/x86-64-addr32.s
---
/home/jbeulich/src/binutils/mainline/2004-07-02.08.43/gas/testsuite/gas/i386/x86-64-addr32.s	1970-01-01
01:00:00.000000000 +0100
+++
2004-07-02.08.43-fixes/gas/testsuite/gas/i386/x86-64-addr32.s	2004-06-02
14:05:47.000000000 +0200
@@ -0,0 +1,5 @@
+.text
+	lea		symbol(%eax), %rax
+	lea		symbol(%r8d), %rax
+	addr32 lea	symbol(%rip), %rax
+	addr32 lea	symbol, %rax
diff -Naur
/home/jbeulich/src/binutils/mainline/2004-07-02.08.43/gas/testsuite/gas/i386/x86_64.d
2004-07-02.08.43-fixes/gas/testsuite/gas/i386/x86_64.d
---
/home/jbeulich/src/binutils/mainline/2004-07-02.08.43/gas/testsuite/gas/i386/x86_64.d	2001-06-12
04:03:10.000000000 +0200
+++
2004-07-02.08.43-fixes/gas/testsuite/gas/i386/x86_64.d	2004-06-30
15:44:44.000000000 +0200
@@ -37,7 +37,7 @@
 [ 	]+5a:	44 0f 20 c0[ 	]+mov[ 	]+%cr8,%rax
 [ 	]+5e:	44 0f 22 c0[ 	]+mov[ 	]+%rax,%cr8
 [ 	]+62:	f3 48 a5[ 	]+repz movsq %ds:\(%rsi\),%es:\(%rdi\)
-[ 	]+65:	f3 66 a5[ 	]+repz movsw %ds:\(%esi\),%es:\(%edi\)
+[ 	]+65:	f3 66 a5[ 	]+repz movsw %ds:\(%rsi\),%es:\(%rdi\)
 [ 	]+68:	f3 48 a5[ 	]+repz movsq %ds:\(%rsi\),%es:\(%rdi\)
 [ 	]+6b:	b0 11[ 	]+mov[ 	]+\$0x11,%al
 [ 	]+6d:	b4 11[ 	]+mov[ 	]+\$0x11,%ah
diff -Naur
/home/jbeulich/src/binutils/mainline/2004-07-02.08.43/gas/testsuite/gas/i386/x86-64-rip.d
2004-07-02.08.43-fixes/gas/testsuite/gas/i386/x86-64-rip.d
---
/home/jbeulich/src/binutils/mainline/2004-07-02.08.43/gas/testsuite/gas/i386/x86-64-rip.d	1970-01-01
01:00:00.000000000 +0100
+++
2004-07-02.08.43-fixes/gas/testsuite/gas/i386/x86-64-rip.d	2004-06-02
14:13:15.000000000 +0200
@@ -0,0 +1,13 @@
+#as: -J
+#objdump: -drw
+#name: x86-64 rip addressing
+
+.*: +file format elf64-x86-64
+
+Disassembly of section .text:
+
+0+000 <.text>:
+[	 ]*0:[	 ]+8d 05 00 00 00 00[	 ]+lea[	 ]+0\(%rip\),%eax[	
]*(#.*)?
+[	 ]*6:[	 ]+8d 05 11 11 11 11[	 ]+lea[	
]+286331153\(%rip\),%eax[	 ]*(#.*)?
+[	 ]*c:[	 ]+8d 05 01 00 00 00[	 ]+lea[	 ]+1\(%rip\),%eax[	
]*(#.*)?
+[	 ]*12:[	 ]+8d 05 00 00 00 00[	 ]+lea[	 ]+0\(%rip\),%eax[	
]*(#.*)?
diff -Naur
/home/jbeulich/src/binutils/mainline/2004-07-02.08.43/gas/testsuite/gas/i386/x86-64-rip.s
2004-07-02.08.43-fixes/gas/testsuite/gas/i386/x86-64-rip.s
---
/home/jbeulich/src/binutils/mainline/2004-07-02.08.43/gas/testsuite/gas/i386/x86-64-rip.s	1970-01-01
01:00:00.000000000 +0100
+++
2004-07-02.08.43-fixes/gas/testsuite/gas/i386/x86-64-rip.s	2004-06-02
12:00:40.000000000 +0200
@@ -0,0 +1,5 @@
+.text
+	leal	symbol(%rip), %eax
+	leal	0x11111111(%rip), %eax
+	leal	1(%rip), %eax
+	leal	(%rip), %eax
diff -Naur
/home/jbeulich/src/binutils/mainline/2004-07-02.08.43/opcodes/i386-dis.c
2004-07-02.08.43-fixes/opcodes/i386-dis.c
---
/home/jbeulich/src/binutils/mainline/2004-07-02.08.43/opcodes/i386-dis.c	2004-06-28
16:52:05.000000000 +0200
+++ 2004-07-02.08.43-fixes/opcodes/i386-dis.c	2004-07-02
11:18:32.266552328 +0200
@@ -3166,7 +3166,7 @@
 	  if ((base & 7) == 5)
 	    {
 	      havebase = 0;
-	      if (mode_64bit && !havesib && (sizeflag & AFLAG))
+	      if (mode_64bit && !havesib)
 		riprel = 1;
 	      disp = get32s ();
 	    }
@@ -3856,8 +3856,8 @@
   const char *s;
 
   *obufp++ = open_char;
-  USED_REX (REX_MODE64);
-  if (rex & REX_MODE64)
+  used_prefixes |= (prefixes & PREFIX_ADDR);
+  if (mode_64bit)
     {
       if (!(sizeflag & AFLAG))
 	s = names32[code - eAX_reg];
@@ -3939,15 +3939,17 @@
 static void
 OP_MMX (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
 {
-  int add = 0;
-  USED_REX (REX_EXTX);
-  if (rex & REX_EXTX)
-    add = 8;
   used_prefixes |= (prefixes & PREFIX_DATA);
   if (prefixes & PREFIX_DATA)
-    sprintf (scratchbuf, "%%xmm%d", reg + add);
+    {
+      int add = 0;
+      USED_REX (REX_EXTX);
+      if (rex & REX_EXTX)
+	add = 8;
+      sprintf (scratchbuf, "%%xmm%d", reg + add);
+    }
   else
-    sprintf (scratchbuf, "%%mm%d", reg + add);
+    sprintf (scratchbuf, "%%mm%d", reg);
   oappend (scratchbuf + intel_syntax);
 }
 
@@ -3965,24 +3967,26 @@
 static void
 OP_EM (int bytemode, int sizeflag)
 {
-  int add = 0;
   if (mod != 3)
     {
       OP_E (bytemode, sizeflag);
       return;
     }
-  USED_REX (REX_EXTZ);
-  if (rex & REX_EXTZ)
-    add = 8;
 
   /* Skip mod/rm byte.  */
   MODRM_CHECK;
   codep++;
   used_prefixes |= (prefixes & PREFIX_DATA);
   if (prefixes & PREFIX_DATA)
-    sprintf (scratchbuf, "%%xmm%d", rm + add);
+    {
+      int add = 0;
+      USED_REX (REX_EXTZ);
+      if (rex & REX_EXTZ)
+	add = 8;
+      sprintf (scratchbuf, "%%xmm%d", rm + add);
+    }
   else
-    sprintf (scratchbuf, "%%mm%d", rm + add);
+    sprintf (scratchbuf, "%%mm%d", rm);
   oappend (scratchbuf + intel_syntax);
 }
 

-------------- next part --------------
A non-text attachment was scrubbed...
Name: binutils-mainline-x86_64.patch
Type: application/octet-stream
Size: 14668 bytes
Desc: not available
URL: <https://sourceware.org/pipermail/binutils/attachments/20040702/bc32aad0/attachment.obj>


More information about the Binutils mailing list