PATCH: Rewrote i386_index_check

H.J. Lu hongjiu.lu@intel.com
Thu Mar 7 21:41:00 GMT 2013


Hi,

I checked in this patch to rewrite i386_index_check.


H.J.
---
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 31cb2af..40276f4 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,8 @@
+2013-03-07  H.J. Lu  <hongjiu.lu@intel.com>
+
+	* config/tc-i386.c (flag_code_names): Removed.
+	(i386_index_check): Rewrote.
+
 2013-03-05  Yufeng Zhang  <yufeng.zhang@arm.com>
 
 	* config/tc-aarch64.c (aarch64_imm_float_p): Rename 'e' to 'pattern';
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 04640d2..f7d488c 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -425,14 +425,6 @@ enum x86_elf_abi
 static enum x86_elf_abi x86_elf_abi = I386_ABI;
 #endif
 
-/* The names used to print error messages.  */
-static const char *flag_code_names[] =
-  {
-    "32",
-    "16",
-    "64"
-  };
-
 /* 1 for intel syntax,
    0 if att syntax.  */
 static int intel_syntax = 0;
@@ -7420,14 +7412,55 @@ i386_finalize_displacement (segT exp_seg ATTRIBUTE_UNUSED, expressionS *exp,
 static int
 i386_index_check (const char *operand_string)
 {
-  int ok;
   const char *kind = "base/index";
+  enum flag_code addr_mode;
+
+  if (i.prefix[ADDR_PREFIX])
+    addr_mode = flag_code == CODE_32BIT ? CODE_16BIT : CODE_32BIT;
+  else
+    {
+      addr_mode = flag_code;
+
 #if INFER_ADDR_PREFIX
-  int fudged = 0;
+      if (i.mem_operands == 0)
+	{
+	  /* Infer address prefix from the first memory operand.  */
+	  const reg_entry *addr_reg = i.base_reg;
+
+	  if (addr_reg == NULL)
+	    addr_reg = i.index_reg;
 
- tryprefix:
+	  if (addr_reg)
+	    {
+	      if (addr_reg->reg_num == RegEip
+		  || addr_reg->reg_num == RegEiz
+		  || addr_reg->reg_type.bitfield.reg32)
+		addr_mode = CODE_32BIT;
+	      else if (flag_code != CODE_64BIT
+		       && addr_reg->reg_type.bitfield.reg16)
+		addr_mode = CODE_16BIT;
+
+	      if (addr_mode != flag_code)
+		{
+		  i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE;
+		  i.prefixes += 1;
+		  /* Change the size of any displacement too.  At most one
+		     of Disp16 or Disp32 is set.
+		     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 (flag_code != CODE_64BIT
+		      && (i.types[this_operand].bitfield.disp16
+			  || i.types[this_operand].bitfield.disp32))
+		    i.types[this_operand]
+		      = operand_type_xor (i.types[this_operand], disp16_32);
+		}
+	    }
+	}
 #endif
-  ok = 1;
+    }
+
   if (current_templates->start->opcode_modifier.isstring
       && !current_templates->start->opcode_modifier.immext
       && (current_templates->end[-1].opcode_modifier.isstring
@@ -7435,7 +7468,14 @@ i386_index_check (const char *operand_string)
     {
       /* Memory operands of string insns are special in that they only allow
 	 a single register (rDI, rSI, or rBX) as their memory address.  */
-      unsigned int expected;
+      const reg_entry *expected_reg;
+      static const char *di_si[][2] =
+	{
+	  { "esi", "edi" },
+	  { "si", "di" },
+	  { "rsi", "rdi" }
+	};
+      static const char *bx[] = { "ebx", "bx", "rbx" };
 
       kind = "string address";
 
@@ -7448,77 +7488,70 @@ i386_index_check (const char *operand_string)
 		  && current_templates->end[-1].operand_types[1]
 		     .bitfield.baseindex))
 	    type = current_templates->end[-1].operand_types[1];
-	  expected = type.bitfield.esseg ? 7 /* rDI */ : 6 /* rSI */;
+	  expected_reg = hash_find (reg_hash,
+				    di_si[addr_mode][type.bitfield.esseg]);
+
 	}
       else
-	expected = 3 /* rBX */;
+	expected_reg = hash_find (reg_hash, bx[addr_mode]);
 
-      if (!i.base_reg || i.index_reg
+      if (i.base_reg != expected_reg
+	  || i.index_reg
 	  || operand_type_check (i.types[this_operand], disp))
-	ok = -1;
-      else if (!(flag_code == CODE_64BIT
-		 ? i.prefix[ADDR_PREFIX]
-		   ? i.base_reg->reg_type.bitfield.reg32
-		   : i.base_reg->reg_type.bitfield.reg64
-		 : (flag_code == CODE_16BIT) ^ !i.prefix[ADDR_PREFIX]
-		   ? i.base_reg->reg_type.bitfield.reg32
-		   : i.base_reg->reg_type.bitfield.reg16))
-	ok = 0;
-      else if (register_number (i.base_reg) != expected)
-	ok = -1;
-
-      if (ok < 0)
-	{
-	  unsigned int j;
-
-	  for (j = 0; j < i386_regtab_size; ++j)
-	    if ((flag_code == CODE_64BIT
-		 ? i.prefix[ADDR_PREFIX]
-		   ? i386_regtab[j].reg_type.bitfield.reg32
-		   : i386_regtab[j].reg_type.bitfield.reg64
-		 : (flag_code == CODE_16BIT) ^ !i.prefix[ADDR_PREFIX]
-		   ? i386_regtab[j].reg_type.bitfield.reg32
-		   : i386_regtab[j].reg_type.bitfield.reg16)
-		&& register_number(i386_regtab + j) == expected)
-	      break;
-	  gas_assert (j < i386_regtab_size);
+	{
+	  /* The second memory operand must have the same size as
+	     the first one.  */
+	  if (i.mem_operands
+	      && i.base_reg
+	      && !((addr_mode == CODE_64BIT
+		    && i.base_reg->reg_type.bitfield.reg64)
+		   || (addr_mode == CODE_32BIT
+		       ? i.base_reg->reg_type.bitfield.reg32
+		       : i.base_reg->reg_type.bitfield.reg16)))
+	    goto bad_address;
+
 	  as_warn (_("`%s' is not valid here (expected `%c%s%s%c')"),
 		   operand_string,
 		   intel_syntax ? '[' : '(',
 		   register_prefix,
-		   i386_regtab[j].reg_name,
+		   expected_reg->reg_name,
 		   intel_syntax ? ']' : ')');
-	  ok = 1;
-	}
-    }
-  else if (flag_code == CODE_64BIT)
-    {
-      if ((i.base_reg
-	   && ((i.prefix[ADDR_PREFIX] == 0
-		&& !i.base_reg->reg_type.bitfield.reg64)
-	       || (i.prefix[ADDR_PREFIX]
-		   && !i.base_reg->reg_type.bitfield.reg32))
-	   && (i.index_reg
-	       || i.base_reg->reg_num !=
-		  (i.prefix[ADDR_PREFIX] == 0 ? RegRip : RegEip)))
-	  || (i.index_reg
-	      && !(i.index_reg->reg_type.bitfield.regxmm
-		   || i.index_reg->reg_type.bitfield.regymm)
-	      && (!i.index_reg->reg_type.bitfield.baseindex
-		  || (i.prefix[ADDR_PREFIX] == 0
-		      && i.index_reg->reg_num != RegRiz
-		      && !i.index_reg->reg_type.bitfield.reg64
-		      )
-		  || (i.prefix[ADDR_PREFIX]
-		      && i.index_reg->reg_num != RegEiz
-		      && !i.index_reg->reg_type.bitfield.reg32))))
-	ok = 0;
+	  return 1;
+	}
+      else
+	return 1;
+
+bad_address:
+      as_bad (_("`%s' is not a valid %s expression"),
+	      operand_string, kind);
+      return 0;
     }
   else
     {
-      if ((flag_code == CODE_16BIT) ^ (i.prefix[ADDR_PREFIX] != 0))
+      if (addr_mode != CODE_16BIT)
+	{
+	  /* 32-bit/64-bit checks.  */
+	  if ((i.base_reg
+	       && (addr_mode == CODE_64BIT
+		   ? !i.base_reg->reg_type.bitfield.reg64
+		   : !i.base_reg->reg_type.bitfield.reg32)
+	       && (i.index_reg
+		   || (i.base_reg->reg_num
+		       != (addr_mode == CODE_64BIT ? RegRip : RegEip))))
+	      || (i.index_reg
+		  && !i.index_reg->reg_type.bitfield.regxmm
+		  && !i.index_reg->reg_type.bitfield.regymm
+		  && ((addr_mode == CODE_64BIT
+		       ? !(i.index_reg->reg_type.bitfield.reg64
+			   || i.index_reg->reg_num == RegRiz)
+		       : !(i.index_reg->reg_type.bitfield.reg32
+			   || i.index_reg->reg_num == RegEiz))
+		      || !i.index_reg->reg_type.bitfield.baseindex)))
+	    goto bad_address;
+	}
+      else
 	{
-	  /* 16bit checks.  */
+	  /* 16-bit checks.  */
 	  if ((i.base_reg
 	       && (!i.base_reg->reg_type.bitfield.reg16
 		   || !i.base_reg->reg_type.bitfield.baseindex))
@@ -7529,58 +7562,10 @@ i386_index_check (const char *operand_string)
 			   && i.base_reg->reg_num < 6
 			   && i.index_reg->reg_num >= 6
 			   && i.log2_scale_factor == 0))))
-	    ok = 0;
-	}
-      else
-	{
-	  /* 32bit checks.  */
-	  if ((i.base_reg
-	       && !i.base_reg->reg_type.bitfield.reg32)
-	      || (i.index_reg
-		  && !i.index_reg->reg_type.bitfield.regxmm
-		  && !i.index_reg->reg_type.bitfield.regymm
-		  && ((!i.index_reg->reg_type.bitfield.reg32
-		       && i.index_reg->reg_num != RegEiz)
-		      || !i.index_reg->reg_type.bitfield.baseindex)))
-	    ok = 0;
+	    goto bad_address;
 	}
     }
-  if (!ok)
-    {
-#if INFER_ADDR_PREFIX
-      if (!i.mem_operands && !i.prefix[ADDR_PREFIX])
-	{
-	  i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE;
-	  i.prefixes += 1;
-	  /* Change the size of any displacement too.  At most one of
-	     Disp16 or Disp32 is set.
-	     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 (flag_code != CODE_64BIT
-	      && (i.types[this_operand].bitfield.disp16
-		  || i.types[this_operand].bitfield.disp32))
-	    i.types[this_operand]
-	      = operand_type_xor (i.types[this_operand], disp16_32);
-	  fudged = 1;
-	  goto tryprefix;
-	}
-      if (fudged)
-	as_bad (_("`%s' is not a valid %s expression"),
-		operand_string,
-		kind);
-      else
-#endif
-	as_bad (_("`%s' is not a valid %s-bit %s expression"),
-		operand_string,
-		flag_code_names[i.prefix[ADDR_PREFIX]
-					 ? flag_code == CODE_32BIT
-					   ? CODE_16BIT
-					   : CODE_32BIT
-					 : flag_code],
-		kind);
-    }
-  return ok;
+  return 1;
 }
 
 /* Parse OPERAND_STRING into the i386_insn structure I.  Returns zero



More information about the Binutils mailing list