.code16gcc and "lea <32bit>(%eax),%edx"

Alan Modra alan@linuxcare.com.au
Thu Jun 22 04:01:00 GMT 2000


On Thu, 22 Jun 2000, [iso-8859-1] Etienne Lorrain wrote:

>    3                    .code16gcc
>    4 0006 67668D78      leal 4194428(%eax),%edi
>    4      7C

I squinted at this code when I made a similar fix for immediates on
2000-04-03, at the time deciding that displacements wouldn't be a problem
because the size is only affected by the mode and prefixes, which we've
already seen.  Forgot that i386_index_check might magically add a prefix
in...

Ah well.  Following patch installed.

-- 
Linuxcare.  Support for the Revolution.

gas/ChangeLog
	* config/tc-i386.c (i386_displacement): Don't assume a constant
	displacement is necessarily 16 bits when in 16 bit code mode.
	(md_assemble): Instead size the displacement here after we know
	for sure that a .code16gcc operand hasn't automatically added
	operand size prefixes.

Index: gas/config/tc-i386.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-i386.c,v
retrieving revision 1.55
diff -u -p -r1.55 tc-i386.c
--- tc-i386.c	2000/06/21 02:18:17	1.55
+++ tc-i386.c	2000/06/22 10:44:38
@@ -1461,6 +1461,31 @@ md_assemble (line)
 	    }
       }
 
+    if (i.disp_operands)
+      {
+	/* Try to use the smallest displacement type too.  */
+	int op;
+
+	for (op = i.operands; --op >= 0; )
+	  if ((i.types[op] & Disp)
+	      && i.op[op].imms->X_op == O_constant)
+	    {
+	      offsetT disp = i.op[op].disps->X_add_number;
+
+	      if (i.types[op] & Disp16)
+		{
+		  /* We know this operand is at most 16 bits, so
+		     convert to a signed 16 bit number before trying
+		     to see whether it will fit in an even smaller
+		     size.  */
+		  
+		  disp = (((disp & 0xffff) ^ 0x8000) - 0x8000);
+		}
+	      if (fits_in_signed_byte (disp))
+		i.types[op] |= Disp8;
+	    }
+      }
+
     overlap0 = 0;
     overlap1 = 0;
     overlap2 = 0;
@@ -2920,28 +2945,15 @@ i386_displacement (disp_start, disp_end)
       exp->X_op_symbol = (symbolS *) 0;
     }
 
-  if (exp->X_op == O_constant)
-    {
-      if (i.types[this_operand] & Disp16)
-	{
-	  /* We know this operand is at most 16 bits, so convert to a
-	     signed 16 bit number before trying to see whether it will
-	     fit in an even smaller size.  */
-	  exp->X_add_number =
-	    (((exp->X_add_number & 0xffff) ^ 0x8000) - 0x8000);
-	}
-      if (fits_in_signed_byte (exp->X_add_number))
-	i.types[this_operand] |= Disp8;
-    }
 #if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT))
-  else if (
+  if (exp->X_op != O_constant
 #ifdef BFD_ASSEMBLER
-	   OUTPUT_FLAVOR == bfd_target_aout_flavour &&
+      && OUTPUT_FLAVOR == bfd_target_aout_flavour
 #endif
-	   exp_seg != text_section
-	   && exp_seg != data_section
-	   && exp_seg != bss_section
-	   && exp_seg != undefined_section)
+      && exp_seg != text_section
+      && exp_seg != data_section
+      && exp_seg != bss_section
+      && exp_seg != undefined_section)
     {
 #ifdef BFD_ASSEMBLER
       as_bad (_("unimplemented segment %s in operand"), exp_seg->name);



More information about the Binutils mailing list