diff options
author | Jakub Jelinek <jakub@redhat.com> | 2003-12-12 17:45:51 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2003-12-12 17:45:51 +0100 |
commit | 3950dcdfccd66e077b1be064826aac76122f4bb4 (patch) | |
tree | 7cf80b3f7b176478613482e7bd4d3ba7eec2bfe3 /gcc | |
parent | 3075b32758eafbf3cb6dadb9225d28bb2b6abfab (diff) | |
download | gcc-3950dcdfccd66e077b1be064826aac76122f4bb4.zip gcc-3950dcdfccd66e077b1be064826aac76122f4bb4.tar.gz gcc-3950dcdfccd66e077b1be064826aac76122f4bb4.tar.bz2 |
linux.h (IA64_GATE_AREA_END): Increase by 64K.
* 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: r74575
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/config/ia64/linux.h | 68 | ||||
-rw-r--r-- | gcc/config/ia64/unwind-ia64.c | 29 | ||||
-rw-r--r-- | gcc/doc/tm.texi | 13 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/eh/ia64-1.C | 50 |
6 files changed, 162 insertions, 18 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 56fb00f..1cb5de2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 Roger Sayle <roger@eyesopen.com> PR optimization/13037 diff --git a/gcc/config/ia64/linux.h b/gcc/config/ia64/linux.h index 460dd26..d456ea5 100644 --- a/gcc/config/ia64/linux.h +++ b/gcc/config/ia64/linux.h @@ -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 */ diff --git a/gcc/config/ia64/unwind-ia64.c b/gcc/config/ia64/unwind-ia64.c index 41f59d1..4de3263 100644 --- a/gcc/config/ia64/unwind-ia64.c +++ b/gcc/config/ia64/unwind-ia64.c @@ -157,6 +157,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 */ @@ -221,7 +222,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 @@ -621,11 +622,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 @@ -1814,9 +1815,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 (); @@ -1930,6 +1931,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. */ @@ -2081,22 +2086,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" @@ -2244,7 +2249,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" diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index e560412..5075a4c 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -3052,6 +3052,19 @@ For proper signal handling in Java this macro is accompanied by @code{MAKE_THROW_FRAME}, defined in @file{libjava/include/*-signal.h} headers. @end defmac +@defmac 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 defmac + @node Stack Checking @subsection Specifying How Stack Checking is Done diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f206b50..62c363e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2003-12-12 Jakub Jelinek <jakub@redhat.com> + + * g++.dg/eh/ia64-1.C: New test. + 2003-12-12 Roger Sayle <roger@eyesopen.com> PR optimization/13037 diff --git a/gcc/testsuite/g++.dg/eh/ia64-1.C b/gcc/testsuite/g++.dg/eh/ia64-1.C new file mode 100644 index 0000000..a1b731c --- /dev/null +++ b/gcc/testsuite/g++.dg/eh/ia64-1.C @@ -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; +} |