PR target/45807
authoramodra <amodra@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 28 Sep 2010 15:25:03 +0000 (15:25 +0000)
committeramodra <amodra@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 28 Sep 2010 15:25:03 +0000 (15:25 +0000)
* config/rs6000/aix.h (SETUP_FRAME_ADDRESSES): Delete.
* config/rs6000/linux64.h (SETUP_FRAME_ADDRESSES): Delete.
* config/rs6000/rs6000-protos.h (rs6000_aix_emit_builtin_unwind_init):
Delete.
* config/rs6000/rs6000.c (rs6000_aix_emit_builtin_unwind_init): Delete.
(rs6000_emit_prologue): Don't just create frame save info for r2,
actually save r2.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@164685 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/rs6000/aix.h
gcc/config/rs6000/linux64.h
gcc/config/rs6000/rs6000-protos.h
gcc/config/rs6000/rs6000.c

index 157ce82..a176a7a 100644 (file)
@@ -1,3 +1,14 @@
+2010-09-29  Alan Modra  <amodra@gmail.com>
+
+       PR target/45807
+       * config/rs6000/aix.h (SETUP_FRAME_ADDRESSES): Delete.
+       * config/rs6000/linux64.h (SETUP_FRAME_ADDRESSES): Delete.
+       * config/rs6000/rs6000-protos.h (rs6000_aix_emit_builtin_unwind_init):
+       Delete.
+       * config/rs6000/rs6000.c (rs6000_aix_emit_builtin_unwind_init): Delete.
+       (rs6000_emit_prologue): Don't just create frame save info for r2,
+       actually save r2.
+
 2010-09-28  Richard Henderson  <rth@redhat.com>
 
        * config/i386/cygming.h (ASM_OUTPUT_DWARF_OFFSET): Output 8 bytes
index 0bf781e..f9004b4 100644 (file)
 /* And similarly for general purpose registers.  */
 #define GP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) < 32)
 
-/* __throw will restore its own return address to be the same as the
-   return address of the function that the throw is being made to.
-   This is unfortunate, because we want to check the original
-   return address to see if we need to restore the TOC.
-   So we have to squirrel it away with this.  */
-#define SETUP_FRAME_ADDRESSES() rs6000_aix_emit_builtin_unwind_init ()
-
 /* If the current unwind info (FS) does not contain explicit info
    saving R2, then we have to do a minor amount of code reading to
    figure out if it was saved.  The big problem here is that the
index 62eed2e..b233261 100644 (file)
@@ -305,14 +305,6 @@ extern enum rs6000_cmodel cmodel;
 #define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
   (!(FIRST) ? upward : FUNCTION_ARG_PADDING (MODE, TYPE))
 
-/* __throw will restore its own return address to be the same as the
-   return address of the function that the throw is being made to.
-   This is unfortunate, because we want to check the original
-   return address to see if we need to restore the TOC.
-   So we have to squirrel it away with this.  */
-#define SETUP_FRAME_ADDRESSES() \
-  do { if (TARGET_64BIT) rs6000_aix_emit_builtin_unwind_init (); } while (0)
-
 /* Override svr4.h  */
 #undef MD_EXEC_PREFIX
 #undef MD_STARTFILE_PREFIX
index a5e055e..0678fc0 100644 (file)
@@ -163,7 +163,6 @@ extern int rs6000_trampoline_size (void);
 extern alias_set_type get_TOC_alias_set (void);
 extern void rs6000_emit_prologue (void);
 extern void rs6000_emit_load_toc_table (int);
-extern void rs6000_aix_emit_builtin_unwind_init (void);
 extern unsigned int rs6000_dbx_register_number (unsigned int);
 extern void rs6000_emit_epilogue (int);
 extern void rs6000_emit_eh_reg_restore (rtx, rtx);
index 5a3e333..6399cab 100644 (file)
@@ -18916,42 +18916,6 @@ rs6000_aix_asm_output_dwarf_table_ref (char * frame_table_label)
   fprintf (asm_out_file, "\t.ref %s\n",
           TARGET_STRIP_NAME_ENCODING (frame_table_label));
 }
-
-/* If _Unwind_* has been called from within the same module,
-   toc register is not guaranteed to be saved to 40(1) on function
-   entry.  Save it there in that case.  */
-
-void
-rs6000_aix_emit_builtin_unwind_init (void)
-{
-  rtx mem;
-  rtx stack_top = gen_reg_rtx (Pmode);
-  rtx opcode_addr = gen_reg_rtx (Pmode);
-  rtx opcode = gen_reg_rtx (SImode);
-  rtx tocompare = gen_reg_rtx (SImode);
-  rtx no_toc_save_needed = gen_label_rtx ();
-
-  mem = gen_frame_mem (Pmode, hard_frame_pointer_rtx);
-  emit_move_insn (stack_top, mem);
-
-  mem = gen_frame_mem (Pmode,
-                      gen_rtx_PLUS (Pmode, stack_top,
-                                    GEN_INT (2 * GET_MODE_SIZE (Pmode))));
-  emit_move_insn (opcode_addr, mem);
-  emit_move_insn (opcode, gen_rtx_MEM (SImode, opcode_addr));
-  emit_move_insn (tocompare, gen_int_mode (TARGET_32BIT ? 0x80410014
-                                          : 0xE8410028, SImode));
-
-  do_compare_rtx_and_jump (opcode, tocompare, EQ, 1,
-                          SImode, NULL_RTX, NULL_RTX,
-                          no_toc_save_needed, -1);
-
-  mem = gen_frame_mem (Pmode,
-                      gen_rtx_PLUS (Pmode, stack_top,
-                                    GEN_INT (5 * GET_MODE_SIZE (Pmode))));
-  emit_move_insn (mem, gen_rtx_REG (Pmode, 2));
-  emit_label (no_toc_save_needed);
-}
 \f
 /* This ties together stack memory (MEM with an alias set of frame_alias_set)
    and the change to the stack pointer.  */
@@ -20237,22 +20201,6 @@ rs6000_emit_prologue (void)
     {
       unsigned int i, regno;
 
-      /* In AIX ABI we need to pretend we save r2 here.  */
-      if (TARGET_AIX)
-       {
-         rtx addr, reg, mem;
-
-         reg = gen_rtx_REG (reg_mode, 2);
-         addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
-                              GEN_INT (sp_offset + 5 * reg_size));
-         mem = gen_frame_mem (reg_mode, addr);
-
-         insn = emit_move_insn (mem, reg);
-         rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
-                               NULL_RTX, NULL_RTX);
-         PATTERN (insn) = gen_blockage ();
-       }
-
       for (i = 0; ; ++i)
        {
          regno = EH_RETURN_DATA_REGNO (i);
@@ -20266,6 +20214,53 @@ rs6000_emit_prologue (void)
        }
     }
 
+  /* In AIX ABI we need to make sure r2 is really saved.  */
+  if (TARGET_AIX && crtl->calls_eh_return)
+    {
+      rtx tmp_reg, tmp_reg_si, compare_result, toc_save_done, jump;
+      long toc_restore_insn;
+
+      gcc_assert (frame_reg_rtx == frame_ptr_rtx
+                 || frame_reg_rtx == sp_reg_rtx);
+      tmp_reg = gen_rtx_REG (Pmode, 11);
+      tmp_reg_si = gen_rtx_REG (SImode, 11);
+      if (using_static_chain_p)
+       emit_move_insn (gen_rtx_REG (Pmode, 0), tmp_reg);
+      gcc_assert (saving_GPRs_inline && saving_FPRs_inline);
+      emit_move_insn (tmp_reg, gen_rtx_REG (Pmode, LR_REGNO));
+      /* Peek at instruction to which this function returns.  If it's
+        restoring r2, then we know we've already saved r2.  We can't
+        unconditionally save r2 because the value we have will already
+        be updated if we arrived at this function via a plt call or
+        toc adjusting stub.  */
+      emit_move_insn (tmp_reg_si, gen_rtx_MEM (SImode, tmp_reg));
+      toc_restore_insn = ((TARGET_32BIT ? 0x80410014 : 0xE8410028)
+                         ^ 0x80000000) - 0x80000000;
+      emit_insn (gen_xorsi3 (tmp_reg_si, tmp_reg_si,
+                            GEN_INT (toc_restore_insn & ~0xffff)));
+      compare_result = gen_rtx_REG (CCUNSmode, CR0_REGNO);
+      validate_condition_mode (EQ, CCUNSmode);
+      emit_insn (gen_rtx_SET (VOIDmode, compare_result,
+                             gen_rtx_COMPARE (CCUNSmode, tmp_reg_si,
+                                              GEN_INT (toc_restore_insn
+                                                       & 0xffff))));
+      toc_save_done = gen_label_rtx ();
+      jump = gen_rtx_IF_THEN_ELSE (VOIDmode,
+                                  gen_rtx_EQ (VOIDmode, compare_result,
+                                              const0_rtx),
+                                  gen_rtx_LABEL_REF (VOIDmode, toc_save_done),
+                                  pc_rtx);
+      jump = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, jump));
+      JUMP_LABEL (jump) = toc_save_done;
+      LABEL_NUSES (toc_save_done) += 1;
+
+      emit_frame_save (frame_reg_rtx, frame_ptr_rtx, reg_mode, 2,
+                      sp_offset + 5 * reg_size, info->total_size);
+      emit_label (toc_save_done);
+      if (using_static_chain_p)
+       emit_move_insn (tmp_reg, gen_rtx_REG (Pmode, 0));
+    }
+
   /* Save CR if we use any that must be preserved.  */
   if (!WORLD_SAVE_P (info) && info->cr_save_p)
     {