OSDN Git Service

(rs6000_output_load_toc_table): New function.
[pf3gnuchains/gcc-fork.git] / gcc / config / rs6000 / rs6000.c
index d1920a0..c009eff 100644 (file)
@@ -1,5 +1,5 @@
 /* Subroutines used for code generation on IBM RS/6000.
-   Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+   Copyright (C) 1991, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
    Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
 
 This file is part of GNU CC.
@@ -36,6 +36,7 @@ Boston, MA 02111-1307, USA.  */
 #include "expr.h"
 #include "obstack.h"
 #include "tree.h"
+#include "except.h"
 #include "function.h"
 
 #ifndef TARGET_NO_PROTOTYPE
@@ -94,9 +95,6 @@ char *rs6000_sdata_name = (char *)0;
 /* Whether a System V.4 varargs area was created.  */
 int rs6000_sysv_varargs_p;
 
-/* Whether we need to save the TOC register.  */
-int rs6000_save_toc_p;
-
 /* ABI enumeration available for subtarget to use.  */
 enum rs6000_abi rs6000_current_abi;
 
@@ -211,12 +209,21 @@ rs6000_override_options (default_cpu)
         {"604", PROCESSOR_PPC604,
            MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
            POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
+        {"604e", PROCESSOR_PPC604,
+           MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
+           POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
         {"620", PROCESSOR_PPC620,
            MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
            POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
+        {"801", PROCESSOR_MPCCORE,
+           MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS,
+           POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},
         {"821", PROCESSOR_MPCCORE,
            MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS,
            POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},
+        {"823", PROCESSOR_MPCCORE,
+           MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS,
+           POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},
         {"860", PROCESSOR_MPCCORE,
            MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS,
            POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64}};
@@ -448,7 +455,7 @@ short_cint_operand (op, mode)
      enum machine_mode mode;
 {
   return (GET_CODE (op) == CONST_INT
-         && (unsigned) (INTVAL (op) + 0x8000) < 0x10000);
+         && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x8000) < 0x10000);
 }
 
 /* Similar for a unsigned D field.  */
@@ -469,7 +476,7 @@ non_short_cint_operand (op, mode)
      enum machine_mode mode;
 {
   return (GET_CODE (op) == CONST_INT
-         && (unsigned) (INTVAL (op) + 0x8000) >= 0x10000);
+         && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x8000) >= 0x10000);
 }
 
 /* Returns 1 if OP is a register that is not special (i.e., not MQ,
@@ -677,6 +684,12 @@ easy_fp_constant (op, mode)
   if (flag_pic && (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS))
     return 0;
 
+#ifdef TARGET_RELOCATABLE
+  /* Similarly if we are using -mrelocatable, consider all constants to be hard */
+  if (TARGET_RELOCATABLE)
+    return 0;
+#endif
+
   if (mode == DFmode)
     {
       long k[2];
@@ -746,22 +759,6 @@ offsettable_addr_operand (op, mode)
                                mode, op);
 }
 
-/* Return 1 if the operand is either a floating-point register, a pseudo
-   register, or memory.  */
-
-int
-fp_reg_or_mem_operand (op, mode)
-     register rtx op;
-     enum machine_mode mode;
-{
-  return (memory_operand (op, mode)
-         || volatile_mem_operand (op, mode)
-         || (register_operand (op, mode)
-             && (GET_CODE (op) != REG
-                 || REGNO (op) >= FIRST_PSEUDO_REGISTER
-                 || FP_REGNO_P (REGNO (op)))));
-}
-
 /* Return 1 if the operand is either an easy FP constant (see above) or
    memory.  */
 
@@ -793,7 +790,7 @@ non_add_cint_operand (op, mode)
      enum machine_mode mode;
 {
   return (GET_CODE (op) == CONST_INT
-         && (unsigned) (INTVAL (op) + 0x8000) >= 0x10000
+         && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x8000) >= 0x10000
          && (INTVAL (op) & 0xffff) != 0);
 }
 
@@ -1895,7 +1892,7 @@ includes_rshift_p (shiftop, andop)
      register rtx shiftop;
      register rtx andop;
 {
-  unsigned shift_mask = ~(unsigned)0;
+  unsigned HOST_WIDE_INT shift_mask = ~(unsigned HOST_WIDE_INT) 0;
 
   shift_mask >>= INTVAL (shiftop);
 
@@ -2071,7 +2068,7 @@ struct rtx_def *
 rs6000_got_register (value)
      rtx value;
 {
-  if (!pic_offset_table_rtx)
+  if (!current_function_uses_pic_offset_table || !pic_offset_table_rtx)
     {
       if (reload_in_progress || reload_completed)
        fatal_insn ("internal error -- needed new GOT register during reload phase to load:", value);
@@ -2235,7 +2232,6 @@ rs6000_save_machine_status (p)
 
   p->machine = machine;
   machine->sysv_varargs_p = rs6000_sysv_varargs_p;
-  machine->save_toc_p     = rs6000_save_toc_p;
   machine->fpmem_size     = rs6000_fpmem_size;
   machine->fpmem_offset   = rs6000_fpmem_offset;
 }
@@ -2247,7 +2243,6 @@ rs6000_restore_machine_status (p)
   struct machine_function *machine = p->machine;
 
   rs6000_sysv_varargs_p = machine->sysv_varargs_p;
-  rs6000_save_toc_p     = machine->save_toc_p;
   rs6000_fpmem_size     = machine->fpmem_size;
   rs6000_fpmem_offset   = machine->fpmem_offset;
 
@@ -2262,7 +2257,6 @@ rs6000_init_expanders ()
 {
   /* Reset varargs and save TOC indicator */
   rs6000_sysv_varargs_p = 0;
-  rs6000_save_toc_p = 0;
   rs6000_fpmem_size = 0;
   rs6000_fpmem_offset = 0;
   pic_offset_table_rtx = (rtx)0;
@@ -2843,7 +2837,7 @@ first_reg_to_save ()
       break;
 
   /* If profiling, then we must save/restore every register that contains
-     a parameter before/after the .mcount call.  Use registers from 30 down
+     a parameter before/after the .__mcount call.  Use registers from 30 down
      to 23 to do this.  Don't use the frame pointer in reg 31.
 
      For now, save enough room for all of the parameter registers.  */
@@ -2876,7 +2870,7 @@ rs6000_makes_calls ()
 {
   rtx insn;
 
-  /* If we are profiling, we will be making a call to mcount.  */
+  /* If we are profiling, we will be making a call to __mcount.  */
   if (profile_flag)
     return 1;
 
@@ -2993,6 +2987,10 @@ rs6000_makes_calls ()
    old SP.  To support calls through pointers, we also allocate a
    fixed slot to store the TOC, -8 off the old SP.  */
 
+#ifndef ABI_STACK_BOUNDARY
+#define ABI_STACK_BOUNDARY STACK_BOUNDARY
+#endif
+
 rs6000_stack_t *
 rs6000_stack_info ()
 {
@@ -3018,8 +3016,8 @@ rs6000_stack_info ()
   /* Does this function call anything? */
   info_ptr->calls_p = rs6000_makes_calls ();
 
-  /* Do we need to allocate space to save the toc? */
-  if (rs6000_save_toc_p)
+  /* Allocate space to save the toc. */
+  if (abi == ABI_NT && info_ptr->calls_p)
     {
       info_ptr->toc_save_p = 1;
       info_ptr->toc_size = reg_size;
@@ -3107,7 +3105,7 @@ rs6000_stack_info ()
                            + info_ptr->varargs_size
                            + info_ptr->fixed_size);
 
-  info_ptr->total_size   = ALIGN (total_raw_size, STACK_BOUNDARY / BITS_PER_UNIT);
+  info_ptr->total_size   = ALIGN (total_raw_size, ABI_STACK_BOUNDARY / BITS_PER_UNIT);
 
   /* Determine if we need to allocate any stack frame.
      For AIX We need to push the stack if a frame pointer is needed (because
@@ -3326,8 +3324,76 @@ debug_stack_info (info)
 
   fprintf (stderr, "\n");
 }
-
 \f
+/* Write out an instruction to load the TOC_TABLE address into register 30.
+   This is only needed when TARGET_TOC, TARGET_MINIMAL_TOC, and there is
+   a constant pool.  */
+
+void
+rs6000_output_load_toc_table (file)
+     FILE *file;
+{
+  char buf[256];
+
+#ifdef USING_SVR4_H
+  if (TARGET_RELOCATABLE)
+    {
+      ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);
+      fprintf (file, "\tbl ");
+      assemble_name (file, buf);
+      fprintf (file, "\n");
+
+      ASM_OUTPUT_INTERNAL_LABEL (file, "LCF", rs6000_pic_labelno);
+      fprintf (file, "\tmflr %s\n", reg_names[30]);
+
+      if (TARGET_POWERPC64)
+       fprintf (file, "\tld");
+      else if (TARGET_NEW_MNEMONICS)
+       fprintf (file, "\tlwz");
+      else
+       fprintf (file, "\tl");
+
+      fprintf (file, " %s,(", reg_names[0]);
+      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]);
+      asm_fprintf (file, "\t{cax|add} %s,%s,%s\n",
+                  reg_names[30], reg_names[0], reg_names[30]);
+      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]);
+      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]);
+         assemble_name (file, buf);
+         asm_fprintf (file, "@l\n");
+       }
+      else
+       {
+         asm_fprintf (file, "\tcal %s,", reg_names[30]);
+         assemble_name (file, buf);
+         asm_fprintf (file, "@l(%s)\n", reg_names[30]);
+       }
+    }
+  else
+    abort ();
+
+#else  /* !USING_SVR4_H */
+  ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 0);
+  asm_fprintf (file, "\t{l|lwz} %s,", reg_names[30]);
+  assemble_name (file, buf);
+  asm_fprintf (file, "(%s)\n", reg_names[2]);
+#endif /* USING_SVR4_H */
+}
+
 /* Write function prologue.  */
 void
 output_prolog (file, size)
@@ -3478,10 +3544,6 @@ output_prolog (file, size)
                     reg_names[sp_reg]);
     }
 
-  if (info->toc_save_p)
-    asm_fprintf (file, store_reg, reg_names[2], info->toc_save_offset + sp_offset,
-                reg_names[sp_reg]);
-
   /* NT needs us to probe the stack frame every 4k pages for large frames, so
      do it here.  */
   if (DEFAULT_ABI == ABI_NT && info->total_size > 4096)
@@ -3514,7 +3576,7 @@ output_prolog (file, size)
          asm_fprintf (file, "\tmr %s,%s\n", reg_names[12], reg_names[1]);
          ASM_OUTPUT_INTERNAL_LABEL (file, "LCprobe", probe_labelno);
          asm_fprintf (file, "\t{lu|lwzu} %s,-4096(%s)\n", reg_names[0], reg_names[12]);
-         ASM_GENERATE_INTERNAL_LABEL (buf, "LCprobe", probe_labelno);
+         ASM_GENERATE_INTERNAL_LABEL (buf, "LCprobe", probe_labelno++);
          fputs ("\tbdnz ", file);
          assemble_name (file, buf);
          fputs ("\n", file);
@@ -3601,73 +3663,7 @@ output_prolog (file, size)
   /* If TARGET_MINIMAL_TOC, and the constant pool is needed, then load the
      TOC_TABLE address into register 30.  */
   if (TARGET_TOC && TARGET_MINIMAL_TOC && get_pool_size () != 0)
-    {
-      char buf[256];
-
-#ifdef TARGET_RELOCATABLE
-      if (TARGET_RELOCATABLE)
-       {
-         ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);
-         fputs ("\tbl ", file);
-         assemble_name (file, buf);
-         putc ('\n', file);
-
-         ASM_OUTPUT_INTERNAL_LABEL (file, "LCF", rs6000_pic_labelno);
-         fprintf (file, "\tmflr %s\n", reg_names[30]);
-
-         asm_fprintf (file, (TARGET_32BIT) ? "\t{l|lwz}" : "\tld");
-         fprintf (file, " %s,(", reg_names[0]);
-         ASM_GENERATE_INTERNAL_LABEL (buf, "LCL", rs6000_pic_labelno);
-         assemble_name (file, buf);
-         putc ('-', file);
-         ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);
-         assemble_name (file, buf);
-         fprintf (file, ")(%s)\n", reg_names[30]);
-         asm_fprintf (file, "\t{cax|add} %s,%s,%s\n",
-                      reg_names[30], reg_names[0], reg_names[30]);
-         rs6000_pic_labelno++;
-       }
-      else
-#endif
-
-       switch (DEFAULT_ABI)
-         {
-         case ABI_V4:
-         case ABI_SOLARIS:
-         case ABI_AIX_NODESC:
-           if (TARGET_32BIT)
-             {
-               ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 1);
-               asm_fprintf (file, "\t{cau|addis} %s,%s,", reg_names[30], 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]);
-                   assemble_name (file, buf);
-                   asm_fprintf (file, "@l\n");
-                 }
-               else
-                 {
-                   asm_fprintf (file, "\tcal %s,", reg_names[30]);
-                   assemble_name (file, buf);
-                   asm_fprintf (file, "@l(%s)\n", reg_names[30]);
-                 }
-             }
-           else
-             abort ();
-
-         break;
-
-       case ABI_NT:
-       case ABI_AIX:
-         ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 0);
-         asm_fprintf (file, "\t{l|lwz} %s,", reg_names[30]);
-         assemble_name (file, buf);
-         asm_fprintf (file, "(%s)\n", reg_names[2]);
-         break;
-       }
-    }
+    rs6000_output_load_toc_table (file);
 
   if (DEFAULT_ABI == ABI_NT)
     {
@@ -4056,9 +4052,9 @@ output_toc (file, x, labelno)
       REAL_VALUE_TO_TARGET_SINGLE (rv, l);
 
       if (TARGET_MINIMAL_TOC)
-       fprintf (file, "\t.long %d\n", l);
+       fprintf (file, "\t.long %ld\n", l);
       else
-       fprintf (file, "\t.tc FS_%x[TC],%d\n", l, l);
+       fprintf (file, "\t.tc FS_%lx[TC],%ld\n", l, l);
       return;
     }
   else if (GET_MODE (x) == DImode
@@ -4087,10 +4083,10 @@ output_toc (file, x, labelno)
 #endif
 
       if (TARGET_MINIMAL_TOC)
-       fprintf (file, "\t.long %ld\n\t.long %ld\n", high, low);
+       fprintf (file, "\t.long %ld\n\t.long %ld\n", (long)high, (long)low);
       else
        fprintf (file, "\t.tc ID_%lx_%lx[TC],%ld,%ld\n",
-                high, low, high, low);
+                (long)high, (long)low, (long)high, (long)low);
       return;
     }
 
@@ -4109,11 +4105,11 @@ output_toc (file, x, labelno)
   else
     abort ();
 
+  STRIP_NAME_ENCODING (real_name, name);
   if (TARGET_MINIMAL_TOC)
     fputs ("\t.long ", file);
   else
     {
-      STRIP_NAME_ENCODING (real_name, name);
       fprintf (file, "\t.tc %s", real_name);
 
       if (offset < 0)
@@ -4123,7 +4119,23 @@ output_toc (file, x, labelno)
 
       fputs ("[TC],", file);
     }
-  output_addr_const (file, x);
+
+  /* Currently C++ toc references to vtables can be emitted before it
+     is decided whether the vtable is public or private.  If this is
+     the case, then the linker will eventually complain that there is
+     a TOC reference to an unknown section.  Thus, for vtables only,
+     we emit the TOC reference to reference the symbol and not the
+     section.  */
+  if (!strncmp ("_vt.", name, 4))
+    {
+      RS6000_OUTPUT_BASENAME (file, name);
+      if (offset < 0)
+       fprintf (file, "%d", offset);
+      else if (offset > 0)
+       fprintf (file, "+%d", offset);
+    }
+  else
+    output_addr_const (file, x);
   putc ('\n', file);
 }
 \f
@@ -4307,7 +4319,7 @@ output_function_profiler (file, labelno)
   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 .mcount\n", reg_names[2]);
+  asm_fprintf (file, "(%s)\n\tbl %s\n", reg_names[2], RS6000_MCOUNT);
 
   /* Restore parameter registers.  */
 
@@ -4370,65 +4382,6 @@ int get_issue_rate()
   }
 }
 
-\f
-/* Output insns to flush the {data|instruction} caches after building a
-   trampoline. */
-
-static void
-rs6000_sync_trampoline (addr)
-     rtx addr;
-{
-  enum machine_mode pmode = Pmode;
-  rtx reg = gen_reg_rtx (pmode);
-  rtx mem2;
-  rtx mem1;
-  int size = rs6000_trampoline_size ();
-  rtx (*sub_fcn) PROTO ((rtx, rtx, rtx));
-  rtx (*cmp_fcn) PROTO ((rtx, rtx));
-  rtx label;
-
-  if (TARGET_32BIT)
-    {
-      sub_fcn = gen_subsi3;
-      cmp_fcn = gen_cmpsi;
-    }
-  else
-    {
-      sub_fcn = gen_subdi3;
-      cmp_fcn = gen_cmpdi;
-    }
-
-  addr = force_reg (pmode, addr);
-  mem2 = gen_rtx (MEM, pmode, gen_rtx (PLUS, pmode, addr, reg));
-  mem1 = gen_rtx (MEM, pmode, addr);
-
-  /* Issue a loop of dcbst's to flush the data cache */
-  emit_move_insn (reg, GEN_INT (size-4));
-  label = gen_label_rtx ();
-  emit_label (label);
-  emit_insn (gen_dcbst (mem2, addr, reg));
-  emit_insn ((*sub_fcn) (reg, reg, GEN_INT (4)));
-  emit_insn ((*cmp_fcn) (reg, const0_rtx));
-  emit_jump_insn (gen_bgt (label));
-
-  /* Issue a sync after the dcbst's to let things settle down */
-  emit_insn (gen_sync (mem1));
-
-  /* Issue a loop of icbi's to flush the instruction cache */
-  emit_move_insn (reg, GEN_INT (size-4));
-  label = gen_label_rtx ();
-  emit_label (label);
-  emit_insn (gen_icbi (mem2, addr, reg));
-  emit_insn ((*sub_fcn) (reg, reg, GEN_INT (4)));
-  emit_insn ((*cmp_fcn) (reg, const0_rtx));
-  emit_jump_insn (gen_bgt (label));
-
-  /* Issue a sync after the icbi's to let things settle down */
-  emit_insn (gen_sync (mem1));
-
-  /* Finally issue an isync to synchronize the icache */
-  emit_insn (gen_isync (mem1));
-}
 
 \f
 /* Output assembler code for a block containing the constant parts
@@ -4455,7 +4408,6 @@ rs6000_trampoline_template (file)
        the address of the function, the second word is the TOC pointer (r2),
        and the third word is the static chain value.  */
     case ABI_AIX:
-      fprintf (file, "\t.long %s\n", (TARGET_32BIT) ? "0,0,0" : "0,0,0,0,0,0");
       break;
 
 
@@ -4464,35 +4416,6 @@ rs6000_trampoline_template (file)
     case ABI_V4:
     case ABI_SOLARIS:
     case ABI_AIX_NODESC:
-      if (STATIC_CHAIN_REGNUM == 0 || !TARGET_NEW_MNEMONICS)
-       abort ();
-
-      if (TARGET_32BIT)
-       {
-         fprintf (file, "\tmflr %s\n", r0);            /* offset  0 */
-         fprintf (file, "\tbl .LTRAMP1\n");            /* offset  4 */
-         fprintf (file, "\t.long 0,0\n");              /* offset  8 */
-         fprintf (file, ".LTRAMP1:\n");
-         fprintf (file, "\tmflr %s\n", sc);            /* offset 20 */
-         fprintf (file, "\tmtlr %s\n", r0);            /* offset 24 */
-         fprintf (file, "\tlwz %s,0(%s)\n", r0, sc);   /* offset 28 */
-         fprintf (file, "\tlwz %s,4(%s)\n", sc, sc);   /* offset 32 */
-         fprintf (file, "\tmtctr %s\n", r0);           /* offset 36 */
-         fprintf (file, "\tbctr\n");                   /* offset 40 */
-       }
-      else
-       {
-         fprintf (file, "\tmflr %s\n", r0);            /* offset  0 */
-         fprintf (file, "\tbl .LTRAMP1\n");            /* offset  4 */
-         fprintf (file, "\t.long 0,0,0,0\n");          /* offset  8 */
-         fprintf (file, ".LTRAMP1:\n");
-         fprintf (file, "\tmflr %s\n", sc);            /* offset 28 */
-         fprintf (file, "\tmtlr %s\n", r0);            /* offset 32 */
-         fprintf (file, "\tld %s,0(%s)\n", r0, sc);    /* offset 36 */
-         fprintf (file, "\tld %s,8(%s)\n", sc, sc);    /* offset 40 */
-         fprintf (file, "\tmtctr %s\n", r0);           /* offset 44 */
-         fprintf (file, "\tbctr\n");                   /* offset 48 */
-       }
       break;
 
   /* NT function pointers point to a two word area (real address, TOC)
@@ -4589,18 +4512,16 @@ rs6000_initialize_trampoline (addr, fnaddr, cxt)
       }
       break;
 
-    /* Under V.4/eabi, update the two words after the bl to have the real
-       function address and the static chain.  */
+    /* Under V.4/eabi, call __trampoline_setup to do the real work.  */
     case ABI_V4:
     case ABI_SOLARIS:
     case ABI_AIX_NODESC:
-      {
-       rtx reg = gen_reg_rtx (pmode);
-       emit_move_insn (reg, fnaddr);
-       emit_move_insn (MEM_PLUS (addr, 8), reg);
-       emit_move_insn (MEM_PLUS (addr, 8 + regsize), ctx_reg);
-       rs6000_sync_trampoline (addr);
-      }
+      emit_library_call (gen_rtx (SYMBOL_REF, SImode, "__trampoline_setup"),
+                        FALSE, VOIDmode, 4,
+                        addr, pmode,
+                        GEN_INT (rs6000_trampoline_size ()), SImode,
+                        fnaddr, pmode,
+                        ctx_reg, pmode);
       break;
 
     /* Under NT, update the first word to point to the ..LTRAMP1..0 header,
@@ -4933,74 +4854,3 @@ rs6000_encode_section_info (decl)
 }
 
 #endif /* USING_SVR4_H */
-
-\f
-/* CYGNUS LOCAL mac */
-
-/* Whether we are using m68k-compatible alignment.  */
-
-int mac68k_aligned;
-
-/* Most Mac compiler pragmas are unimportant, but we must recognize
-   the m68k alignment pragma, because that is crucial to transitions
-   to and from the m68k emulator on PowerMacs.  */
-
-int
-handle_mac_pragma (finput, t)
-     FILE *finput;
-     tree t;
-{
-  int retval = 0;
-  register char *pname;
-  char pbuf[200];
-  int c, psize;
-
-  if (TREE_CODE (t) != IDENTIFIER_NODE)
-    return 0;
-
-  pname = IDENTIFIER_POINTER (t);
-  if (strcmp (pname, "segment") == 0)
-    {
-      /* (should collect pbuf + 8 into a segment name) */
-    }
-  else if (strcmp (pname, "options") == 0)
-    {
-      c = getc (finput);
-      /* Skip over initial whitespace.  */
-      while (c == ' ' || c == '\t')
-       c = getc (finput);
-
-      /* Return without doing anything if no content.  */
-      if (c == '\n' || c == EOF)
-       {
-         ungetc (c, finput);
-         return 0;
-       }
-
-      /* Collect the rest of the line.  */
-      while (psize < sizeof (pbuf) - 1 && c != '\n')
-       {
-         pbuf[psize++] = c;
-         c = getc (finput);
-       }
-
-      if (strncmp (pbuf, "align=mac68k", 12) == 0)
-       {
-         mac68k_aligned = 1;
-         retval = 1;
-       }
-      else if (strncmp (pbuf, "align=power", 11) == 0)
-       {
-         mac68k_aligned = 0;
-         retval = 1;
-       }
-      else if (strncmp (pbuf, "align=reset", 11) == 0)
-       {
-         mac68k_aligned = 0;
-         retval = 1;
-       }
-    }
-
-  return retval;
-}
-/* END CYGNUS LOCAL mac */