OSDN Git Service

* config/i386/i386.md (prefix_data16, prefix_rep): Set to 0 for
[pf3gnuchains/gcc-fork.git] / gcc / config / i386 / i386.c
index 55ec1d9..26bb300 100644 (file)
@@ -19351,9 +19351,33 @@ memory_address_length (rtx addr)
        len = 1;
     }
 
-  /* Direct Addressing.  */
+  /* Direct Addressing.  In 64-bit mode mod 00 r/m 5
+     is not disp32, but disp32(%rip), so for disp32
+     SIB byte is needed, unless print_operand_address
+     optimizes it into disp32(%rip) or (%rip) is implied
+     by UNSPEC.  */
   else if (disp && !base && !index)
-    len = 4;
+    {
+      len = 4;
+      if (TARGET_64BIT)
+       {
+         rtx symbol = disp;
+
+         if (GET_CODE (disp) == CONST)
+           symbol = XEXP (disp, 0);
+         if (GET_CODE (symbol) == PLUS
+             && CONST_INT_P (XEXP (symbol, 1)))
+           symbol = XEXP (symbol, 0);
+
+         if (GET_CODE (symbol) != LABEL_REF
+             && (GET_CODE (symbol) != SYMBOL_REF
+                 || SYMBOL_REF_TLS_MODEL (symbol) != 0)
+             && (GET_CODE (symbol) != UNSPEC
+                 || (XINT (symbol, 1) != UNSPEC_GOTPCREL
+                     && XINT (symbol, 1) != UNSPEC_GOTNTPOFF)))
+           len += 1;
+       }
+    }
 
   else
     {
@@ -19368,7 +19392,7 @@ memory_address_length (rtx addr)
       /* ebp always wants a displacement.  Similarly r13.  */
       else if (REG_P (base)
               && (REGNO (base) == BP_REG || REGNO (base) == R13_REG))
-        len = 1;
+       len = 1;
 
       /* An index requires the two-byte modrm form....  */
       if (index
@@ -19380,6 +19404,16 @@ memory_address_length (rtx addr)
        len += 1;
     }
 
+  switch (parts.seg)
+    {
+    case SEG_FS:
+    case SEG_GS:
+      len += 1;
+      break;
+    default:
+      break;
+    }
+
   return len;
 }
 
@@ -19394,30 +19428,50 @@ ix86_attr_length_immediate_default (rtx insn, int shortform)
   for (i = recog_data.n_operands - 1; i >= 0; --i)
     if (CONSTANT_P (recog_data.operand[i]))
       {
+        enum attr_mode mode = get_attr_mode (insn);
+
        gcc_assert (!len);
-       if (shortform && satisfies_constraint_K (recog_data.operand[i]))
-         len = 1;
-       else
+       if (shortform && CONST_INT_P (recog_data.operand[i]))
          {
-           switch (get_attr_mode (insn))
+           HOST_WIDE_INT ival = INTVAL (recog_data.operand[i]);
+           switch (mode)
              {
-               case MODE_QI:
-                 len+=1;
-                 break;
-               case MODE_HI:
-                 len+=2;
-                 break;
-               case MODE_SI:
-                 len+=4;
-                 break;
-               /* Immediates for DImode instructions are encoded as 32bit sign extended values.  */
-               case MODE_DI:
-                 len+=4;
-                 break;
-               default:
-                 fatal_insn ("unknown insn mode", insn);
+             case MODE_QI:
+               len = 1;
+               continue;
+             case MODE_HI:
+               ival = trunc_int_for_mode (ival, HImode);
+               break;
+             case MODE_SI:
+               ival = trunc_int_for_mode (ival, SImode);
+               break;
+             default:
+               break;
+             }
+           if (IN_RANGE (ival, -128, 127))
+             {
+               len = 1;
+               continue;
              }
          }
+       switch (mode)
+         {
+         case MODE_QI:
+           len = 1;
+           break;
+         case MODE_HI:
+           len = 2;
+           break;
+         case MODE_SI:
+           len = 4;
+           break;
+         /* Immediates for DImode instructions are encoded as 32bit sign extended values.  */
+         case MODE_DI:
+           len = 4;
+           break;
+         default:
+           fatal_insn ("unknown insn mode", insn);
+       }
       }
   return len;
 }
@@ -19452,8 +19506,22 @@ ix86_attr_length_address_default (rtx insn)
   for (i = recog_data.n_operands - 1; i >= 0; --i)
     if (MEM_P (recog_data.operand[i]))
       {
+        constrain_operands_cached (reload_completed);
+        if (which_alternative != -1)
+         {
+           const char *constraints = recog_data.constraints[i];
+           int alt = which_alternative;
+
+           while (*constraints == '=' || *constraints == '+')
+             constraints++;
+           while (alt-- > 0)
+             while (*constraints++ != ',')
+               ;
+           /* Skip ignored operands.  */
+           if (*constraints == 'X')
+             continue;
+         }
        return memory_address_length (XEXP (recog_data.operand[i], 0));
-       break;
       }
   return 0;
 }
@@ -19482,7 +19550,8 @@ ix86_attr_length_vex_default (rtx insn, int has_0f_opcode,
     if (REG_P (recog_data.operand[i]))
       {
        /* REX.W bit uses 3 byte VEX prefix.  */
-       if (GET_MODE (recog_data.operand[i]) == DImode)
+       if (GET_MODE (recog_data.operand[i]) == DImode
+           && GENERAL_REG_P (recog_data.operand[i]))
          return 3 + 1;
       }
     else