OSDN Git Service

* config/alpha/alpha.c (alpha_sa_mask): Add EH_RETURN_DATA_REGNOs.
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 28 Mar 2001 11:09:20 +0000 (11:09 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 28 Mar 2001 11:09:20 +0000 (11:09 +0000)
        (alpha_mark_machine_status): No eh_epilogue_sp_ofs ...
        (alpha_expand_epilogue): ... use EH_RETURN_STACKADJ_RTX instead.
        * config/alpha/alpha.h (machine_function): Remove eh_epilogue_sp_ofs.
        (EH_RETURN_DATA_REGNO): New.
        (EH_RETURN_STACKADJ_RTX, EH_RETURN_HANDLER_RTX): New.
        * config/alpha/alpha.md (eh_epilogue): Remove.
        (exception_receiver): Use $26 for ldgp input.
        * config/alpha/linux.h (MD_FALLBACK_FRAME_STATE_FOR): New.

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

gcc/ChangeLog
gcc/config/alpha/alpha.c
gcc/config/alpha/alpha.h
gcc/config/alpha/alpha.md
gcc/config/alpha/linux.h

index deb12a5..66122d4 100644 (file)
@@ -1,5 +1,17 @@
 2001-03-28  Richard Henderson  <rth@redhat.com>
 
+        * config/alpha/alpha.c (alpha_sa_mask): Add EH_RETURN_DATA_REGNOs.
+        (alpha_mark_machine_status): No eh_epilogue_sp_ofs ...
+        (alpha_expand_epilogue): ... use EH_RETURN_STACKADJ_RTX instead.
+        * config/alpha/alpha.h (machine_function): Remove eh_epilogue_sp_ofs.
+        (EH_RETURN_DATA_REGNO): New.
+        (EH_RETURN_STACKADJ_RTX, EH_RETURN_HANDLER_RTX): New.
+        * config/alpha/alpha.md (eh_epilogue): Remove.
+        (exception_receiver): Use $26 for ldgp input.
+       * config/alpha/linux.h (MD_FALLBACK_FRAME_STATE_FOR): New.
+
+2001-03-28  Richard Henderson  <rth@redhat.com>
+
        * except.c: Rewrite entirely for IA-64 ABI exception handling.
        * except.h: Likewise.
 
index 997fb36..18a61d6 100644 (file)
@@ -3664,7 +3664,6 @@ alpha_mark_machine_status (p)
 
   if (machine)
     {
-      ggc_mark_rtx (machine->eh_epilogue_sp_ofs);
       ggc_mark_rtx (machine->ra_rtx);
     }
 }
@@ -4416,6 +4415,18 @@ alpha_sa_mask (imaskP, fmaskP)
              fmask |= (1L << (i - 32));
          }
 
+      /* We need to restore these for the handler.  */
+      if (current_function_calls_eh_return)
+       {
+         for (i = 0; ; ++i)
+           {
+             unsigned regno = EH_RETURN_DATA_REGNO (i);
+             if (regno == INVALID_REGNUM)
+               break;
+             imask |= 1L << regno;
+           }
+       }
+
       if (imask || fmask || alpha_ra_ever_killed ())
        imask |= (1L << REG_RA);
     }
@@ -5112,7 +5123,11 @@ alpha_expand_epilogue ()
   fp_offset = 0;
   sa_reg = stack_pointer_rtx;
 
-  eh_ofs = cfun->machine->eh_epilogue_sp_ofs;
+  if (current_function_calls_eh_return)
+    eh_ofs = EH_RETURN_STACKADJ_RTX;
+  else
+    eh_ofs = NULL_RTX;
+
   if (sa_size)
     {
       /* If we have a frame pointer, restore SP from it.  */
@@ -5140,12 +5155,11 @@ alpha_expand_epilogue ()
          
       /* Restore registers in order, excepting a true frame pointer. */
 
+      mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset));
       if (! eh_ofs)
-       {
-         mem = gen_rtx_MEM (DImode, plus_constant(sa_reg, reg_offset));
-         MEM_ALIAS_SET (mem) = alpha_sr_alias_set;
-          FRP (emit_move_insn (gen_rtx_REG (DImode, REG_RA), mem));
-       }
+        MEM_ALIAS_SET (mem) = alpha_sr_alias_set;
+      FRP (emit_move_insn (gen_rtx_REG (DImode, REG_RA), mem));
+
       reg_offset += 8;
       imask &= ~(1L << REG_RA);
 
index dc2a1ec..7d4c194 100644 (file)
@@ -1213,9 +1213,6 @@ extern struct alpha_compare alpha_compare;
 
 struct machine_function
 {
-  /* An offset to apply to the stack pointer when unwinding from EH.  */
-  struct rtx_def *eh_epilogue_sp_ofs;
-
   /* If non-null, this rtx holds the return address for the function.  */
   struct rtx_def *ra_rtx;
 };
@@ -1342,6 +1339,13 @@ do {                                             \
 /* Before the prologue, RA lives in $26. */
 #define INCOMING_RETURN_ADDR_RTX  gen_rtx_REG (Pmode, 26)
 #define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (26)
+
+/* Describe how we implement __builtin_eh_return.  */
+#define EH_RETURN_DATA_REGNO(N)        ((N) < 4 ? (N) + 16 : INVALID_REGNUM)
+#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, 28)
+#define EH_RETURN_HANDLER_RTX \
+  gen_rtx_MEM (Pmode, plus_constant (stack_pointer_rtx, \
+                                    current_function_outgoing_args_size))
 \f
 /* Addressing modes, and classification of registers for them.  */
 
index 01462c9..3460d42 100644 (file)
   DONE;
 }")
 
-(define_expand "eh_epilogue"
-  [(use (match_operand:DI 0 "register_operand" "r"))
-   (use (match_operand:DI 1 "register_operand" "r"))
-   (use (match_operand:DI 2 "register_operand" "r"))]
-  "! TARGET_OPEN_VMS"
-  "
-{
-  cfun->machine->eh_epilogue_sp_ofs = operands[1];
-  if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 26)
-    {
-      rtx ra = gen_rtx_REG (Pmode, 26);
-      emit_move_insn (ra, operands[2]);
-      operands[2] = ra;
-    }
-}")
-
 ;; In creating a large stack frame, NT _must_ use ldah+lda to load
 ;; the frame size into a register.  We use this pattern to ensure
 ;; we get lda instead of addq.
 (define_insn "exception_receiver"
   [(unspec_volatile [(const_int 0)] 7)]
   "! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT"
-  "br $29,$LSJ%=\\n$LSJ%=:\;ldgp $29,0($29)"
-  [(set_attr "length" "12")
+  "ldgp $29,0($26)"
+  [(set_attr "length" "8")
    (set_attr "type" "multi")])
 
 (define_expand "nonlocal_goto_receiver"
index c8f649a..1be967e 100644 (file)
@@ -44,3 +44,54 @@ SUB_CPP_PREDEFINES
 
 /* Define this so that all GNU/Linux targets handle the same pragmas.  */
 #define HANDLE_PRAGMA_PACK_PUSH_POP
+
+/* Do code reading to identify a signal frame, and set the frame
+   state data appropriately.  See unwind-dw2.c for the structs.  */
+
+#ifdef IN_LIBGCC2
+#include <signal.h>
+#include <sys/ucontext.h>
+#endif
+
+#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS)              \
+  do {                                                                 \
+    unsigned int *pc_ = (CONTEXT)->ra;                                 \
+    struct sigcontext *sc_;                                            \
+    long new_cfa_, i_;                                                 \
+                                                                       \
+    if (pc_[0] != 0x47fe0410           /* mov $30,$16 */               \
+        || pc_[2] != 0x00000083                /* callsys */)                  \
+      break;                                                           \
+    if (pc_[1] == 0x201f0067)          /* lda $0,NR_sigreturn */       \
+      sc_ = (CONTEXT)->cfa;                                            \
+    else if (pc_[1] == 0x201f015f)     /* lda $0,NR_rt_sigreturn */    \
+      {                                                                        \
+       struct rt_sigframe {                                            \
+         struct siginfo info;                                          \
+         struct ucontext uc;                                           \
+       } *rt_ = (CONTEXT)->cfa;                                        \
+       sc_ = &rt_->uc.uc_mcontext;                                     \
+      }                                                                        \
+    else                                                               \
+      break;                                                           \
+    new_cfa_ = sc_->sc_regs[30];                                       \
+    (FS)->cfa_how = CFA_REG_OFFSET;                                    \
+    (FS)->cfa_reg = 30;                                                        \
+    (FS)->cfa_offset = new_cfa_ - (long) (CONTEXT)->cfa;               \
+    for (i_ = 0; i_ < 30; ++i_)                                                \
+      {                                                                        \
+       (FS)->regs.reg[i_].how = REG_SAVED_OFFSET;                      \
+       (FS)->regs.reg[i_].loc.offset                                   \
+         = (long)&sc_->sc_regs[i_] - new_cfa_;                         \
+      }                                                                        \
+    for (i_ = 0; i_ < 31; ++i_)                                                \
+      {                                                                        \
+       (FS)->regs.reg[i_+32].how = REG_SAVED_OFFSET;                   \
+       (FS)->regs.reg[i_+32].loc.offset                                \
+         = (long)&sc_->sc_fpregs[i_] - new_cfa_;                       \
+      }                                                                        \
+    (FS)->regs.reg[31].how = REG_SAVED_OFFSET;                         \
+    (FS)->regs.reg[31].loc.offset = (long)&sc_->sc_pc - new_cfa_;      \
+    (FS)->retaddr_column = 31;                                         \
+    goto SUCCESS;                                                      \
+  } while (0)