Fix various problems; Add -m{,no-}fused-madd, -m{,no-}no-update switches; Allow add...
authorMichael Meissner <meissner@gcc.gnu.org>
Sun, 29 Jun 1997 16:13:13 +0000 (16:13 +0000)
committerMichael Meissner <meissner@gcc.gnu.org>
Sun, 29 Jun 1997 16:13:13 +0000 (16:13 +0000)
From-SVN: r14361

gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/config/rs6000/rs6000.md
gcc/config/rs6000/sysv4.h

index 8146ce978064673caebb57700d55eeca9b96a4df..60262a9aba4144acc3a6ea18b48ab18efb1d3474 100644 (file)
@@ -104,6 +104,14 @@ enum rs6000_abi rs6000_current_abi;
 int rs6000_fpmem_offset;
 int rs6000_fpmem_size;
 
+/* Debug flags */
+char *rs6000_debug_name;
+int rs6000_debug_stack;                /* debug stack applications */
+int rs6000_debug_arg;          /* debug argument handling */
+
+/* Flag to say the TOC is initialized */
+int toc_initialized;
+
 \f
 /* Default register names.  */
 char rs6000_reg_names[][8] =
@@ -297,6 +305,19 @@ rs6000_override_options (default_cpu)
        }
     }
 
+  /* Set debug flags */
+  if (rs6000_debug_name)
+    {
+      if (!strcmp (rs6000_debug_name, "all"))
+       rs6000_debug_stack = rs6000_debug_arg = 1;
+      else if (!strcmp (rs6000_debug_name, "stack"))
+       rs6000_debug_stack = 1;
+      else if (!strcmp (rs6000_debug_name, "arg"))
+       rs6000_debug_arg = 1;
+      else
+       error ("Unknown -mdebug-%s switch", rs6000_debug_name);
+    }
+
 #ifdef TARGET_REGNAMES
   /* If the user desires alternate register names, copy in the alternate names
      now.  */
@@ -416,7 +437,8 @@ any_operand (op, mode)
 }
 
 /* Returns 1 if op is the count register */
-int count_register_operand(op, mode)
+int
+count_register_operand(op, mode)
      register rtx op;
      enum machine_mode mode;
 {
@@ -434,7 +456,8 @@ int count_register_operand(op, mode)
 
 /* Returns 1 if op is memory location for float/int conversions that masquerades
    as a register.  */
-int fpmem_operand(op, mode)
+int
+fpmem_operand(op, mode)
      register rtx op;
      enum machine_mode mode;
 {
@@ -576,6 +599,17 @@ got_operand (op, mode)
          || GET_CODE (op) == LABEL_REF);
 }
 
+/* Return 1 if the operand is a simple references that can be loaded via
+   the GOT (labels involving addition aren't allowed).  */
+
+int
+got_no_const_operand (op, mode)
+     register rtx op;
+     enum machine_mode mode;
+{
+  return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF);
+}
+
 /* Return the number of instructions it takes to form a constant in an
    integer register.  */
 
@@ -869,8 +903,7 @@ and_operand (op, mode)
     register rtx op;
     enum machine_mode mode;
 {
-  return (reg_or_short_operand (op, mode)
-         || logical_operand (op, mode)
+  return (logical_operand (op, mode)
          || mask_operand (op, mode));
 }
 
@@ -1009,7 +1042,7 @@ small_data_operand (op, mode)
      rtx op;
      enum machine_mode mode;
 {
-#ifdef TARGET_SDATA
+#if TARGET_ELF
   rtx sym_ref, const_part;
 
   if (rs6000_sdata == SDATA_NONE || rs6000_sdata == SDATA_DATA)
@@ -2168,6 +2201,7 @@ rs6000_finalize_pic ()
       rtx insn = get_insns ();
       rtx reg = NULL_RTX;
       rtx first_insn;
+      rtx last_insn = NULL_RTX;
 
       if (GET_CODE (insn) == NOTE)
        insn = next_nonnote_insn (insn);
@@ -2186,12 +2220,17 @@ rs6000_finalize_pic ()
                                                         GOT_TOC_REGNUM,
                                                         &reg);
            }
+
+         if (GET_CODE (insn) != NOTE)
+           last_insn = insn;
        }
 
       if (reg)
        {
          rtx init = gen_init_v4_pic (reg);
          emit_insn_before (init, first_insn);
+         if (!optimize && last_insn)
+           emit_insn_after (gen_rtx (USE, VOIDmode, reg), last_insn);
        }
     }
 }
@@ -2274,7 +2313,7 @@ rs6000_init_expanders ()
 \f
 /* Print an operand.  Recognize special options, documented below.  */
 
-#ifdef TARGET_SDATA
+#if TARGET_ELF
 #define SMALL_DATA_RELOC ((rs6000_sdata == SDATA_EABI) ? "sda21" : "sdarel")
 #else
 #define SMALL_DATA_RELOC "sda21"
@@ -2875,8 +2914,10 @@ rs6000_makes_calls ()
 {
   rtx insn;
 
-  /* If we are profiling, we will be making a call to __mcount.  */
-  if (profile_flag)
+  /* If we are profiling, we will be making a call to __mcount.
+     Under the System V ABI's, we store the LR directly, so
+     we don't need to do it here.  */
+  if (DEFAULT_ABI == ABI_AIX && profile_flag)
     return 1;
 
   for (insn = get_insns (); insn; insn = next_insn (insn))
@@ -3066,7 +3107,8 @@ rs6000_stack_info ()
 
 
   /* Determine if we need to save the link register */
-  if (regs_ever_live[65] || profile_flag
+  if (regs_ever_live[65]
+      || (DEFAULT_ABI == ABI_AIX && profile_flag)
 #ifdef TARGET_RELOCATABLE
       || (TARGET_RELOCATABLE && (get_pool_size () != 0))
 #endif
@@ -3336,8 +3378,9 @@ debug_stack_info (info)
    a constant pool.  */
 
 void
-rs6000_output_load_toc_table (file)
+rs6000_output_load_toc_table (file, reg)
      FILE *file;
+     int reg;
 {
   char buf[256];
 
@@ -3349,8 +3392,45 @@ rs6000_output_load_toc_table (file)
       assemble_name (file, buf);
       fprintf (file, "\n");
 
+      /* possibly create the toc section */
+      if (!toc_initialized)
+       {
+         toc_section ();
+         function_section (current_function_decl);
+       }
+
+      /* If not first call in this function, we need to put the
+        different between .LCTOC1 and the address we get to right
+        after the bl.  It will mess up disassembling the instructions
+        but that can't be helped.  We will later need to bias the
+        address before loading.  */
+      if (rs6000_pic_func_labelno != rs6000_pic_labelno)
+       {
+         char *init_ptr = (TARGET_64BIT) ? ".quad" : ".long";
+         char *buf_ptr;
+
+         ASM_OUTPUT_INTERNAL_LABEL (file, "LCL", rs6000_pic_labelno);
+
+         ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 1);
+         STRIP_NAME_ENCODING (buf_ptr, buf);
+         fprintf (file, "\t%s %s-", init_ptr, buf_ptr);
+
+         ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);
+         fprintf (file, "%s\n", buf_ptr);
+       }
+
       ASM_OUTPUT_INTERNAL_LABEL (file, "LCF", rs6000_pic_labelno);
-      fprintf (file, "\tmflr %s\n", reg_names[30]);
+      fprintf (file, "\tmflr %s\n", reg_names[reg]);
+
+      if (rs6000_pic_func_labelno != rs6000_pic_labelno)
+       {
+         if (TARGET_POWERPC64)
+           fprintf (file, "\taddi %s,%s,8\n", reg_names[reg], reg_names[reg]);
+         else if (TARGET_NEW_MNEMONICS)
+           fprintf (file, "\taddi %s,%s,4\n", reg_names[reg], reg_names[reg]);
+         else
+           fprintf (file, "\tcal %s,4(%s)\n", reg_names[reg], reg_names[reg]);
+       }
 
       if (TARGET_POWERPC64)
        fprintf (file, "\tld");
@@ -3360,33 +3440,33 @@ rs6000_output_load_toc_table (file)
        fprintf (file, "\tl");
 
       fprintf (file, " %s,(", reg_names[0]);
-      ASM_GENERATE_INTERNAL_LABEL (buf, "LCL", rs6000_pic_func_labelno);
+      ASM_GENERATE_INTERNAL_LABEL (buf, "LCL", rs6000_pic_labelno);
       assemble_name (file, buf);
       fprintf (file, "-");
       ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);
       assemble_name (file, buf);
-      fprintf (file, ")(%s)\n", reg_names[30]);
+      fprintf (file, ")(%s)\n", reg_names[reg]);
       asm_fprintf (file, "\t{cax|add} %s,%s,%s\n",
-                  reg_names[30], reg_names[0], reg_names[30]);
+                  reg_names[reg], reg_names[0], reg_names[reg]);
       rs6000_pic_labelno++;
     }
   else if (!TARGET_64BIT)
     {
       ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 1);
-      asm_fprintf (file, "\t{cau|addis} %s,%s,", reg_names[30], reg_names[0]);
+      asm_fprintf (file, "\t{cau|addis} %s,%s,", reg_names[reg], reg_names[0]);
       assemble_name (file, buf);
       asm_fprintf (file, "@ha\n");
       if (TARGET_NEW_MNEMONICS)
        {
-         asm_fprintf (file, "\taddi %s,%s,", reg_names[30], reg_names[30]);
+         asm_fprintf (file, "\taddi %s,%s,", reg_names[reg], reg_names[reg]);
          assemble_name (file, buf);
          asm_fprintf (file, "@l\n");
        }
       else
        {
-         asm_fprintf (file, "\tcal %s,", reg_names[30]);
+         asm_fprintf (file, "\tcal %s,", reg_names[reg]);
          assemble_name (file, buf);
-         asm_fprintf (file, "@l(%s)\n", reg_names[30]);
+         asm_fprintf (file, "@l(%s)\n", reg_names[reg]);
        }
     }
   else
@@ -3394,12 +3474,68 @@ rs6000_output_load_toc_table (file)
 
 #else  /* !USING_SVR4_H */
   ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 0);
-  asm_fprintf (file, "\t{l|lwz} %s,", reg_names[30]);
+  asm_fprintf (file, "\t{l|lwz} %s,", reg_names[reg]);
   assemble_name (file, buf);
   asm_fprintf (file, "(%s)\n", reg_names[2]);
 #endif /* USING_SVR4_H */
 }
 
+\f
+/* Emit the correct code for allocating stack space.  If COPY_R12, make sure a copy
+   of the old frame is left in r12.  */
+
+void
+rs6000_allocate_stack_space (file, size, copy_r12)
+     FILE *file;
+     int size;
+     int copy_r12;
+{
+  int neg_size = -size;
+  if (TARGET_UPDATE)
+    {
+      if (size < 32767)
+       asm_fprintf (file,
+                    (TARGET_32BIT) ? "\t{stu|stwu} %s,%d(%s)\n" : "\tstdu %s,%d(%s)\n",
+                    reg_names[1], neg_size, reg_names[1]);
+      else
+       {
+         if (copy_r12)
+           fprintf (file, "\tmr %s,%s\n", reg_names[12], reg_names[1]);
+
+         asm_fprintf (file, "\t{liu|lis} %s,%d\n\t{oril|ori} %s,%s,%d\n",
+                      reg_names[0], (neg_size >> 16) & 0xffff,
+                      reg_names[0], reg_names[0], neg_size & 0xffff);
+         asm_fprintf (file,
+                      (TARGET_32BIT) ? "\t{stux|stwux} %s,%s,%s\n" : "\tstdux %s,%s,%s\n",
+                      reg_names[1], reg_names[1], reg_names[0]);
+       }
+    }
+  else
+    {
+      fprintf (file, "\tmr %s,%s\n", reg_names[12], reg_names[1]);
+      if (size < 32767)
+       {
+         if (TARGET_NEW_MNEMONICS)
+           fprintf (file, "\taddi %s,%s,%d\n", reg_names[1], reg_names[1], neg_size);
+         else
+           fprintf (file, "\tcal %s,%d(%s)\n", reg_names[1], neg_size, reg_names[1]);
+       }
+      else
+       {
+         asm_fprintf (file, "\t{liu|lis} %s,%d\n\t{oril|ori} %s,%s,%d\n",
+                      reg_names[0], (neg_size >> 16) & 0xffff,
+                      reg_names[0], reg_names[0], neg_size & 0xffff);
+         asm_fprintf (file, "\t{cax|add} %s,%s,%s\n", reg_names[1],
+                      reg_names[0], reg_names[1]);
+       }
+
+      asm_fprintf (file,
+                  (TARGET_32BIT) ? "\t{st|stw} %s,0(%s)\n" : "\tstd %s,0(%s)\n",
+                  reg_names[12], reg_names[1]);
+    }
+}
+
+\f
 /* Write function prologue.  */
 void
 output_prolog (file, size)
@@ -3458,24 +3594,10 @@ output_prolog (file, size)
   if (info->push_p && (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS))
     {
       if (info->total_size < 32767)
-       {
-         asm_fprintf (file,
-                      (TARGET_32BIT) ? "\t{stu|stwu} %s,%d(%s)\n" : "\tstdu %s,%d(%s)\n",
-                      reg_names[1], - info->total_size, reg_names[1]);
-         sp_offset = info->total_size;
-       }
+       sp_offset = info->total_size;
       else
-       {
-         int neg_size = - info->total_size;
-         sp_reg = 12;
-         asm_fprintf (file, "\tmr %s,%s\n", reg_names[12], reg_names[1]);
-         asm_fprintf (file, "\t{liu|lis} %s,%d\n\t{oril|ori} %s,%s,%d\n",
-                      reg_names[0], (neg_size >> 16) & 0xffff,
-                      reg_names[0], reg_names[0], neg_size & 0xffff);
-         asm_fprintf (file,
-                      (TARGET_32BIT) ? "\t{stux|stwux} %s,%s,%s\n" : "\tstdux %s,%s,%s\n",
-                      reg_names[1], reg_names[1], reg_names[0]);
-       }
+       sp_reg = 12;
+      rs6000_allocate_stack_space (file, info->total_size, sp_reg == 12);
     }
 
   /* If we use the link register, get it into r0.  */
@@ -3589,24 +3711,9 @@ output_prolog (file, size)
        }
     }
 
-  /* Update stack and set back pointer and we have already done so for V.4.  */
+  /* Update stack and set back pointer unless this is V.4, which was done previously */
   if (info->push_p && DEFAULT_ABI != ABI_V4 && DEFAULT_ABI != ABI_SOLARIS)
-    {
-      if (info->total_size < 32767)
-       asm_fprintf (file,
-                    (TARGET_32BIT) ? "\t{stu|stwu} %s,%d(%s)\n" : "\tstdu %s,%d(%s)\n",
-                    reg_names[1], - info->total_size, reg_names[1]);
-      else
-       {
-         int neg_size = - info->total_size;
-         asm_fprintf (file, "\t{liu|lis} %s,%d\n\t{oril|ori} %s,%s,%d\n",
-                      reg_names[0], (neg_size >> 16) & 0xffff,
-                      reg_names[0], reg_names[0], neg_size & 0xffff);
-         asm_fprintf (file,
-                      (TARGET_32BIT) ? "\t{stux|stwux} %s,%s,%s\n" : "\tstdux %s,%s,%s\n",
-                      reg_names[1], reg_names[1], reg_names[0]);
-       }
-    }
+    rs6000_allocate_stack_space (file, info->total_size, FALSE);
 
   /* Set frame pointer, if needed.  */
   if (frame_pointer_needed)
@@ -3671,9 +3778,10 @@ output_prolog (file, size)
   if (TARGET_TOC && TARGET_MINIMAL_TOC && get_pool_size () != 0)
     {
 #ifdef USING_SVR4_H
-      rs6000_pic_func_labelno = rs6000_pic_labelno;
+      if (!profile_flag)
+       rs6000_pic_func_labelno = rs6000_pic_labelno;
 #endif
-      rs6000_output_load_toc_table (file);
+      rs6000_output_load_toc_table (file, 30);
     }
 
   if (DEFAULT_ABI == ABI_NT)
@@ -4287,55 +4395,115 @@ output_function_profiler (file, labelno)
   int i, j;
   char buf[100];
 
-  if (DEFAULT_ABI != ABI_AIX)
-    abort ();
-
-  /* Set up a TOC entry for the profiler label.  */
-  toc_section ();
-  ASM_OUTPUT_INTERNAL_LABEL (file, "LPC", labelno);
   ASM_GENERATE_INTERNAL_LABEL (buf, "LP", labelno);
-  if (TARGET_MINIMAL_TOC)
-    {
-      fputs ("\t.long ", file);
-      assemble_name (file, buf);
-      putc ('\n', file);
-    }
-  else
+  switch (DEFAULT_ABI)
     {
-      fputs ("\t.tc\t", file);
-      assemble_name (file, buf);
-      fputs ("[TC],", file);
-      assemble_name (file, buf);
-      putc ('\n', file);
-    }
-  text_section ();
+    default:
+      abort ();
+
+    case ABI_V4:
+    case ABI_SOLARIS:
+    case ABI_AIX_NODESC:
+      fprintf (file, "\tmflr %s\n", reg_names[0]);
+      if (flag_pic == 1)
+       {
+         fprintf (file, "\tbl _GLOBAL_OFFSET_TABLE_@local-4\n");
+         fprintf (file, "\tmflr %s\n", reg_names[11]);
+         fprintf (file, "\t%s %s,", (TARGET_NEW_MNEMONICS) ? "lwz" : "l",
+                  reg_names[11]);
+         assemble_name (file, buf);
+         fprintf (file, "@got(%s)\n", reg_names[11]);
+       }
+#if TARGET_ELF
+      else if (flag_pic > 1 || TARGET_RELOCATABLE)
+       {
+         fprintf (file, "\tstw %s,4(%s)\n", reg_names[0], reg_names[1]);
+         fprintf (file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP);
+         assemble_name (file, buf);
+         fprintf (file, "X = .-.LCTOC1\n");
+         fprintf (file, "\t.long ");
+         assemble_name (file, buf);
+         fputs ("\n\t.previous\n", file);
+         rs6000_pic_func_labelno = rs6000_pic_labelno;
+         rs6000_output_load_toc_table (file, 11);
+         fprintf (file, "\t%s %s,", (TARGET_NEW_MNEMONICS) ? "lwz" : "l",
+                  reg_names[11]);
+         assemble_name (file, buf);
+         fprintf (file, "X(%s)\n", reg_names[11]);
+       }
+#endif
+      else if (TARGET_NEW_MNEMONICS)
+       {
+         fprintf (file, "\taddis %s,%s,", reg_names[11], reg_names[11]);
+         assemble_name (file, buf);
+         fprintf (file, "@ha\n");
+         fprintf (file, "\tstw %s,4(%s)\n", reg_names[0], reg_names[1]);
+         fprintf (file, "\taddi %s,%s,", reg_names[11], reg_names[11]);
+         assemble_name (file, buf);
+         fputs ("@l\n", file);
+       }
+      else
+       {
+         fprintf (file, "\tcau %s,%s,", reg_names[11], reg_names[11]);
+         assemble_name (file, buf);
+         fprintf (file, "@ha\n");
+         fprintf (file, "\tst %s,4(%s)\n", reg_names[0], reg_names[1]);
+         fprintf (file, "\tcal %s,", reg_names[11]);
+         assemble_name (file, buf);
+         fprintf (file, "@l(%s)\n", reg_names[11]);
+       }
+
+      fprintf (file, "\tbl %s\n", RS6000_MCOUNT);
+      break;
+
+    case ABI_AIX:
+      /* Set up a TOC entry for the profiler label.  */
+      toc_section ();
+      ASM_OUTPUT_INTERNAL_LABEL (file, "LPC", labelno);
+      if (TARGET_MINIMAL_TOC)
+       {
+         fputs ("\t.long ", file);
+         assemble_name (file, buf);
+         putc ('\n', file);
+       }
+      else
+       {
+         fputs ("\t.tc\t", file);
+         assemble_name (file, buf);
+         fputs ("[TC],", file);
+         assemble_name (file, buf);
+         putc ('\n', file);
+       }
+      text_section ();
 
   /* Figure out last used parameter register.  The proper thing to do is
      to walk incoming args of the function.  A function might have live
      parameter registers even if it has no incoming args.  */
 
-  for (last_parm_reg = 10;
-       last_parm_reg > 2 && ! regs_ever_live [last_parm_reg];
-       last_parm_reg--)
-    ;
+      for (last_parm_reg = 10;
+          last_parm_reg > 2 && ! regs_ever_live [last_parm_reg];
+          last_parm_reg--)
+       ;
 
   /* Save parameter registers in regs 23-30.  Don't overwrite reg 31, since
      it might be set up as the frame pointer.  */
 
-  for (i = 3, j = 30; i <= last_parm_reg; i++, j--)
-    asm_fprintf (file, "\tmr %d,%d\n", j, i);
+      for (i = 3, j = 30; i <= last_parm_reg; i++, j--)
+       asm_fprintf (file, "\tmr %d,%d\n", j, i);
 
   /* Load location address into r3, and call mcount.  */
 
-  ASM_GENERATE_INTERNAL_LABEL (buf, "LPC", labelno);
-  asm_fprintf (file, "\t{l|lwz} %s,", reg_names[3]);
-  assemble_name (file, buf);
-  asm_fprintf (file, "(%s)\n\tbl %s\n", reg_names[2], RS6000_MCOUNT);
+      ASM_GENERATE_INTERNAL_LABEL (buf, "LPC", labelno);
+      asm_fprintf (file, "\t{l|lwz} %s,", reg_names[3]);
+      assemble_name (file, buf);
+      asm_fprintf (file, "(%s)\n\tbl %s\n", reg_names[2], RS6000_MCOUNT);
 
   /* Restore parameter registers.  */
 
-  for (i = 3, j = 30; i <= last_parm_reg; i++, j--)
-    asm_fprintf (file, "\tmr %d,%d\n", i, j);
+      for (i = 3, j = 30; i <= last_parm_reg; i++, j--)
+       asm_fprintf (file, "\tmr %d,%d\n", i, j);
+      break;
+    }
 }
 
 /* Adjust the cost of a scheduling dependency.  Return the new cost of
index f469061a0d8bf9f58d261560167cd4aca5fe0f2a..60b4c529e82d9e4915062574d412261e92552077 100644 (file)
@@ -208,33 +208,33 @@ Boston, MA 02111-1307, USA.  */
 extern int target_flags;
 
 /* Use POWER architecture instructions and MQ register.  */
-#define MASK_POWER             0x01
+#define MASK_POWER             0x00000001
 
 /* Use POWER2 extensions to POWER architecture.  */
-#define MASK_POWER2            0x02
+#define MASK_POWER2            0x00000002
 
 /* Use PowerPC architecture instructions.  */
-#define MASK_POWERPC           0x04
+#define MASK_POWERPC           0x00000004
 
 /* Use PowerPC General Purpose group optional instructions, e.g. fsqrt.  */
-#define MASK_PPC_GPOPT         0x08
+#define MASK_PPC_GPOPT         0x00000008
 
 /* Use PowerPC Graphics group optional instructions, e.g. fsel.  */
-#define MASK_PPC_GFXOPT                0x10
+#define MASK_PPC_GFXOPT                0x00000010
 
 /* Use PowerPC-64 architecture instructions.  */
-#define MASK_POWERPC64         0x20
+#define MASK_POWERPC64         0x00000020
 
 /* Use revised mnemonic names defined for PowerPC architecture.  */
-#define MASK_NEW_MNEMONICS     0x40
+#define MASK_NEW_MNEMONICS     0x00000040
 
 /* Disable placing fp constants in the TOC; can be turned on when the
    TOC overflows.  */
-#define MASK_NO_FP_IN_TOC      0x80
+#define MASK_NO_FP_IN_TOC      0x00000080
 
 /* Disable placing symbol+offset constants in the TOC; can be turned on when
    the TOC overflows.  */
-#define MASK_NO_SUM_IN_TOC     0x100
+#define MASK_NO_SUM_IN_TOC     0x00000100
 
 /* Output only one TOC entry per module.  Normally linking fails if
    there are more than 16K unique variables/constants in an executable.  With
@@ -243,25 +243,27 @@ extern int target_flags;
 
    This is at the cost of having 2 extra loads and one extra store per
    function, and one less allocatable register.  */
-#define MASK_MINIMAL_TOC       0x200
+#define MASK_MINIMAL_TOC       0x00000200
 
 /* Nonzero for the 64bit model: ints, longs, and pointers are 64 bits.  */
-#define MASK_64BIT             0x400
+#define MASK_64BIT             0x00000400
 
 /* Disable use of FPRs.  */
-#define MASK_SOFT_FLOAT                0x800
+#define MASK_SOFT_FLOAT                0x00000800
 
 /* Enable load/store multiple, even on powerpc */
-#define        MASK_MULTIPLE           0x1000
-#define        MASK_MULTIPLE_SET       0x2000
+#define        MASK_MULTIPLE           0x00001000
+#define        MASK_MULTIPLE_SET       0x00002000
 
 /* Use string instructions for block moves */
-#define MASK_STRING            0x4000
-#define MASK_STRING_SET                0x8000
+#define MASK_STRING            0x00004000
+#define MASK_STRING_SET                0x00008000
 
-/* Temporary debug switches */
-#define MASK_DEBUG_STACK       0x10000
-#define MASK_DEBUG_ARG         0x20000
+/* Disable update form of load/store */
+#define MASK_NO_UPDATE         0x00010000
+
+/* Disable fused multiply/add operations */
+#define MASK_NO_FUSED_MADD     0x00020000
 
 #define TARGET_POWER           (target_flags & MASK_POWER)
 #define TARGET_POWER2          (target_flags & MASK_POWER2)
@@ -279,11 +281,13 @@ extern int target_flags;
 #define        TARGET_MULTIPLE_SET     (target_flags & MASK_MULTIPLE_SET)
 #define TARGET_STRING          (target_flags & MASK_STRING)
 #define TARGET_STRING_SET      (target_flags & MASK_STRING_SET)
-#define        TARGET_DEBUG_STACK      (target_flags & MASK_DEBUG_STACK)
-#define        TARGET_DEBUG_ARG        (target_flags & MASK_DEBUG_ARG)
+#define TARGET_NO_UPDATE       (target_flags & MASK_NO_UPDATE)
+#define TARGET_NO_FUSED_MADD   (target_flags & MASK_NO_FUSED_MADD)
 
 #define TARGET_32BIT           (! TARGET_64BIT)
 #define TARGET_HARD_FLOAT      (! TARGET_SOFT_FLOAT)
+#define TARGET_UPDATE          (! TARGET_NO_UPDATE)
+#define TARGET_FUSED_MADD      (! TARGET_NO_FUSED_MADD)
 
 /* Pseudo target to indicate whether the object format is ELF
    (to get around not having conditional compilation in the md file)  */
@@ -366,8 +370,10 @@ extern int target_flags;
   {"string",           MASK_STRING | MASK_STRING_SET},                 \
   {"no-string",                - MASK_STRING},                                 \
   {"no-string",                MASK_STRING_SET},                               \
-  {"debug-stack",      MASK_DEBUG_STACK},                              \
-  {"debug-arg",                MASK_DEBUG_ARG},                                \
+  {"update",           - MASK_NO_UPDATE},                              \
+  {"no-update",                MASK_NO_UPDATE},                                \
+  {"fused-madd",       - MASK_NO_FUSED_MADD},                          \
+  {"no-fused-madd",    MASK_NO_FUSED_MADD},                            \
   SUBTARGET_SWITCHES                                                   \
   {"",                 TARGET_DEFAULT}}
 
@@ -427,6 +433,8 @@ extern enum processor_type rs6000_cpu;
 {                                              \
    {"cpu=",  &rs6000_select[1].string},                \
    {"tune=", &rs6000_select[2].string},                \
+   {"debug-", &rs6000_debug_name},             \
+   {"debug=", &rs6000_debug_name},             \
    SUBTARGET_OPTIONS                           \
 }
 
@@ -441,6 +449,14 @@ struct rs6000_cpu_select
 
 extern struct rs6000_cpu_select rs6000_select[];
 
+/* Debug support */
+extern char *rs6000_debug_name;                /* Name for -mdebug-xxxx option */
+extern int rs6000_debug_stack;         /* debug stack applications */
+extern int rs6000_debug_arg;           /* debug argument handling */
+
+#define        TARGET_DEBUG_STACK      rs6000_debug_stack
+#define        TARGET_DEBUG_ARG        rs6000_debug_arg
+
 /* Sometimes certain combinations of command options do not make sense
    on a particular target machine.  You can define a macro
    `OVERRIDE_OPTIONS' to take account of this.  This macro, if
@@ -1811,6 +1827,7 @@ typedef struct rs6000_args
 { if (LEGITIMATE_INDIRECT_ADDRESS_P (X))               \
     goto ADDR;                                         \
   if ((GET_CODE (X) == PRE_INC || GET_CODE (X) == PRE_DEC) \
+      && TARGET_UPDATE                                 \
       && LEGITIMATE_INDIRECT_ADDRESS_P (XEXP (X, 0)))  \
     goto ADDR;                                         \
   if (LEGITIMATE_SMALL_DATA_P (MODE, X))               \
@@ -1904,9 +1921,9 @@ typedef struct rs6000_args
       && ! LEGITIMATE_ADDRESS_INTEGER_P (XEXP (ADDR, 1),       \
                                         (TARGET_32BIT ? 4 : 8))) \
     goto LABEL;                                                        \
-  if (GET_CODE (ADDR) == PRE_INC)                              \
+  if (TARGET_UPDATE && GET_CODE (ADDR) == PRE_INC)             \
     goto LABEL;                                                        \
-  if (GET_CODE (ADDR) == PRE_DEC)                              \
+  if (TARGET_UPDATE && GET_CODE (ADDR) == PRE_DEC)             \
     goto LABEL;                                                        \
   if (GET_CODE (ADDR) == LO_SUM)                               \
     goto LABEL;                                                        \
@@ -2096,59 +2113,74 @@ typedef struct rs6000_args
 /* Provide the costs of a rtl expression.  This is in the body of a
    switch on CODE.  */
 
-#define RTX_COSTS(X,CODE,OUTER_CODE)                   \
-  case MULT:                                           \
-  switch (rs6000_cpu)                                  \
-    {                                                  \
-    case PROCESSOR_RIOS1:                              \
-      return (GET_CODE (XEXP (X, 1)) != CONST_INT      \
-             ? COSTS_N_INSNS (5)                       \
-             : INTVAL (XEXP (X, 1)) >= -256 && INTVAL (XEXP (X, 1)) <= 255 \
-             ? COSTS_N_INSNS (3) : COSTS_N_INSNS (4)); \
-    case PROCESSOR_RIOS2:                              \
-    case PROCESSOR_MPCCORE:                            \
-      return COSTS_N_INSNS (2);                                \
-    case PROCESSOR_PPC601:                             \
-      return COSTS_N_INSNS (5);                                \
-    case PROCESSOR_PPC603:                             \
-      return (GET_CODE (XEXP (X, 1)) != CONST_INT      \
-             ? COSTS_N_INSNS (5)                       \
-             : INTVAL (XEXP (X, 1)) >= -256 && INTVAL (XEXP (X, 1)) <= 255 \
-             ? COSTS_N_INSNS (2) : COSTS_N_INSNS (3)); \
-    case PROCESSOR_PPC403:                             \
-    case PROCESSOR_PPC604:                             \
-    case PROCESSOR_PPC620:                             \
-      return COSTS_N_INSNS (4);                                \
-    }                                                  \
-  case DIV:                                            \
-  case MOD:                                            \
-    if (GET_CODE (XEXP (X, 1)) == CONST_INT            \
-       && exact_log2 (INTVAL (XEXP (X, 1))) >= 0)      \
-      return COSTS_N_INSNS (2);                                \
-    /* otherwise fall through to normal divide.  */    \
-  case UDIV:                                           \
-  case UMOD:                                           \
-  switch (rs6000_cpu)                                  \
-    {                                                  \
-    case PROCESSOR_RIOS1:                              \
-      return COSTS_N_INSNS (19);                       \
-    case PROCESSOR_RIOS2:                              \
-      return COSTS_N_INSNS (13);                       \
-    case PROCESSOR_MPCCORE:                            \
-      return COSTS_N_INSNS (6);                                \
-    case PROCESSOR_PPC403:                             \
-      return COSTS_N_INSNS (33);                       \
-    case PROCESSOR_PPC601:                             \
-      return COSTS_N_INSNS (36);                       \
-    case PROCESSOR_PPC603:                             \
-      return COSTS_N_INSNS (37);                       \
-    case PROCESSOR_PPC604:                             \
-    case PROCESSOR_PPC620:                             \
-      return COSTS_N_INSNS (20);                       \
-    }                                                  \
-  case FFS:                                            \
-    return COSTS_N_INSNS (4);                          \
-  case MEM:                                            \
+#define RTX_COSTS(X,CODE,OUTER_CODE)                                   \
+  case PLUS:                                                           \
+    return ((GET_CODE (XEXP (X, 1)) == CONST_INT                       \
+            && (unsigned HOST_WIDE_INT) ((INTVAL (XEXP (X, 1))         \
+                                          + 0x8000) >= 0x10000))       \
+           ? COSTS_N_INSNS (2)                                         \
+           : COSTS_N_INSNS (1));                                       \
+  case AND:                                                            \
+    return ((non_and_cint_operand (XEXP (X, 1), SImode))               \
+           ? COSTS_N_INSNS (2)                                         \
+           : COSTS_N_INSNS (1));                                       \
+  case IOR:                                                            \
+  case XOR:                                                            \
+    return ((non_logical_cint_operand (XEXP (X, 1), SImode))           \
+           ? COSTS_N_INSNS (2)                                         \
+           : COSTS_N_INSNS (1));                                       \
+  case MULT:                                                           \
+    switch (rs6000_cpu)                                                        \
+      {                                                                        \
+      case PROCESSOR_RIOS1:                                            \
+        return (GET_CODE (XEXP (X, 1)) != CONST_INT                    \
+               ? COSTS_N_INSNS (5)                                     \
+               : INTVAL (XEXP (X, 1)) >= -256 && INTVAL (XEXP (X, 1)) <= 255 \
+               ? COSTS_N_INSNS (3) : COSTS_N_INSNS (4));               \
+      case PROCESSOR_RIOS2:                                            \
+      case PROCESSOR_MPCCORE:                                          \
+        return COSTS_N_INSNS (2);                                      \
+      case PROCESSOR_PPC601:                                           \
+        return COSTS_N_INSNS (5);                                      \
+      case PROCESSOR_PPC603:                                           \
+        return (GET_CODE (XEXP (X, 1)) != CONST_INT                    \
+               ? COSTS_N_INSNS (5)                                     \
+               : INTVAL (XEXP (X, 1)) >= -256 && INTVAL (XEXP (X, 1)) <= 255 \
+               ? COSTS_N_INSNS (2) : COSTS_N_INSNS (3));               \
+      case PROCESSOR_PPC403:                                           \
+      case PROCESSOR_PPC604:                                           \
+      case PROCESSOR_PPC620:                                           \
+        return COSTS_N_INSNS (4);                                      \
+      }                                                                        \
+  case DIV:                                                            \
+  case MOD:                                                            \
+    if (GET_CODE (XEXP (X, 1)) == CONST_INT                            \
+       && exact_log2 (INTVAL (XEXP (X, 1))) >= 0)                      \
+      return COSTS_N_INSNS (2);                                                \
+    /* otherwise fall through to normal divide.  */                    \
+  case UDIV:                                                           \
+  case UMOD:                                                           \
+    switch (rs6000_cpu)                                                        \
+      {                                                                        \
+      case PROCESSOR_RIOS1:                                            \
+       return COSTS_N_INSNS (19);                                      \
+      case PROCESSOR_RIOS2:                                            \
+       return COSTS_N_INSNS (13);                                      \
+      case PROCESSOR_MPCCORE:                                          \
+       return COSTS_N_INSNS (6);                                       \
+      case PROCESSOR_PPC403:                                           \
+       return COSTS_N_INSNS (33);                                      \
+      case PROCESSOR_PPC601:                                           \
+       return COSTS_N_INSNS (36);                                      \
+      case PROCESSOR_PPC603:                                           \
+       return COSTS_N_INSNS (37);                                      \
+      case PROCESSOR_PPC604:                                           \
+      case PROCESSOR_PPC620:                                           \
+       return COSTS_N_INSNS (20);                                      \
+      }                                                                        \
+  case FFS:                                                            \
+    return COSTS_N_INSNS (4);                                          \
+  case MEM:                                                            \
     /* MEM should be slightly more expensive than (plus (reg) (const)) */ \
     return 5;
 
@@ -2373,8 +2405,6 @@ toc_section ()                                            \
 {                                                      \
   if (TARGET_MINIMAL_TOC)                              \
     {                                                  \
-      static int toc_initialized = 0;                  \
-                                                       \
       /* toc_section is always called at least once from ASM_FILE_START, \
         so this is guaranteed to always be defined once and only once   \
         in each file.  */                                               \
@@ -2396,6 +2426,9 @@ toc_section ()                                            \
   in_section = toc;                                    \
 }
 
+/* Flag to say the TOC is initialized */
+extern int toc_initialized;
+
 /* This macro produces the initial definition of a function name.
    On the RS/6000, we need to place an extra '.' in the function name and
    output the function descriptor.
@@ -2998,6 +3031,7 @@ do {                                                                      \
   {"reg_or_u_short_operand", {SUBREG, REG, CONST_INT}},                \
   {"reg_or_cint_operand", {SUBREG, REG, CONST_INT}},           \
   {"got_operand", {SYMBOL_REF, CONST, LABEL_REF}},             \
+  {"got_no_const_operand", {SYMBOL_REF, LABEL_REF}},           \
   {"easy_fp_constant", {CONST_DOUBLE}},                                \
   {"reg_or_mem_operand", {SUBREG, MEM, REG}},                  \
   {"lwa_operand", {SUBREG, MEM, REG}},                         \
@@ -3058,6 +3092,7 @@ extern int reg_or_neg_short_operand ();
 extern int reg_or_u_short_operand ();
 extern int reg_or_cint_operand ();
 extern int got_operand ();
+extern int got_no_const_operand ();
 extern int num_insns_constant ();
 extern int easy_fp_constant ();
 extern int volatile_mem_operand ();
index fc1323a7b3ca4220d3ff3a3c3d36d682f1e904d7..0e6e259c8c897fdb39de7ca1f35a52d46d1a3d3e 100644 (file)
 ;; Discourage ai/addic because of carry but provide it in an alternative
 ;; allowing register zero as source.
 (define_insn "addsi3"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,?r,r")
-       (plus:SI (match_operand:SI 1 "gpc_reg_operand" "%r,b,r,b")
-                (match_operand:SI 2 "add_operand" "r,I,I,J")))]
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,?r,r,r")
+       (plus:SI (match_operand:SI 1 "gpc_reg_operand" "%r,b,r,b,b")
+                (match_operand:SI 2 "reg_or_cint_operand" "r,I,I,J,n")))]
   ""
   "@
    {cax|add} %0,%1,%2
    {cal %0,%2(%1)|addi %0,%1,%2}
    {ai|addic} %0,%1,%2
-   {cau|addis} %0,%1,%v2")
+   {cau|addis} %0,%1,%v2
+   #"
+  [(set_attr "length" "4,4,4,4,8")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,x")
   [(set_attr "type" "idiv")])
 \f
 (define_insn "andsi3"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
-       (and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r")
-               (match_operand:SI 2 "and_operand" "?r,L,K,J")))
-   (clobber (match_scratch:CC 3 "=X,X,x,x"))]
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r,r")
+       (and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r")
+               (match_operand:SI 2 "reg_or_cint_operand" "?r,L,K,J,n")))
+   (clobber (match_scratch:CC 3 "=X,X,x,x,x"))]
   ""
   "@
    and %0,%1,%2
    {rlinm|rlwinm} %0,%1,0,%m2,%M2
    {andil.|andi.} %0,%1,%b2
-   {andiu.|andis.} %0,%1,%u2")
+   {andiu.|andis.} %0,%1,%u2
+   #"
+  [(set_attr "length" "4,4,4,4,8")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,x")
   [(set_attr "type" "compare,compare,compare,delayed_compare")])
 
 ;; Take a AND with a constant that cannot be done in a single insn and try to
-;; split it into two insns.  This does not verify that the insns are valid
-;; since this need not be done as combine will do it.
+;; split it into two insns.
 
 (define_split
   [(set (match_operand:SI 0 "gpc_reg_operand" "")
        (and:SI (match_operand:SI 1 "gpc_reg_operand" "")
-               (match_operand:SI 2 "non_and_cint_operand" "")))]
-  ""
-  [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 3)))
-   (set (match_dup 0) (and:SI (match_dup 0) (match_dup 4)))]
+               (match_operand:SI 2 "non_and_cint_operand" "")))
+   (clobber (match_scratch:CC 3 ""))]
+  "reload_completed"
+  [(parallel [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 4))) (clobber (match_dup 6))])
+   (parallel [(set (match_dup 0) (and:SI (match_dup 0) (match_dup 5))) (clobber (match_dup 7))])]
   "
 {
-  int maskval = INTVAL (operands[2]);
-  int i, transitions, last_bit_value;
-  int orig = maskval, first_c = maskval, second_c;
-
-  /* We know that MASKVAL must have more than 2 bit-transitions.  Start at
-     the low-order bit and count for the third transition.  When we get there,
-     make a first mask that has everything to the left of that position
-     a one.  Then make the second mask to turn off whatever else is needed.  */
-
-  for (i = 1, transitions = 0, last_bit_value = maskval & 1; i < 32; i++)
-    {
-      if (((maskval >>= 1) & 1) != last_bit_value)
-       last_bit_value ^= 1, transitions++;
-
-      if (transitions > 2)
-       {
-         first_c |= (~0) << i;
-         break;
-       }
-    }
-
-  second_c = orig | ~ first_c;
-
-  operands[3] = gen_rtx (CONST_INT, VOIDmode, first_c);
-  operands[4] = gen_rtx (CONST_INT, VOIDmode, second_c);
+  operands[4] = GEN_INT (INTVAL (operands[2]) & 0xffff0000);
+  operands[5] = GEN_INT (INTVAL (operands[2]) & 0x0000ffff);
+  operands[6] = ((mask_constant (INTVAL (operands[4])))
+                ? gen_rtx (SCRATCH, CCmode)
+                : operands[3]);
+  operands[7] = operands[3];
 }")
 
 (define_insn "iorsi3"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r")
-       (ior:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r")
-               (match_operand:SI 2 "logical_operand" "r,K,J")))]
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
+       (ior:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r")
+               (match_operand:SI 2 "reg_or_cint_operand" "r,K,J,n")))]
   ""
   "@
    or %0,%1,%2
    {oril|ori} %0,%1,%b2
-   {oriu|oris} %0,%1,%u2")
+   {oriu|oris} %0,%1,%u2
+   #"
+  [(set_attr "length" "4,4,4,8")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
   [(set_attr "type" "compare")])
 
 ;; Split an IOR that we can't do in one insn into two insns, each of which
-;; does one 16-bit part.  This is used by combine.
+;; does one 16-bit part.
 
 (define_split
   [(set (match_operand:SI 0 "gpc_reg_operand" "")
    (set (match_dup 0) (ior:SI (match_dup 0) (match_dup 4)))]
 "
 {
-  operands[3] = gen_rtx (CONST_INT, VOIDmode,
-                        INTVAL (operands[2]) & 0xffff0000);
-  operands[4] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 0xffff);
+  operands[3] = GEN_INT (INTVAL (operands[2]) & 0xffff0000);
+  operands[4] = GEN_INT (INTVAL (operands[2]) & 0x0000ffff);
 }")
 
 (define_insn "xorsi3"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r")
-       (xor:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r")
-               (match_operand:SI 2 "logical_operand" "r,K,J")))]
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
+       (xor:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r")
+               (match_operand:SI 2 "reg_or_cint_operand" "r,K,J,n")))]
   ""
   "@
    xor %0,%1,%2
    {xoril|xori} %0,%1,%b2
-   {xoriu|xoris} %0,%1,%u2")
+   {xoriu|xoris} %0,%1,%u2
+   #"
+  [(set_attr "length" "4,4,4,8")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
   [(set_attr "type" "compare")])
 
 ;; Split an XOR that we can't do in one insn into two insns, each of which
-;; does one 16-bit part.  This is used by combine.
+;; does one 16-bit part.
 
 (define_split
   [(set (match_operand:SI 0 "gpc_reg_operand" "")
    (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 4)))]
 "
 {
-  operands[3] = gen_rtx (CONST_INT, VOIDmode,
-                        INTVAL (operands[2]) & 0xffff0000);
-  operands[4] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 0xffff);
+  operands[3] = GEN_INT (INTVAL (operands[2]) & 0xffff0000);
+  operands[4] = GEN_INT (INTVAL (operands[2]) & 0x0000ffff);
 }")
 
 (define_insn ""
        (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
                          (match_operand:SF 2 "gpc_reg_operand" "f"))
                 (match_operand:SF 3 "gpc_reg_operand" "f")))]
-  "TARGET_POWERPC && TARGET_HARD_FLOAT"
+  "TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FUSED_MADD"
   "fmadds %0,%1,%2,%3"
   [(set_attr "type" "fp")])
 
        (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
                          (match_operand:SF 2 "gpc_reg_operand" "f"))
                 (match_operand:SF 3 "gpc_reg_operand" "f")))]
-  "! TARGET_POWERPC && TARGET_HARD_FLOAT"
+  "! TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FUSED_MADD"
   "{fma|fmadd} %0,%1,%2,%3"
   [(set_attr "type" "dmul")])
 
        (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
                           (match_operand:SF 2 "gpc_reg_operand" "f"))
                  (match_operand:SF 3 "gpc_reg_operand" "f")))]
-  "TARGET_POWERPC && TARGET_HARD_FLOAT"
+  "TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FUSED_MADD"
   "fmsubs %0,%1,%2,%3"
   [(set_attr "type" "fp")])
 
        (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
                           (match_operand:SF 2 "gpc_reg_operand" "f"))
                  (match_operand:SF 3 "gpc_reg_operand" "f")))]
-  "! TARGET_POWERPC && TARGET_HARD_FLOAT"
+  "! TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FUSED_MADD"
   "{fms|fmsub} %0,%1,%2,%3"
   [(set_attr "type" "dmul")])
 
        (neg:SF (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
                                  (match_operand:SF 2 "gpc_reg_operand" "f"))
                         (match_operand:SF 3 "gpc_reg_operand" "f"))))]
-  "TARGET_POWERPC && TARGET_HARD_FLOAT"
+  "TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FUSED_MADD"
   "fnmadds %0,%1,%2,%3"
   [(set_attr "type" "fp")])
 
        (neg:SF (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
                                  (match_operand:SF 2 "gpc_reg_operand" "f"))
                         (match_operand:SF 3 "gpc_reg_operand" "f"))))]
-  "! TARGET_POWERPC && TARGET_HARD_FLOAT"
+  "! TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FUSED_MADD"
   "{fnma|fnmadd} %0,%1,%2,%3"
   [(set_attr "type" "dmul")])
 
        (neg:SF (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
                                   (match_operand:SF 2 "gpc_reg_operand" "f"))
                          (match_operand:SF 3 "gpc_reg_operand" "f"))))]
-  "TARGET_POWERPC && TARGET_HARD_FLOAT"
+  "TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FUSED_MADD"
   "fnmsubs %0,%1,%2,%3"
   [(set_attr "type" "fp")])
 
        (neg:SF (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
                                   (match_operand:SF 2 "gpc_reg_operand" "f"))
                          (match_operand:SF 3 "gpc_reg_operand" "f"))))]
-  "! TARGET_POWERPC && TARGET_HARD_FLOAT"
+  "! TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FUSED_MADD"
   "{fnms|fnmsub} %0,%1,%2,%3"
   [(set_attr "type" "dmul")])
 
   "(DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS) && flag_pic == 1"
   "
 {
+  if (GET_CODE (operands[1]) == CONST)
+    {
+      rtx offset = const0_rtx;
+      HOST_WIDE_INT value;
+
+      operands[1] = eliminate_constant_term (XEXP (operands[1], 0), &offset);
+      value = INTVAL (offset);
+      if (value != 0)
+       {
+         rtx tmp = ((reload_in_progress || reload_completed)
+                    ? operands[0]
+                    : gen_reg_rtx (Pmode));
+         emit_insn (gen_movsi_got (tmp, operands[1]));
+         emit_insn (gen_addsi3 (operands[0], tmp, offset));
+         DONE;
+       }
+    }
+
   operands[2] = rs6000_got_register (operands[1]);
 }")
 
 (define_insn "*movsi_got_internal"
   [(set (match_operand:SI 0 "register_operand" "=r")
-       (unspec [(match_operand:SI 1 "got_operand" "")
+       (unspec [(match_operand:SI 1 "got_no_const_operand" "")
                 (match_operand:SI 2 "register_operand" "b")] 8))]
   "(DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS) && flag_pic == 1"
   "{l|lwz} %0,%a1@got(%2)"
 
          emit_insn (gen_movsi (tmp1, sym));
          if (INTVAL (const_term) != 0)
-           {
-             if (value + 0x8000 < 0x10000)
-               emit_insn (gen_addsi3 (operands[0], tmp1, GEN_INT (value)));
-
-             else
-               {
-                 HOST_WIDE_INT high_int = value & (~ (HOST_WIDE_INT) 0xffff);
-                 HOST_WIDE_INT low_int = value & 0xffff;
-                 rtx tmp2 = (!new_reg_p || !low_int) ? operands[0] : gen_reg_rtx (Pmode);
-
-                 if (low_int & 0x8000)
-                   high_int += 0x10000, low_int |= ((HOST_WIDE_INT) -1) << 16;
-
-                 emit_insn (gen_addsi3 (tmp2, tmp1, GEN_INT (high_int)));
-                 if (low_int)
-                   emit_insn (gen_addsi3 (operands[0], tmp2, GEN_INT (low_int)));
-               }
-           }
+           emit_insn (gen_addsi3 (operands[0], tmp1, GEN_INT (value)));
          DONE;
        }
       else
 ;; tie and these are the pair most likely to be tieable (and the ones
 ;; that will benefit the most).
 
-(define_insn ""
+(define_insn "*movdi_update1"
   [(set (match_operand:DI 3 "gpc_reg_operand" "=r,r")
        (mem:DI (plus:DI (match_operand:DI 1 "gpc_reg_operand" "0,0")
                         (match_operand:DI 2 "reg_or_short_operand" "r,I"))))
    (set (match_operand:DI 0 "gpc_reg_operand" "=b,b")
        (plus:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_POWERPC64"
+  "TARGET_POWERPC64 && TARGET_UPDATE"
   "@
    ldux %3,%0,%2
    ldu %3,%2(%0)"
   [(set_attr "type" "load")])
 
-(define_insn ""
+(define_insn "*movdi_update2"
   [(set (match_operand:DI 3 "gpc_reg_operand" "=r")
        (sign_extend:DI
         (mem:SI (plus:DI (match_operand:DI 1 "gpc_reg_operand" "0")
        (match_operand:DI 3 "gpc_reg_operand" "r,r"))
    (set (match_operand:DI 0 "gpc_reg_operand" "=b,b")
        (plus:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_POWERPC64"
+  "TARGET_POWERPC64 && TARGET_UPDATE"
   "@
    stdux %3,%0,%2
    stdu %3,%2(%0)"
   [(set_attr "type" "store")])
 
-(define_insn ""
+(define_insn "*movsi_update1"
   [(set (match_operand:SI 3 "gpc_reg_operand" "=r,r")
        (mem:SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
                         (match_operand:SI 2 "reg_or_short_operand" "r,I"))))
        (match_operand:SI 3 "gpc_reg_operand" "r,r"))
    (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
        (plus:SI (match_dup 1) (match_dup 2)))]
-  ""
+  "TARGET_UPDATE"
   "@
    {stux|stwux} %3,%0,%2
    {stu|stwu} %3,%2(%0)"
   [(set_attr "type" "store")])
 
-(define_insn ""
+(define_insn "*movhi_update"
   [(set (match_operand:HI 3 "gpc_reg_operand" "=r,r")
        (mem:HI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
                         (match_operand:SI 2 "reg_or_short_operand" "r,I"))))
    (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
        (plus:SI (match_dup 1) (match_dup 2)))]
-  ""
+  "TARGET_UPDATE"
   "@
    lhzux %3,%0,%2
    lhzu %3,%2(%0)"
   [(set_attr "type" "load")])
 
-(define_insn ""
+(define_insn "*movhi_update2"
   [(set (match_operand:SI 3 "gpc_reg_operand" "=r,r")
        (zero_extend:SI
         (mem:HI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
                          (match_operand:SI 2 "reg_or_short_operand" "r,I")))))
    (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
        (plus:SI (match_dup 1) (match_dup 2)))]
-  ""
+  "TARGET_UPDATE"
   "@
    lhzux %3,%0,%2
    lhzu %3,%2(%0)"
   [(set_attr "type" "load")])
 
-(define_insn ""
+(define_insn "*movhi_update3"
   [(set (match_operand:SI 3 "gpc_reg_operand" "=r,r")
        (sign_extend:SI
         (mem:HI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
                          (match_operand:SI 2 "reg_or_short_operand" "r,I")))))
    (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
        (plus:SI (match_dup 1) (match_dup 2)))]
-  ""
+  "TARGET_UPDATE"
   "@
    lhaux %3,%0,%2
    lhau %3,%2(%0)"
   [(set_attr "type" "load")])
 
-(define_insn ""
+(define_insn "*movhi_update4"
   [(set (mem:HI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
                         (match_operand:SI 2 "reg_or_short_operand" "r,I")))
        (match_operand:HI 3 "gpc_reg_operand" "r,r"))
    (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
        (plus:SI (match_dup 1) (match_dup 2)))]
-  ""
+  "TARGET_UPDATE"
   "@
    sthux %3,%0,%2
    sthu %3,%2(%0)"
   [(set_attr "type" "store")])
 
-(define_insn ""
+(define_insn "*movqi_update1"
   [(set (match_operand:QI 3 "gpc_reg_operand" "=r,r")
        (mem:QI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
                         (match_operand:SI 2 "reg_or_short_operand" "r,I"))))
    (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
        (plus:SI (match_dup 1) (match_dup 2)))]
-  ""
+  "TARGET_UPDATE"
   "@
    lbzux %3,%0,%2
    lbzu %3,%2(%0)"
   [(set_attr "type" "load")])
 
-(define_insn ""
+(define_insn "*movqi_update2"
   [(set (match_operand:SI 3 "gpc_reg_operand" "=r,r")
        (zero_extend:SI
         (mem:QI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
                          (match_operand:SI 2 "reg_or_short_operand" "r,I")))))
    (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
        (plus:SI (match_dup 1) (match_dup 2)))]
-  ""
+  "TARGET_UPDATE"
   "@
    lbzux %3,%0,%2
    lbzu %3,%2(%0)"
   [(set_attr "type" "load")])
 
-(define_insn ""
+(define_insn "*movqi_update3"
   [(set (mem:QI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
                         (match_operand:SI 2 "reg_or_short_operand" "r,I")))
        (match_operand:QI 3 "gpc_reg_operand" "r,r"))
    (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
        (plus:SI (match_dup 1) (match_dup 2)))]
-  ""
+  "TARGET_UPDATE"
   "@
    stbux %3,%0,%2
    stbu %3,%2(%0)"
   [(set_attr "type" "store")])
 
-(define_insn ""
+(define_insn "*movsf_update1"
   [(set (match_operand:SF 3 "gpc_reg_operand" "=f,f")
        (mem:SF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
                         (match_operand:SI 2 "reg_or_short_operand" "r,I"))))
    (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
        (plus:SI (match_dup 1) (match_dup 2)))]
-  "TARGET_HARD_FLOAT"
+  "TARGET_HARD_FLOAT && TARGET_UPDATE"
   "@
    lfsux %3,%0,%2
    lfsu %3,%2(%0)"
   [(set_attr "type" "fpload")])
 
-(define_insn ""
+(define_insn "*movsf_update2"
   [(set (mem:SF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
                         (match_operand:SI 2 "reg_or_short_operand" "r,I")))
        (match_operand:SF 3 "gpc_reg_operand" "f,f"))
    (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
        (plus:SI (match_dup 1) (match_dup 2)))]
-  "TARGET_HARD_FLOAT"
+  "TARGET_HARD_FLOAT && TARGET_UPDATE"
   "@
    stfsux %3,%0,%2
    stfsu %3,%2(%0)"
   [(set_attr "type" "fpstore")])
 
-(define_insn ""
+(define_insn "*movsf_update3"
+  [(set (match_operand:SF 3 "gpc_reg_operand" "=r,r")
+       (mem:SF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
+                        (match_operand:SI 2 "reg_or_short_operand" "r,I"))))
+   (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
+       (plus:SI (match_dup 1) (match_dup 2)))]
+  "TARGET_SOFT_FLOAT && TARGET_UPDATE"
+  "@
+   {lux|lwzux} %3,%0,%2
+   {lu|lwzu} %3,%2(%0)"
+  [(set_attr "type" "load")])
+
+(define_insn "*movsf_update4"
+  [(set (mem:SF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
+                        (match_operand:SI 2 "reg_or_short_operand" "r,I")))
+       (match_operand:SF 3 "gpc_reg_operand" "r,r"))
+   (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
+       (plus:SI (match_dup 1) (match_dup 2)))]
+  "TARGET_SOFT_FLOAT && TARGET_UPDATE"
+  "@
+   {stux|stwux} %3,%0,%2
+   {stu|stwu} %3,%2(%0)"
+  [(set_attr "type" "store")])
+
+(define_insn "*movdf_update1"
   [(set (match_operand:DF 3 "gpc_reg_operand" "=f,f")
        (mem:DF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
                         (match_operand:SI 2 "reg_or_short_operand" "r,I"))))
    (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
        (plus:SI (match_dup 1) (match_dup 2)))]
-  "TARGET_HARD_FLOAT"
+  "TARGET_HARD_FLOAT && TARGET_UPDATE"
   "@
    lfdux %3,%0,%2
    lfdu %3,%2(%0)"
   [(set_attr "type" "fpload")])
 
-(define_insn ""
+(define_insn "*movdf_update2"
   [(set (mem:DF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
                         (match_operand:SI 2 "reg_or_short_operand" "r,I")))
        (match_operand:DF 3 "gpc_reg_operand" "f,f"))
    (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
        (plus:SI (match_dup 1) (match_dup 2)))]
-  "TARGET_HARD_FLOAT"
+  "TARGET_HARD_FLOAT && TARGET_UPDATE"
   "@
    stfdux %3,%0,%2
    stfdu %3,%2(%0)"
   else
     neg_op0 = GEN_INT (- INTVAL (operands[0]));
 
-  if (TARGET_32BIT)
-    emit_insn (gen_movsi_update (stack_pointer_rtx, stack_pointer_rtx, neg_op0, chain));
-  else
-    emit_insn (gen_movdi_update (stack_pointer_rtx, stack_pointer_rtx, neg_op0, chain));
+  if (TARGET_UPDATE)
+    emit_insn ((* ((TARGET_32BIT) ? gen_movsi_update : gen_movdi_update))
+               (stack_pointer_rtx, stack_pointer_rtx, neg_op0, chain));
 
+  else
+    {
+      emit_insn ((* ((TARGET_32BIT) ? gen_addsi3 : gen_adddi3))
+                (stack_pointer_rtx, stack_pointer_rtx, neg_op0));
+      emit_move_insn (gen_rtx (MEM, (TARGET_32BIT) ? SImode : DImode,
+                              stack_pointer_rtx),
+                     chain);
+    }
   DONE;
 }")
 
   "TARGET_TOC && TARGET_MINIMAL_TOC && get_pool_size () != 0"
   "*
 {
-  rs6000_output_load_toc_table (asm_out_file);
+  rs6000_output_load_toc_table (asm_out_file, 30);
   return \"\";
 }"
   [(set_attr "type" "load")])
index 73c09dfa24efd9c3eb4ce4b61d4f67de99af2bfb..294debf3f9883023c80b879cb05949ffbadab4d4 100644 (file)
@@ -33,20 +33,18 @@ extern enum rs6000_sdata_type rs6000_sdata;
 #define        MASK_NO_BITFIELD_TYPE   0x40000000      /* Set PCC_BITFIELD_TYPE_MATTERS to 0 */
 #define        MASK_STRICT_ALIGN       0x20000000      /* Set STRICT_ALIGNMENT to 1.  */
 #define MASK_RELOCATABLE       0x10000000      /* GOT pointers are PC relative */
-#define        MASK_SDATA              0x08000000      /* use small data areas */
+#define        MASK_EABI               0x08000000      /* Adhere to eabi, not System V spec */
 #define MASK_LITTLE_ENDIAN     0x04000000      /* target is little endian */
 #define MASK_REGNAMES          0x02000000      /* use alternate register names.  */
 #define MASK_PROTOTYPE         0x01000000      /* Only prototyped fcns pass variable args */
-#define        MASK_EABI               0x00800000      /* Adhere to eabi, not System V spec */
 
 #define        TARGET_NO_BITFIELD_TYPE (target_flags & MASK_NO_BITFIELD_TYPE)
 #define TARGET_STRICT_ALIGN    (target_flags & MASK_STRICT_ALIGN)
 #define TARGET_RELOCATABLE     (target_flags & MASK_RELOCATABLE)
-#define TARGET_SDATA           (target_flags & MASK_SDATA)
+#define TARGET_EABI            (target_flags & MASK_EABI)
 #define TARGET_LITTLE_ENDIAN   (target_flags & MASK_LITTLE_ENDIAN)
 #define TARGET_REGNAMES                (target_flags & MASK_REGNAMES)
 #define        TARGET_PROTOTYPE        (target_flags & MASK_PROTOTYPE)
-#define TARGET_EABI            (target_flags & MASK_EABI)
 #define        TARGET_TOC              ((target_flags & MASK_64BIT)            \
                                 || ((target_flags & (MASK_RELOCATABLE  \
                                                      | MASK_MINIMAL_TOC)) \
@@ -73,13 +71,9 @@ extern enum rs6000_sdata_type rs6000_sdata;
   { "strict-align",     MASK_STRICT_ALIGN },                           \
   { "no-strict-align", -MASK_STRICT_ALIGN },                           \
   { "relocatable",      MASK_RELOCATABLE | MASK_MINIMAL_TOC | MASK_NO_FP_IN_TOC }, \
-  { "relocatable",     -MASK_SDATA },                                  \
   { "no-relocatable",  -MASK_RELOCATABLE },                            \
   { "relocatable-lib",  MASK_RELOCATABLE | MASK_MINIMAL_TOC | MASK_NO_FP_IN_TOC }, \
-  { "relocatable-lib", -MASK_SDATA },                                  \
   { "no-relocatable-lib", -MASK_RELOCATABLE },                         \
-  { "sdata",            MASK_SDATA },                                  \
-  { "no-sdata",                -MASK_SDATA },                                  \
   { "little-endian",    MASK_LITTLE_ENDIAN },                          \
   { "little",           MASK_LITTLE_ENDIAN },                          \
   { "big-endian",      -MASK_LITTLE_ENDIAN },                          \
@@ -94,6 +88,8 @@ extern enum rs6000_sdata_type rs6000_sdata;
   { "no-eabi",         -MASK_EABI },                                   \
   { "regnames",                  MASK_REGNAMES },                              \
   { "no-regnames",      -MASK_REGNAMES },                              \
+  { "sdata",            0 },                                           \
+  { "no-sdata",                 0 },                                           \
   { "sim",              0 },                                           \
   { "mvme",             0 },                                           \
   { "emb",              0 },                                           \
@@ -169,12 +165,8 @@ do {                                                                       \
                                                                        \
   if (rs6000_sdata_name)                                               \
     {                                                                  \
-      target_flags |= MASK_SDATA;                                      \
       if (!strcmp (rs6000_sdata_name, "none"))                         \
-       {                                                               \
-         rs6000_sdata = SDATA_NONE;                                    \
-         target_flags &= ~MASK_SDATA;                                  \
-       }                                                               \
+       rs6000_sdata = SDATA_NONE;                                      \
       else if (!strcmp (rs6000_sdata_name, "data"))                    \
        rs6000_sdata = SDATA_DATA;                                      \
       else if (!strcmp (rs6000_sdata_name, "default"))                 \
@@ -186,21 +178,10 @@ do {                                                                      \
       else                                                             \
        error ("Bad value for -msdata=%s", rs6000_sdata_name);          \
     }                                                                  \
-  else if (TARGET_SDATA && TARGET_EABI)                                        \
-    {                                                                  \
-      rs6000_sdata = SDATA_EABI;                                       \
-      rs6000_sdata_name = "eabi";                                      \
-    }                                                                  \
-  else if (TARGET_SDATA)                                               \
-    {                                                                  \
-      rs6000_sdata = SDATA_SYSV;                                       \
-      rs6000_sdata_name = "sysv";                                      \
-    }                                                                  \
   else if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)                \
     {                                                                  \
       rs6000_sdata = SDATA_DATA;                                       \
       rs6000_sdata_name = "data";                                      \
-      target_flags |= MASK_SDATA;                                      \
     }                                                                  \
   else                                                                 \
     {                                                                  \
@@ -225,10 +206,12 @@ do {                                                                      \
             rs6000_sdata_name);                                        \
     }                                                                  \
                                                                        \
-  if (TARGET_SDATA && DEFAULT_ABI != ABI_V4 && DEFAULT_ABI != ABI_SOLARIS) \
+  if (rs6000_sdata != SDATA_NONE && DEFAULT_ABI != ABI_V4              \
+      && DEFAULT_ABI != ABI_SOLARIS)                                   \
     {                                                                  \
-      target_flags &= ~MASK_SDATA;                                     \
-      error ("-msdata and -mcall-%s are incompatible.", rs6000_abi_name); \
+      rs6000_sdata = SDATA_NONE;                                       \
+      error ("-msdata=%s and -mcall-%s are incompatible.",             \
+            rs6000_sdata_name, rs6000_abi_name);                       \
     }                                                                  \
                                                                        \
   if (TARGET_RELOCATABLE && !TARGET_MINIMAL_TOC)                       \
@@ -467,8 +450,6 @@ extern void sbss_section ();
 void                                                                   \
 toc_section ()                                                         \
 {                                                                      \
-  static int toc_initialized = 0;                                      \
-                                                                       \
   if (in_section != in_toc)                                            \
     {                                                                  \
       in_section = in_toc;                                             \
@@ -628,7 +609,7 @@ extern int rs6000_pic_labelno;
     char *init_ptr = (TARGET_64BIT) ? ".quad" : ".long";               \
     STRIP_NAME_ENCODING (orig_name, NAME);                             \
                                                                        \
-    if (TARGET_RELOCATABLE && get_pool_size () != 0)                   \
+    if (TARGET_RELOCATABLE && (get_pool_size () != 0 || profile_flag)) \
       {                                                                        \
        char buf[256], *buf_ptr;                                        \
                                                                        \
@@ -701,7 +682,8 @@ extern int rs6000_pic_labelno;
 #undef ASM_OUTPUT_ALIGNED_LOCAL
 #define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN)              \
 do {                                                                   \
-  if (TARGET_SDATA && (SIZE) > 0 && (SIZE) <= g_switch_value)          \
+  if (rs6000_sdata != SDATA_NONE && (SIZE) > 0                         \
+      && (SIZE) <= g_switch_value)                                     \
     {                                                                  \
       sdata_section ();                                                        \
       ASM_OUTPUT_ALIGN (FILE, exact_log2 (ALIGN / BITS_PER_UNIT));     \
@@ -961,7 +943,8 @@ do {                                                                        \
 
 /* Pass various options to the assembler */
 #undef ASM_SPEC
-#define ASM_SPEC "%(asm_cpu) %{mregnames} %{mno-regnames} \
+#define ASM_SPEC "%(asm_cpu) \
+%{.s: %{mregnames} %{mno-regnames}} %{.S: %{mregnames} %{mno-regnames}} \
 %{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*} \
 %{mrelocatable} %{mrelocatable-lib} %{fpic:-K PIC} %{fPIC:-K PIC} \
 %{memb} %{!memb: %{msdata: -memb} %{msdata=eabi: -memb}} \
@@ -983,7 +966,9 @@ do {                                                                        \
 %{!meabi: %{!mno-eabi: \
     %{mrelocatable: -meabi } \
     %{mcall-solaris: -mno-eabi } \
-    %{mcall-linux: -mno-eabi }}}"
+    %{mcall-linux: -mno-eabi }}} \
+%{msdata: -msdata=default} \
+%{mno-sdata: -msdata=none}"
 
 /* Don't put -Y P,<path> for cross compilers */
 #undef LINK_PATH_SPEC
@@ -1357,3 +1342,12 @@ do {                                                                     \
 
 #undef MULTILIB_DEFAULTS
 #define        MULTILIB_DEFAULTS { "mbig", "mcall-sysv" }
+
+/* Define this macro if the code for function profiling should come
+   before the function prologue.  Normally, the profiling code comes
+   after.  */
+#define PROFILE_BEFORE_PROLOGUE 1
+
+/* Function name to call to do profiling.  */
+#undef RS6000_MCOUNT
+#define RS6000_MCOUNT "_mcount"