OSDN Git Service

* config/i386/i386.c (override_options): Don't accept
[pf3gnuchains/gcc-fork.git] / gcc / config / i386 / i386.c
index 27593d7..2179b5a 100644 (file)
@@ -53,6 +53,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm-constrs.h"
 #include "params.h"
 #include "cselib.h"
+#include "debug.h"
+#include "dwarf2out.h"
 
 static rtx legitimize_dllimport_symbol (rtx, bool);
 
@@ -1910,6 +1912,10 @@ static unsigned int ix86_minimum_incoming_stack_boundary (bool);
 static enum calling_abi ix86_function_abi (const_tree);
 
 \f
+#ifndef SUBTARGET32_DEFAULT_CPU
+#define SUBTARGET32_DEFAULT_CPU "i386"
+#endif
+
 /* The svr4 ABI for the i386 says that records and unions are returned
    in memory.  */
 #ifndef DEFAULT_PCC_STRUCT_RETURN
@@ -2400,7 +2406,7 @@ ix86_handle_option (size_t code, const char *arg ATTRIBUTE_UNUSED, int value)
     }
 }
 \f
-/* Return a string the documents the current -m options.  The caller is
+/* Return a string that documents the current -m options.  The caller is
    responsible for freeing the string.  */
 
 static char *
@@ -2419,6 +2425,7 @@ ix86_target_string (int isa, int flags, const char *arch, const char *tune,
   {
     { "-m64",          OPTION_MASK_ISA_64BIT },
     { "-mfma4",                OPTION_MASK_ISA_FMA4 },
+    { "-mfma",         OPTION_MASK_ISA_FMA },
     { "-mxop",         OPTION_MASK_ISA_XOP },
     { "-mlwp",         OPTION_MASK_ISA_LWP },
     { "-msse4a",       OPTION_MASK_ISA_SSE4A },
@@ -2876,7 +2883,7 @@ override_options (bool main_args_p)
     }
 
   if (!ix86_arch_string)
-    ix86_arch_string = TARGET_64BIT ? "x86-64" : "i386";
+    ix86_arch_string = TARGET_64BIT ? "x86-64" : SUBTARGET32_DEFAULT_CPU;
   else
     ix86_arch_specified = 1;
 
@@ -3190,8 +3197,6 @@ override_options (bool main_args_p)
        ix86_tls_dialect = TLS_DIALECT_GNU;
       else if (strcmp (ix86_tls_dialect_string, "gnu2") == 0)
        ix86_tls_dialect = TLS_DIALECT_GNU2;
-      else if (strcmp (ix86_tls_dialect_string, "sun") == 0)
-       ix86_tls_dialect = TLS_DIALECT_SUN;
       else
        error ("bad value (%s) for %stls-dialect=%s %s",
               ix86_tls_dialect_string, prefix, suffix, sw);
@@ -7584,6 +7589,9 @@ ix86_file_end (void)
   for (regno = 0; regno < 8; ++regno)
     {
       char name[32];
+#ifdef DWARF2_UNWIND_INFO
+      bool do_cfi;
+#endif
 
       if (! ((pic_labels_used >> regno) & 1))
        continue;
@@ -7629,10 +7637,19 @@ ix86_file_end (void)
          ASM_OUTPUT_LABEL (asm_out_file, name);
        }
 
+#ifdef DWARF2_UNWIND_INFO
+      do_cfi = dwarf2out_do_cfi_asm ();
+      if (do_cfi)
+       fprintf (asm_out_file, "\t.cfi_startproc\n");
+#endif
       xops[0] = gen_rtx_REG (Pmode, regno);
       xops[1] = gen_rtx_MEM (Pmode, stack_pointer_rtx);
       output_asm_insn ("mov%z0\t{%1, %0|%0, %1}", xops);
       output_asm_insn ("ret", xops);
+#ifdef DWARF2_UNWIND_INFO
+      if (do_cfi)
+       fprintf (asm_out_file, "\t.cfi_endproc\n");
+#endif
     }
 
   if (NEED_INDICATE_EXEC_STACK)
@@ -7673,7 +7690,24 @@ output_set_got (rtx dest, rtx label ATTRIBUTE_UNUSED)
       if (!flag_pic)
        output_asm_insn ("mov%z0\t{%2, %0|%0, %2}", xops);
       else
-       output_asm_insn ("call\t%a2", xops);
+       {
+         output_asm_insn ("call\t%a2", xops);
+#ifdef DWARF2_UNWIND_INFO
+         /* The call to next label acts as a push.  */
+         if (dwarf2out_do_frame ())
+           {
+             rtx insn;
+             start_sequence ();
+             insn = emit_insn (gen_rtx_SET (VOIDmode, stack_pointer_rtx,
+                                            gen_rtx_PLUS (Pmode,
+                                                          stack_pointer_rtx,
+                                                          GEN_INT (-4))));
+             RTX_FRAME_RELATED_P (insn) = 1;
+             dwarf2out_frame_debug (insn, true);
+             end_sequence ();
+           }
+#endif
+       }
 
 #if TARGET_MACHO
       /* Output the Mach-O "canonical" label name ("Lxx$pb") here too.  This
@@ -7686,7 +7720,27 @@ output_set_got (rtx dest, rtx label ATTRIBUTE_UNUSED)
                                 CODE_LABEL_NUMBER (XEXP (xops[2], 0)));
 
       if (flag_pic)
-       output_asm_insn ("pop%z0\t%0", xops);
+       {
+         output_asm_insn ("pop%z0\t%0", xops);
+#ifdef DWARF2_UNWIND_INFO
+         /* The pop is a pop and clobbers dest, but doesn't restore it
+            for unwind info purposes.  */
+         if (dwarf2out_do_frame ())
+           {
+             rtx insn;
+             start_sequence ();
+             insn = emit_insn (gen_rtx_SET (VOIDmode, dest, const0_rtx));
+             dwarf2out_frame_debug (insn, true);
+             insn = emit_insn (gen_rtx_SET (VOIDmode, stack_pointer_rtx,
+                                            gen_rtx_PLUS (Pmode,
+                                                          stack_pointer_rtx,
+                                                          GEN_INT (4))));
+             RTX_FRAME_RELATED_P (insn) = 1;
+             dwarf2out_frame_debug (insn, true);
+             end_sequence ();
+           }
+#endif
+       }
     }
   else
     {
@@ -7694,6 +7748,18 @@ output_set_got (rtx dest, rtx label ATTRIBUTE_UNUSED)
       get_pc_thunk_name (name, REGNO (dest));
       pic_labels_used |= 1 << REGNO (dest);
 
+#ifdef DWARF2_UNWIND_INFO
+      /* Ensure all queued register saves are flushed before the
+        call.  */
+      if (dwarf2out_do_frame ())
+       {
+         rtx insn;
+         start_sequence ();
+         insn = emit_barrier ();
+         end_sequence ();
+         dwarf2out_frame_debug (insn, false);
+       }
+#endif
       xops[2] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name));
       xops[2] = gen_rtx_MEM (QImode, xops[2]);
       output_asm_insn ("call\t%X2", xops);
@@ -8330,7 +8396,11 @@ ix86_get_drap_rtx (void)
       end_sequence ();
       
       insn = emit_insn_before (seq, NEXT_INSN (entry_of_function ()));
-      RTX_FRAME_RELATED_P (insn) = 1;
+      if (!optimize)
+       {
+         add_reg_note (insn, REG_CFA_SET_VDRAP, drap_vreg);
+         RTX_FRAME_RELATED_P (insn) = 1;
+       }
       return drap_vreg;
     }
   else
@@ -10883,6 +10953,9 @@ static rtx
 ix86_delegitimize_address (rtx x)
 {
   rtx orig_x = delegitimize_mem_from_attrs (x);
+  /* addend is NULL or some rtx if x is something+GOTOFF where
+     something doesn't include the PIC register.  */
+  rtx addend = NULL_RTX;
   /* reg_addend is NULL or a multiple of some register.  */
   rtx reg_addend = NULL_RTX;
   /* const_addend is NULL or a const_int.  */
@@ -10921,14 +10994,13 @@ ix86_delegitimize_address (rtx x)
       else if (ix86_pic_register_p (XEXP (reg_addend, 1)))
        reg_addend = XEXP (reg_addend, 0);
       else
-       return orig_x;
-      if (!REG_P (reg_addend)
-         && GET_CODE (reg_addend) != MULT
-         && GET_CODE (reg_addend) != ASHIFT)
-       return orig_x;
+       {
+         reg_addend = NULL_RTX;
+         addend = XEXP (x, 0);
+       }
     }
   else
-    return orig_x;
+    addend = XEXP (x, 0);
 
   x = XEXP (XEXP (x, 1), 0);
   if (GET_CODE (x) == PLUS
@@ -10939,7 +11011,7 @@ ix86_delegitimize_address (rtx x)
     }
 
   if (GET_CODE (x) == UNSPEC
-      && ((XINT (x, 1) == UNSPEC_GOT && MEM_P (orig_x))
+      && ((XINT (x, 1) == UNSPEC_GOT && MEM_P (orig_x) && !addend)
          || (XINT (x, 1) == UNSPEC_GOTOFF && !MEM_P (orig_x))))
     result = XVECEXP (x, 0, 0);
 
@@ -10954,6 +11026,22 @@ ix86_delegitimize_address (rtx x)
     result = gen_rtx_CONST (Pmode, gen_rtx_PLUS (Pmode, result, const_addend));
   if (reg_addend)
     result = gen_rtx_PLUS (Pmode, reg_addend, result);
+  if (addend)
+    {
+      /* If the rest of original X doesn't involve the PIC register, add
+        addend and subtract pic_offset_table_rtx.  This can happen e.g.
+        for code like:
+        leal (%ebx, %ecx, 4), %ecx
+        ...
+        movl foo@GOTOFF(%ecx), %edx
+        in which case we return (%ecx - %ebx) + foo.  */
+      if (pic_offset_table_rtx)
+        result = gen_rtx_PLUS (Pmode, gen_rtx_MINUS (Pmode, copy_rtx (addend),
+                                                    pic_offset_table_rtx),
+                              result);
+      else
+       return orig_x;
+    }
   return result;
 }
 
@@ -24655,7 +24743,7 @@ avx_vpermilp_parallel (rtx par, enum machine_mode mode)
       if (!CONST_INT_P (er))
        return 0;
       ei = INTVAL (er);
-      if (ei >= 2 * nelt)
+      if (ei >= nelt)
        return 0;
       ipar[i] = ei;
     }
@@ -26280,7 +26368,7 @@ x86_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
   if (TARGET_64BIT)
     {
 #ifndef NO_PROFILE_COUNTERS
-      fprintf (file, "\tleaq\t" LPREFIX "P%d@(%%rip),%%r11\n", labelno);
+      fprintf (file, "\tleaq\t" LPREFIX "P%d(%%rip),%%r11\n", labelno);
 #endif
 
       if (DEFAULT_ABI == SYSV_ABI && flag_pic)
@@ -29126,8 +29214,8 @@ expand_vec_perm_blend (struct expand_vec_perm_d *d)
     do_subreg:
       vmode = V8HImode;
       target = gen_lowpart (vmode, target);
-      op0 = gen_lowpart (vmode, target);
-      op1 = gen_lowpart (vmode, target);
+      op0 = gen_lowpart (vmode, op0);
+      op1 = gen_lowpart (vmode, op1);
       break;
 
     default:
@@ -29135,7 +29223,7 @@ expand_vec_perm_blend (struct expand_vec_perm_d *d)
     }
 
   /* This matches five different patterns with the different modes.  */
-  x = gen_rtx_VEC_MERGE (vmode, op0, op1, GEN_INT (mask));
+  x = gen_rtx_VEC_MERGE (vmode, op1, op0, GEN_INT (mask));
   x = gen_rtx_SET (VOIDmode, target, x);
   emit_insn (x);
 
@@ -29247,7 +29335,12 @@ expand_vec_perm_1 (struct expand_vec_perm_d *d)
      input where SEL+CONCAT may not.  */
   if (d->op0 == d->op1)
     {
-      if (expand_vselect (d->target, d->op0, d->perm, nelt))
+      int mask = nelt - 1;
+
+      for (i = 0; i < nelt; i++)
+       perm2[i] = d->perm[i] & mask;
+
+      if (expand_vselect (d->target, d->op0, perm2, nelt))
        return true;
 
       /* There are plenty of patterns in sse.md that are written for
@@ -29258,8 +29351,8 @@ expand_vec_perm_1 (struct expand_vec_perm_d *d)
         every other permutation operand.  */
       for (i = 0; i < nelt; i += 2)
        {
-         perm2[i] = d->perm[i];
-         perm2[i+1] = d->perm[i+1] + nelt;
+         perm2[i] = d->perm[i] & mask;
+         perm2[i + 1] = (d->perm[i + 1] & mask) + nelt;
        }
       if (expand_vselect_vconcat (d->target, d->op0, d->op0, perm2, nelt))
        return true;
@@ -29267,11 +29360,12 @@ expand_vec_perm_1 (struct expand_vec_perm_d *d)
       /* Recognize shufps, which means adding {0, 0, nelt, nelt}.  */
       if (nelt >= 4)
        {
-         memcpy (perm2, d->perm, nelt);
-         for (i = 2; i < nelt; i += 4)
+         for (i = 0; i < nelt; i += 4)
            {
-             perm2[i+0] += nelt;
-             perm2[i+1] += nelt;
+             perm2[i + 0] = d->perm[i + 0] & mask;
+             perm2[i + 1] = d->perm[i + 1] & mask;
+             perm2[i + 2] = (d->perm[i + 2] & mask) + nelt;
+             perm2[i + 3] = (d->perm[i + 3] & mask) + nelt;
            }
 
          if (expand_vselect_vconcat (d->target, d->op0, d->op0, perm2, nelt))