gas/
[deliverable/binutils-gdb.git] / gas / config / tc-i386.c
index 18df9cfe3686bce60f606d9b3d723f5d8826f0e6..76c43f90d53694531e9ae481cc4e49b330d2efce 100644 (file)
@@ -1409,7 +1409,11 @@ md_assemble (line)
   if (i.imm_operands)
     optimize_imm ();
 
-  if (i.disp_operands)
+  /* Don't optimize displacement for movabs since it only takes 64bit
+     displacement.  */
+  if (i.disp_operands
+      && (flag_code != CODE_64BIT
+         || strcmp (mnemonic, "movabs") != 0))
     optimize_disp ();
 
   /* Next, we find a template that matches the given insn,
@@ -2065,43 +2069,51 @@ optimize_disp ()
   int op;
 
   for (op = i.operands; --op >= 0;)
-    if ((i.types[op] & Disp) && i.op[op].disps->X_op == O_constant)
+    if (i.types[op] & Disp)
       {
-       offsetT disp = i.op[op].disps->X_add_number;
-
-       if (i.types[op] & Disp16)
+       if (i.op[op].disps->X_op == O_constant)
          {
-           /* 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.  */
+           offsetT disp = i.op[op].disps->X_add_number;
 
-           disp = (((disp & 0xffff) ^ 0x8000) - 0x8000);
-         }
-       else if (i.types[op] & Disp32)
-         {
-           /* We know this operand is at most 32 bits, so convert to a
-              signed 32 bit number before trying to see whether it will
-              fit in an even smaller size.  */
-           disp &= (((offsetT) 2 << 31) - 1);
-           disp = (disp ^ ((offsetT) 1 << 31)) - ((addressT) 1 << 31);
-         }
-       if (!disp && (i.types[op] & BaseIndex))
-         {
-           i.types[op] &= ~Disp;
-           i.op[op].disps = 0;
-           i.disp_operands--;
-         }
-       else if (flag_code == CODE_64BIT)
-         {
-           if (fits_in_signed_long (disp))
-             i.types[op] |= Disp32S;
-           if (fits_in_unsigned_long (disp))
-             i.types[op] |= Disp32;
+           if ((i.types[op] & Disp16)
+               && (disp & ~(offsetT) 0xffff) == 0)
+             {
+               /* If this operand is at most 16 bits, convert
+                  to a signed 16 bit number and don't use 64bit
+                  displacement.  */
+               disp = (((disp & 0xffff) ^ 0x8000) - 0x8000);
+               i.types[op] &= ~Disp64;
+             }
+           if ((i.types[op] & Disp32)
+               && (disp & ~(((offsetT) 2 << 31) - 1)) == 0)
+             {
+               /* If this operand is at most 32 bits, convert
+                  to a signed 32 bit number and don't use 64bit
+                  displacement.  */
+               disp &= (((offsetT) 2 << 31) - 1);
+               disp = (disp ^ ((offsetT) 1 << 31)) - ((addressT) 1 << 31);
+               i.types[op] &= ~Disp64;
+             }
+           if (!disp && (i.types[op] & BaseIndex))
+             {
+               i.types[op] &= ~Disp;
+               i.op[op].disps = 0;
+               i.disp_operands--;
+             }
+           else if (flag_code == CODE_64BIT)
+             {
+               if (fits_in_signed_long (disp))
+                 i.types[op] |= Disp32S;
+               if (fits_in_unsigned_long (disp))
+                 i.types[op] |= Disp32;
+             }
+           if ((i.types[op] & (Disp32 | Disp32S | Disp16))
+               && fits_in_signed_byte (disp))
+             i.types[op] |= Disp8;
          }
-       if ((i.types[op] & (Disp32 | Disp32S | Disp16))
-           && fits_in_signed_byte (disp))
-         i.types[op] |= Disp8;
+       else
+         /* We only support 64bit displacement on constants.  */
+         i.types[op] &= ~Disp64;
       }
 }
 
This page took 0.026119 seconds and 4 git commands to generate.