]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
linux.h (IA64_GATE_AREA_END): Increase by 64K.
authorJakub Jelinek <jakub@redhat.com>
Fri, 12 Dec 2003 16:10:10 +0000 (17:10 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 12 Dec 2003 16:10:10 +0000 (17:10 +0100)
* config/ia64/linux.h (IA64_GATE_AREA_END): Increase by 64K.
(MD_FALLBACK_FRAME_STATE_FOR): Set fpsr_loc, br_loc[6] and
br_loc[7].  Update comment.
(MD_HANDLE_UNWABI): Define.
* config/ia64/unwind-ia64.c (struct unw_state_record): Add
unwabi field.
(struct _Unwind_Context): Increase br_loc array size to 8 entries.
(desc_abi): Set unwabi.
(uw_update_reg_address): Allow br up to 7.
(uw_update_context): Invoke MD_HANDLE_UNWABI if defined.
(uw_install_context): Load b1..b5 from correct locations.
Fix insn loading ar.fpsr.
* doc/tm.texi: Document MD_HANDLE_UNWABI.

* g++.dg/eh/ia64-1.C: New test.

From-SVN: r74574

gcc/ChangeLog
gcc/config/ia64/linux.h
gcc/config/ia64/unwind-ia64.c
gcc/doc/tm.texi
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/eh/ia64-1.C [new file with mode: 0644]

index 20f21cee0e464bf7d70645dae2d2c5e7d6e89c5b..b9a37ff7c66cf0b935b567bef04606e990e02438 100644 (file)
@@ -1,3 +1,19 @@
+2003-12-12  Jakub Jelinek  <jakub@redhat.com>
+
+       * config/ia64/linux.h (IA64_GATE_AREA_END): Increase by 64K.
+       (MD_FALLBACK_FRAME_STATE_FOR): Set fpsr_loc, br_loc[6] and
+       br_loc[7].  Update comment.
+       (MD_HANDLE_UNWABI): Define.
+       * config/ia64/unwind-ia64.c (struct unw_state_record): Add
+       unwabi field.
+       (struct _Unwind_Context): Increase br_loc array size to 8 entries.
+       (desc_abi): Set unwabi.
+       (uw_update_reg_address): Allow br up to 7.
+       (uw_update_context): Invoke MD_HANDLE_UNWABI if defined.
+       (uw_install_context): Load b1..b5 from correct locations.
+       Fix insn loading ar.fpsr.
+       * doc/tm.texi: Document MD_HANDLE_UNWABI.
+
 2003-12-12  Hans-Peter Nilsson  <hp@axis.com>
 
        PR target/13256
index e1d60f7d8c48731db4bf0ade5f6364648a6436d6..fe5b55896d37555290dadded145a712fbc48430e 100644 (file)
@@ -63,7 +63,7 @@ do {                                          \
 #include <sys/ucontext.h>
 
 #define IA64_GATE_AREA_START 0xa000000000000100LL
-#define IA64_GATE_AREA_END   0xa000000000020000LL
+#define IA64_GATE_AREA_END   0xa000000000030000LL
 
 #define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS)              \
   if ((CONTEXT)->rp >= IA64_GATE_AREA_START                            \
@@ -90,10 +90,13 @@ do {                                                \
          (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_];                \
       }                                                                        \
                                                                        \
+      (CONTEXT)->fpsr_loc = &(sc_->sc_ar_fpsr);                                \
       (CONTEXT)->pfs_loc = &(sc_->sc_ar_pfs);                          \
       (CONTEXT)->lc_loc = &(sc_->sc_ar_lc);                            \
       (CONTEXT)->unat_loc = &(sc_->sc_ar_unat);                                \
       (CONTEXT)->br_loc[0] = &(sc_->sc_br[0]);                         \
+      (CONTEXT)->br_loc[6] = &(sc_->sc_br[6]);                         \
+      (CONTEXT)->br_loc[7] = &(sc_->sc_br[7]);                         \
       (CONTEXT)->bsp = sc_->sc_ar_bsp;                                 \
       (CONTEXT)->pr = sc_->sc_pr;                                      \
       (CONTEXT)->psp = sc_->sc_gr[12];                                 \
@@ -102,11 +105,10 @@ do {                                              \
          other than what we adjust for below.    */                    \
       (FS) -> no_reg_stack_frame = 1;                                  \
                                                                        \
-      /* Don't touch the branch registers o.t. b0.  The kernel doesn't \
-        pass the preserved branch registers in the sigcontext but      \
-        leaves them intact, so there's no need to do anything          \
-        with them here.  */                                            \
-                                                                       \
+      /* Don't touch the branch registers o.t. b0, b6 and b7.          \
+        The kernel doesn't pass the preserved branch registers         \
+        in the sigcontext but leaves them intact, so there's no        \
+        need to do anything with them here.  */                        \
       {                                                                        \
        unsigned long sof = sc_->sc_cfm & 0x7f;                         \
        (CONTEXT)->bsp = (unsigned long)                                \
@@ -120,4 +122,58 @@ do {                                               \
                                                                        \
       goto SUCCESS;                                                    \
     }
+
+#define MD_HANDLE_UNWABI(CONTEXT, FS)                                  \
+  if ((FS)->unwabi == ((3 << 8) | 's')                                 \
+      || (FS)->unwabi == ((0 << 8) | 's'))                             \
+    {                                                                  \
+      struct sigframe {                                                        \
+       char scratch[16];                                               \
+       unsigned long sig_number;                                       \
+       struct siginfo *info;                                           \
+       struct sigcontext *sc;                                          \
+      } *frame_ = (struct sigframe *)(CONTEXT)->psp;                   \
+      struct sigcontext *sc_ = frame_->sc;                             \
+                                                                       \
+      /* Restore scratch registers in case the unwinder needs to       \
+        refer to a value stored in one of them.  */                    \
+      {                                                                        \
+       int i_;                                                         \
+                                                                       \
+       for (i_ = 2; i_ < 4; i_++)                                      \
+         (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_];                \
+       for (i_ = 8; i_ < 12; i_++)                                     \
+         (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_];                \
+       for (i_ = 14; i_ < 32; i_++)                                    \
+         (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_];                \
+      }                                                                        \
+                                                                       \
+      (CONTEXT)->pfs_loc = &(sc_->sc_ar_pfs);                          \
+      (CONTEXT)->lc_loc = &(sc_->sc_ar_lc);                            \
+      (CONTEXT)->unat_loc = &(sc_->sc_ar_unat);                                \
+      (CONTEXT)->br_loc[0] = &(sc_->sc_br[0]);                         \
+      (CONTEXT)->br_loc[6] = &(sc_->sc_br[6]);                         \
+      (CONTEXT)->br_loc[7] = &(sc_->sc_br[7]);                         \
+      (CONTEXT)->bsp = sc_->sc_ar_bsp;                                 \
+      (CONTEXT)->pr = sc_->sc_pr;                                      \
+      (CONTEXT)->gp = sc_->sc_gr[1];                                   \
+      /* Signal frame doesn't have an associated reg. stack frame      \
+         other than what we adjust for below.    */                    \
+      (FS) -> no_reg_stack_frame = 1;                                  \
+                                                                       \
+      /* Don't touch the branch registers o.t. b0, b6 and b7.          \
+        The kernel doesn't pass the preserved branch registers         \
+        in the sigcontext but leaves them intact, so there's no        \
+        need to do anything with them here.  */                        \
+      {                                                                        \
+       unsigned long sof = sc_->sc_cfm & 0x7f;                         \
+       (CONTEXT)->bsp = (unsigned long)                                \
+         ia64_rse_skip_regs ((unsigned long *)(sc_->sc_ar_bsp), -sof); \
+      }                                                                        \
+                                                                       \
+      /* pfs_loc already set above.  Without this pfs_loc would point  \
+        incorrectly to sc_cfm instead of sc_ar_pfs.  */                \
+      (FS)->curr.reg[UNW_REG_PFS].where = UNW_WHERE_NONE;              \
+    }
+
 #endif /* IN_LIBGCC2 */
index 88d236b141cd3398ae4a7b52a74497fe02356038..9142c831e7fa4d5875e0296c5c2a1269c7ab5d7a 100644 (file)
@@ -155,6 +155,7 @@ typedef struct unw_state_record
 
   unsigned char gr_save_loc;   /* next general register to use for saving */
   unsigned char return_link_reg; /* branch register for return link */
+  unsigned short unwabi;
 
   struct unw_labeled_state *labeled_states;    /* list of all labeled states */
   struct unw_reg_state curr;   /* current state */
@@ -219,7 +220,7 @@ struct _Unwind_Context
     } nat;
   } ireg[32 - 2];      /* Indexed by <register number> - 2 */
 
-  unsigned long *br_loc[7];
+  unsigned long *br_loc[8];
   void *fr_loc[32 - 2];
 
   /* ??? We initially point pri_unat_loc here.  The entire NAT bit
@@ -619,11 +620,11 @@ desc_prologue (int body, unw_word rlen, unsigned char mask,
  */
 
 static inline void
-desc_abi (unsigned char abi __attribute__((unused)),
-         unsigned char context __attribute__((unused)),
-         struct unw_state_record *sr __attribute__((unused)))
+desc_abi (unsigned char abi,
+         unsigned char context,
+         struct unw_state_record *sr)
 {
-  /* Anything to do?  */
+  sr->unwabi = (abi << 8) | context;
 }
 
 static inline void
@@ -1812,9 +1813,9 @@ uw_update_reg_address (struct _Unwind_Context *context,
 
     case UNW_WHERE_BR:
       /* Note that while RVAL can only be 1-5 from normal descriptors,
-        we can want to look at B0 due to having manually unwound a
+        we can want to look at B0, B6 and B7 due to having manually unwound a
         signal frame.  */
-      if (rval <= 5)
+      if (rval < 8)
        addr = context->br_loc[rval];
       else
        abort ();
@@ -1928,6 +1929,10 @@ uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
 {
   long i;
 
+#ifdef MD_HANDLE_UNWABI
+  MD_HANDLE_UNWABI (context, fs);
+#endif
+
   context->sp = context->psp;
 
   /* First, set PSP.  Subsequent instructions may depend on this value.  */
@@ -2079,22 +2084,22 @@ uw_install_context (struct _Unwind_Context *current __attribute__((unused)),
        ";;                                     \n\t"
        "(p6) ld8.fill r4 = [%1]                \n\t"
        "(p7) ld8.fill r5 = [r20]               \n\t"
-       "add r21 = uc_br_loc + 8, %0            \n\t"
+       "add r21 = uc_br_loc + 16, %0           \n\t"
        "adds %1 = 16, %1                       \n\t"
        "adds r20 = 16, r20                     \n\t"
        ";;                                     \n\t"
        "(p8) ld8.fill r6 = [%1]                \n\t"
        "(p9) ld8.fill r7 = [r20]               \n\t"
-       "add r20 = uc_br_loc, %0                \n\t"
+       "add r20 = uc_br_loc + 8, %0            \n\t"
        ";;                                     \n\t"
        /* Load up call-saved branch registers.  */
        "ld8 r22 = [r20], 16                    \n\t"
        "ld8 r23 = [r21], 16                    \n\t"
        ";;                                     \n\t"
        "ld8 r24 = [r20], 16                    \n\t"
-       "ld8 r25 = [r21], uc_fr_loc - (uc_br_loc + 24)\n\t"
+       "ld8 r25 = [r21], uc_fr_loc - (uc_br_loc + 32)\n\t"
        ";;                                     \n\t"
-       "ld8 r26 = [r20], uc_fr_loc + 8 - (uc_br_loc + 32)\n\t"
+       "ld8 r26 = [r20], uc_fr_loc + 8 - (uc_br_loc + 40)\n\t"
        "ld8 r27 = [r21], 24                    \n\t"
        "cmp.ne p6, p0 = r0, r22                \n\t"
        ";;                                     \n\t"
@@ -2242,7 +2247,7 @@ uw_install_context (struct _Unwind_Context *current __attribute__((unused)),
        "(p9) mov.i ar.lc = r29                 \n\t"
        ";;                                     \n\t"
        "mov.m r25 = ar.rsc                     \n\t"
-       "(p6) mov.i ar.fpsr = r30               \n\t"
+       "(p6) mov.m ar.fpsr = r30               \n\t"
        ";;                                     \n\t"
        "and r25 = 0x1c, r25                    \n\t"
        "mov b0 = r26                           \n\t"
index 9a7117344ac0a8164bcb0618b1934da80955c18b..2c097012f4b9c63f1cb482ebf0472e44a5d9eb4e 100644 (file)
@@ -2969,6 +2969,19 @@ the stack pointer value.  If the frame can be decoded, the register save
 addresses should be updated in @var{fs} and the macro should branch to
 @var{success}.  If the frame cannot be decoded, the macro should do
 nothing.
+
+@findex MD_HANDLE_UNWABI
+@item MD_HANDLE_UNWABI(@var{context}, @var{fs})
+This macro allows the target to add operating system specific code to the
+call-frame unwinder to handle the IA-64 @code{.unwabi} unwinding directive,
+usually used for signal or interrupt frames.
+
+This macro is called from @code{uw_update_context} in @file{unwind-ia64.c}.
+@var{context} is an @code{_Unwind_Context};
+@var{fs} is an @code{_Unwind_FrameState}.  Examine @code{fs->unwabi}
+for the abi and context in the @code{.unwabi} directive.  If the
+@code{.unwabi} directive can be handled, the register save addresses should
+be updated in @var{fs}.
 @end table
 
 @node Stack Checking
index aa578ecff26f93faf6ff5adc2bf9c0b2b0adb877..8f8ab9a0b5a6a7009f68e97508bf7baf29c50ee8 100644 (file)
@@ -1,3 +1,7 @@
+2003-12-12  Jakub Jelinek  <jakub@redhat.com>
+
+       * g++.dg/eh/ia64-1.C: New test.
+
 2003-12-12  Hans-Peter Nilsson  <hp@axis.com>
 
        PR target/13256
diff --git a/gcc/testsuite/g++.dg/eh/ia64-1.C b/gcc/testsuite/g++.dg/eh/ia64-1.C
new file mode 100644 (file)
index 0000000..a1b731c
--- /dev/null
@@ -0,0 +1,50 @@
+// Test whether call saved float and branch regs are restored properly
+// { dg-do run { target ia64-*-* } }
+// { dg-options "-O2" }
+
+extern "C" void abort (void);
+
+char buf[128];
+
+void __attribute__((noinline))
+bar (void)
+{
+  throw 1;
+}
+
+void __attribute__((noinline))
+foo (void)
+{
+  bar ();
+  bar ();
+}
+
+int
+main (void)
+{
+  register double f2 __asm ("f2");
+  register double f3 __asm ("f3");
+  register double f4 __asm ("f4");
+  register double f5 __asm ("f5");
+  register double f16 __asm ("f16");
+  register double f17 __asm ("f17");
+  register void *b1 __asm ("b1");
+  register void *b2 __asm ("b2");
+  register void *b3 __asm ("b3");
+  register void *b4 __asm ("b4");
+  register void *b5 __asm ("b5");
+  f2 = 12.0; f3 = 13.0; f4 = 14.0; f5 = 15.0; f16 = 16.0; f17 = 17.0;
+  b1 = &buf[1]; b2 = &buf[2]; b3 = &buf[3]; b4 = &buf[4]; b5 = &buf[5];
+  try
+    {
+      foo ();
+    }
+  catch (...) {}
+  if (f2 != 12.0 || f3 != 13.0 || f4 != 14.0
+      || f5 != 15.0 || f16 != 16.0 || f17 != 17.0)
+    abort ();
+  if (b1 != &buf[1] || b2 != &buf[2] || b3 != &buf[3]
+      || b4 != &buf[4] || b5 != &buf[5])
+    abort ();
+  return 0;
+}