From 7ecd2f8b9dfd610b8c62cedb87ed513289c85c04 Mon Sep 17 00:00:00 2001
From: Jan Hubicka <jh@suse.cz>
Date: Mon, 11 Feb 2002 12:00:54 +0000
Subject: [PATCH] 	* i386.c (md_assemble): Support 32bit address prefix. 
 (i386_displacement): Likewise. 	(i386_index_check): Accept 32bit
 addressing in 64bit mode.

---
 gas/ChangeLog        |  6 +++++
 gas/config/tc-i386.c | 55 +++++++++++++++++++++++++++++++++-----------
 2 files changed, 47 insertions(+), 14 deletions(-)

diff --git a/gas/ChangeLog b/gas/ChangeLog
index 234f835fdce..12841ede464 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,9 @@
+Mon Feb 11 12:59:29 CET 2002  Jan Hubicka  <jh@suse.cz>
+
+	* i386.c (md_assemble): Support 32bit address prefix.
+	(i386_displacement): Likewise.
+	(i386_index_check): Accept 32bit addressing in 64bit mode.
+
 2002-02-11  Alexandre Oliva  <aoliva@redhat.com>
 
 	* config/tc-sh.c (dot): Removed unused function.
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 650621feeb2..cce25d8b332 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -1298,6 +1298,7 @@ md_assemble (line)
 	    /* If we are in 16-bit mode, do not allow addr16 or data16.
 	       Similarly, in 32-bit mode, do not allow addr32 or data32.  */
 	    if ((current_templates->start->opcode_modifier & (Size16 | Size32))
+		&& flag_code != CODE_64BIT
 		&& (((current_templates->start->opcode_modifier & Size32) != 0)
 		    ^ (flag_code == CODE_16BIT)))
 	      {
@@ -2263,6 +2264,14 @@ md_assemble (line)
 	      return;
 	  }
 
+	if (i.suffix != QWORD_MNEM_SUFFIX && (flag_code == CODE_64BIT)
+	    && !(i.tm.opcode_modifier & IgnoreSize)
+	    && (i.tm.opcode_modifier & JumpByte))
+	  {
+	    if (! add_prefix (ADDR_PREFIX_OPCODE))
+	      return;
+	  }
+
 	/* Set mode64 for an operand.  */
 	if (i.suffix == QWORD_MNEM_SUFFIX
 	    && !(i.tm.opcode_modifier & NoRex64))
@@ -2415,13 +2424,15 @@ md_assemble (line)
 			if (! i.index_reg)
 			  {
 			    /* Operand is just <disp>  */
-			    if ((flag_code == CODE_16BIT) ^ (i.prefix[ADDR_PREFIX] != 0))
+			    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)
+			    else if (flag_code != CODE_64BIT
+				     || (i.prefix[ADDR_PREFIX] != 0))
 			      {
 				i.rm.regmem = NO_BASE_REGISTER;
 				i.types[op] &= ~Disp;
@@ -3438,10 +3449,13 @@ i386_displacement (disp_start, disp_end)
 #endif
   int bigdisp = Disp32;
 
-  if ((flag_code == CODE_16BIT) ^ (i.prefix[ADDR_PREFIX] != 0))
-    bigdisp = Disp16;
   if (flag_code == CODE_64BIT)
-    bigdisp = Disp64;
+    {
+      if (!i.prefix[ADDR_PREFIX])
+        bigdisp = Disp64;
+    }
+  else if ((flag_code == CODE_16BIT) ^ (i.prefix[ADDR_PREFIX] != 0))
+    bigdisp = Disp16;
   i.types[this_operand] |= bigdisp;
 
   exp = &disp_expressions[i.disp_operands];
@@ -3596,15 +3610,28 @@ i386_index_check (operand_string)
   ok = 1;
   if (flag_code == CODE_64BIT)
     {
-      /* 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;
+      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;
+	}
     }
   else
     {