Fix a problem with 32-bit displacements in .code16gcc mode.
authorAlan Modra <amodra@gmail.com>
Thu, 22 Jun 2000 10:49:13 +0000 (10:49 +0000)
committerAlan Modra <amodra@gmail.com>
Thu, 22 Jun 2000 10:49:13 +0000 (10:49 +0000)
gas/ChangeLog
gas/config/tc-i386.c

index 35854d9c82dd1cfc845e49d48caa7c34e0719f5a..f5c06d7e5a0f379c3e3b3d08144a75c23bc2ae9a 100644 (file)
@@ -1,3 +1,11 @@
+2000-06-22  Alan Modra  <alan@linuxcare.com.au>
+
+       * 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.
+
 2000-06-21  H.J. Lu  <hjl@gnu.org>
 
        * Makefile.am: Rebuild dependency.
index 2c32e744d5bfdb134cb4734c658c17fde6431099..6ab93c5ac98e0fd71da39406df406f3e69eea11e 100644 (file)
@@ -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);