This is the mail archive of the binutils@sourceware.cygnus.com 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]

Re: binutils-as: can addr32 prefix be automatically inferred?



On Mon, 2 Aug 1999, Klaus Espenlaub wrote:

> I just stumbled across some old code that already uses the .code16 feature
> of the i386 gas. It contains instructions like
> 
> .code16
> movl 8(%ebp),%edx
> leal (%esi,%edx),%eax
> 
> The old gas (2.9.1) automatically inferred the required addr32 prefixes for
> these instructions, while the 990628 snapshot just gives error messages:
> 
> /tmp/cca19394.s:257: Error: `8(%ebp)' is not a valid 16 bit base/index expression
> /tmp/cca20380.s:289: Error: `(%esi,%edx)' is not a valid 16 bit base/index expression
> 
> While this is a valid behaviour, it would be more convenient to put at
> least a limited heuristics into gas, making old code acceptable to the
> newer (and stricter) gas.  But if you decide against it, please state that
> somewhere public (like the gas docs) so that there is no further confusion
> about this matter.  I don't care, because someone else has to maintain the
> code I am just using :)

Hello Klaus,
   The following patch (untested!) ought to do what you want.  I
re-indented i386_intel_operand, so there are a few extra lines in the
patch.  Can you test it out please?

--- binutils-current/gas/config/tc-i386.c~	Tue Jul 20 23:41:31 1999
+++ binutils-current/gas/config/tc-i386.c	Tue Aug  3 08:38:14 1999
@@ -40,6 +40,10 @@
 #define REGISTER_WARNINGS 1
 #endif
 
+#ifndef INFER_ADDR_PREFIX
+#define INFER_ADDR_PREFIX 1
+#endif
+
 #ifndef SCALE1_WHEN_NO_INDEX
 /* Specifying a scale factor besides 1 when there is no index is
    futile.  eg. `mov (%ebx,2),%al' does exactly the same as
@@ -3241,71 +3245,71 @@ i386_intel_operand (operand_string, got_
     case SHORT:
 
     case NONE_FOUND:
-    /* Should be register or immediate */
-    if (is_digit_char (*op_string)
-        && strchr (op_string, '[') == 0)
-      {
-      if (!i386_immediate (op_string))
-        return 0;
-      }
-    else if (*op_string == REGISTER_PREFIX
-             || (allow_naked_reg
-	         && i386_is_reg (op_string)))
-      {
-
-        register const reg_entry * r;
-        char *end_op;
+      /* Should be register or immediate */
+      if (is_digit_char (*op_string)
+	  && strchr (op_string, '[') == 0)
+	{
+	  if (!i386_immediate (op_string))
+	    return 0;
+	}
+      else if (*op_string == REGISTER_PREFIX
+	       || (allow_naked_reg
+		   && i386_is_reg (op_string)))
+	{
 
-        r = parse_register (op_string, &end_op);
-        if (r == NULL)
-          return 0;
+	  register const reg_entry * r;
+	  char *end_op;
 
-        /* Check for a segment override by searching for ':' after a
-           segment register.  */
-        op_string = end_op;
-        if (is_space_char (*op_string))
-          ++op_string;
-        if (*op_string == ':' && (r->reg_type & (SReg2 | SReg3)))
-          {
-            switch (r->reg_num)
-              {
-              case 0:
-                i.seg[i.mem_operands] = &es;
-                break;
-              case 1:
-                i.seg[i.mem_operands] = &cs;
-                break;
-              case 2:
-                i.seg[i.mem_operands] = &ss;
-                break;
-              case 3:
-                i.seg[i.mem_operands] = &ds;
-                break;
-              case 4:
-                i.seg[i.mem_operands] = &fs;
-                break;
-              case 5:
-                i.seg[i.mem_operands] = &gs;
-                break;
-              }
+	  r = parse_register (op_string, &end_op);
+	  if (r == NULL)
+	    return 0;
+
+	  /* Check for a segment override by searching for ':' after a
+	     segment register.  */
+	  op_string = end_op;
+	  if (is_space_char (*op_string))
+	    ++op_string;
+	  if (*op_string == ':' && (r->reg_type & (SReg2 | SReg3)))
+	    {
+	      switch (r->reg_num)
+		{
+		case 0:
+		  i.seg[i.mem_operands] = &es;
+		  break;
+		case 1:
+		  i.seg[i.mem_operands] = &cs;
+		  break;
+		case 2:
+		  i.seg[i.mem_operands] = &ss;
+		  break;
+		case 3:
+		  i.seg[i.mem_operands] = &ds;
+		  break;
+		case 4:
+		  i.seg[i.mem_operands] = &fs;
+		  break;
+		case 5:
+		  i.seg[i.mem_operands] = &gs;
+		  break;
+		}
 
-          }
-        i.types[this_operand] |= r->reg_type & ~BaseIndex;
-        i.regs[this_operand] = r;
-        i.reg_operands++;
-      }
+	    }
+	  i.types[this_operand] |= r->reg_type & ~BaseIndex;
+	  i.regs[this_operand] = r;
+	  i.reg_operands++;
+	}
 
-    else 
-      {
+      else 
+	{
 
-        if (!i386_intel_memory_operand (op_string))
-          return 0;
+	  if (!i386_intel_memory_operand (op_string))
+	    return 0;
 
-        i.mem_operands++;
-      }
-    break;
+	  i.mem_operands++;
+	}
+      break;
 
-  }  /* end switch */
+    }  /* end switch */
   /* Special case for (%dx) while doing input/output op.  */
   if (i.base_reg
       && i.base_reg->reg_type == (Reg16 | InOutPortReg)
@@ -3313,42 +3317,68 @@ i386_intel_operand (operand_string, got_
       && i.log2_scale_factor == 0
       && i.seg[i.mem_operands] == 0
       && (i.types[this_operand] & Disp) == 0)
-     {
-       i.types[this_operand] = InOutPortReg;
-       return 1;
-     }
+    {
+      i.types[this_operand] = InOutPortReg;
+      return 1;
+    }
   /* Make sure the memory operand we've been dealt is valid.  */
   if (flag_16bit_code ^ (i.prefix[ADDR_PREFIX] != 0))
     {
+#if INFER_ADDR_PREFIX
+    try16:
+#endif
       if ((i.base_reg
 	   && ((i.base_reg->reg_type & (Reg16|BaseIndex))
-		!= (Reg16|BaseIndex)))
-	      || (i.index_reg
-		  && (((i.index_reg->reg_type & (Reg16|BaseIndex))
-		       != (Reg16|BaseIndex))
-		      || ! (i.base_reg
-			    && i.base_reg->reg_num < 6
-			    && i.index_reg->reg_num >= 6
-			    && i.log2_scale_factor == 0))))
-	 {
-	   as_bad (_("`%s' is not a valid %s bit base/index expression"),
-                   operand_string, "16");
-           return 0;
-	 }
+	       != (Reg16|BaseIndex)))
+	  || (i.index_reg
+	      && (((i.index_reg->reg_type & (Reg16|BaseIndex))
+		   != (Reg16|BaseIndex))
+		  || ! (i.base_reg
+			&& i.base_reg->reg_num < 6
+			&& i.index_reg->reg_num >= 6
+			&& i.log2_scale_factor == 0))))
+	{
+	  if (i.prefix[ADDR_PREFIX] != 0)
+	    {
+	      as_bad (_("`%s' is not a valid %s bit base/index expression"),
+		      operand_string, "16");
+	      return 0;
+	    }
+#if INFER_ADDR_PREFIX
+	  else
+	    {
+	      i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE;
+	      goto try32;
+	    }
+#endif
+	}
     }
-      else
+  else
+    {
+#if INFER_ADDR_PREFIX
+    try32:
+#endif
+      if ((i.base_reg
+	   && (i.base_reg->reg_type & Reg32) == 0)
+	  || (i.index_reg
+	      && ((i.index_reg->reg_type & (Reg32|BaseIndex))
+		  != (Reg32|BaseIndex))))
 	{
-	  if ((i.base_reg
-	       && (i.base_reg->reg_type & Reg32) == 0)
-	      || (i.index_reg
-		  && ((i.index_reg->reg_type & (Reg32|BaseIndex))
-		      != (Reg32|BaseIndex))))
+	  if (i.prefix[ADDR_PREFIX] != 0)
 	    {
 	      as_bad (_("`%s' is not a valid %s bit base/index expression"),
 		      operand_string, "32");
 	      return 0;
 	    }
+#if INFER_ADDR_PREFIX
+	  else
+	    {
+	      i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE;
+	      goto try16;
+	    }
+#endif
 	}
+    }
   return 1;
 }
 


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