Commit 3950dcdf by Jakub Jelinek Committed by Jakub Jelinek

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
parent 3075b327
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> 2003-12-12 Roger Sayle <roger@eyesopen.com>
PR optimization/13037 PR optimization/13037
......
...@@ -63,7 +63,7 @@ do { \ ...@@ -63,7 +63,7 @@ do { \
#include <sys/ucontext.h> #include <sys/ucontext.h>
#define IA64_GATE_AREA_START 0xa000000000000100LL #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) \ #define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
if ((CONTEXT)->rp >= IA64_GATE_AREA_START \ if ((CONTEXT)->rp >= IA64_GATE_AREA_START \
...@@ -90,10 +90,13 @@ do { \ ...@@ -90,10 +90,13 @@ do { \
(CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_]; \ (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_]; \
} \ } \
\ \
(CONTEXT)->fpsr_loc = &(sc_->sc_ar_fpsr); \
(CONTEXT)->pfs_loc = &(sc_->sc_ar_pfs); \ (CONTEXT)->pfs_loc = &(sc_->sc_ar_pfs); \
(CONTEXT)->lc_loc = &(sc_->sc_ar_lc); \ (CONTEXT)->lc_loc = &(sc_->sc_ar_lc); \
(CONTEXT)->unat_loc = &(sc_->sc_ar_unat); \ (CONTEXT)->unat_loc = &(sc_->sc_ar_unat); \
(CONTEXT)->br_loc[0] = &(sc_->sc_br[0]); \ (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)->bsp = sc_->sc_ar_bsp; \
(CONTEXT)->pr = sc_->sc_pr; \ (CONTEXT)->pr = sc_->sc_pr; \
(CONTEXT)->psp = sc_->sc_gr[12]; \ (CONTEXT)->psp = sc_->sc_gr[12]; \
...@@ -102,11 +105,10 @@ do { \ ...@@ -102,11 +105,10 @@ do { \
other than what we adjust for below. */ \ other than what we adjust for below. */ \
(FS) -> no_reg_stack_frame = 1; \ (FS) -> no_reg_stack_frame = 1; \
\ \
/* Don't touch the branch registers o.t. b0. The kernel doesn't \ /* Don't touch the branch registers o.t. b0, b6 and b7. \
pass the preserved branch registers in the sigcontext but \ The kernel doesn't pass the preserved branch registers \
leaves them intact, so there's no need to do anything \ in the sigcontext but leaves them intact, so there's no \
with them here. */ \ need to do anything with them here. */ \
\
{ \ { \
unsigned long sof = sc_->sc_cfm & 0x7f; \ unsigned long sof = sc_->sc_cfm & 0x7f; \
(CONTEXT)->bsp = (unsigned long) \ (CONTEXT)->bsp = (unsigned long) \
...@@ -120,4 +122,58 @@ do { \ ...@@ -120,4 +122,58 @@ do { \
\ \
goto SUCCESS; \ 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 */ #endif /* IN_LIBGCC2 */
...@@ -157,6 +157,7 @@ typedef struct unw_state_record ...@@ -157,6 +157,7 @@ typedef struct unw_state_record
unsigned char gr_save_loc; /* next general register to use for saving */ unsigned char gr_save_loc; /* next general register to use for saving */
unsigned char return_link_reg; /* branch register for return link */ 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_labeled_state *labeled_states; /* list of all labeled states */
struct unw_reg_state curr; /* current state */ struct unw_reg_state curr; /* current state */
...@@ -221,7 +222,7 @@ struct _Unwind_Context ...@@ -221,7 +222,7 @@ struct _Unwind_Context
} nat; } nat;
} ireg[32 - 2]; /* Indexed by <register number> - 2 */ } ireg[32 - 2]; /* Indexed by <register number> - 2 */
unsigned long *br_loc[7]; unsigned long *br_loc[8];
void *fr_loc[32 - 2]; void *fr_loc[32 - 2];
/* ??? We initially point pri_unat_loc here. The entire NAT bit /* ??? 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, ...@@ -621,11 +622,11 @@ desc_prologue (int body, unw_word rlen, unsigned char mask,
*/ */
static inline void static inline void
desc_abi (unsigned char abi __attribute__((unused)), desc_abi (unsigned char abi,
unsigned char context __attribute__((unused)), unsigned char context,
struct unw_state_record *sr __attribute__((unused))) struct unw_state_record *sr)
{ {
/* Anything to do? */ sr->unwabi = (abi << 8) | context;
} }
static inline void static inline void
...@@ -1814,9 +1815,9 @@ uw_update_reg_address (struct _Unwind_Context *context, ...@@ -1814,9 +1815,9 @@ uw_update_reg_address (struct _Unwind_Context *context,
case UNW_WHERE_BR: case UNW_WHERE_BR:
/* Note that while RVAL can only be 1-5 from normal descriptors, /* 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. */ signal frame. */
if (rval <= 5) if (rval < 8)
addr = context->br_loc[rval]; addr = context->br_loc[rval];
else else
abort (); abort ();
...@@ -1930,6 +1931,10 @@ uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs) ...@@ -1930,6 +1931,10 @@ uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
{ {
long i; long i;
#ifdef MD_HANDLE_UNWABI
MD_HANDLE_UNWABI (context, fs);
#endif
context->sp = context->psp; context->sp = context->psp;
/* First, set PSP. Subsequent instructions may depend on this value. */ /* First, set PSP. Subsequent instructions may depend on this value. */
...@@ -2081,22 +2086,22 @@ uw_install_context (struct _Unwind_Context *current __attribute__((unused)), ...@@ -2081,22 +2086,22 @@ uw_install_context (struct _Unwind_Context *current __attribute__((unused)),
";; \n\t" ";; \n\t"
"(p6) ld8.fill r4 = [%1] \n\t" "(p6) ld8.fill r4 = [%1] \n\t"
"(p7) ld8.fill r5 = [r20] \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 %1 = 16, %1 \n\t"
"adds r20 = 16, r20 \n\t" "adds r20 = 16, r20 \n\t"
";; \n\t" ";; \n\t"
"(p8) ld8.fill r6 = [%1] \n\t" "(p8) ld8.fill r6 = [%1] \n\t"
"(p9) ld8.fill r7 = [r20] \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" ";; \n\t"
/* Load up call-saved branch registers. */ /* Load up call-saved branch registers. */
"ld8 r22 = [r20], 16 \n\t" "ld8 r22 = [r20], 16 \n\t"
"ld8 r23 = [r21], 16 \n\t" "ld8 r23 = [r21], 16 \n\t"
";; \n\t" ";; \n\t"
"ld8 r24 = [r20], 16 \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" ";; \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" "ld8 r27 = [r21], 24 \n\t"
"cmp.ne p6, p0 = r0, r22 \n\t" "cmp.ne p6, p0 = r0, r22 \n\t"
";; \n\t" ";; \n\t"
...@@ -2244,7 +2249,7 @@ uw_install_context (struct _Unwind_Context *current __attribute__((unused)), ...@@ -2244,7 +2249,7 @@ uw_install_context (struct _Unwind_Context *current __attribute__((unused)),
"(p9) mov.i ar.lc = r29 \n\t" "(p9) mov.i ar.lc = r29 \n\t"
";; \n\t" ";; \n\t"
"mov.m r25 = ar.rsc \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" ";; \n\t"
"and r25 = 0x1c, r25 \n\t" "and r25 = 0x1c, r25 \n\t"
"mov b0 = r26 \n\t" "mov b0 = r26 \n\t"
......
...@@ -3052,6 +3052,19 @@ For proper signal handling in Java this macro is accompanied by ...@@ -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. @code{MAKE_THROW_FRAME}, defined in @file{libjava/include/*-signal.h} headers.
@end defmac @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 @node Stack Checking
@subsection Specifying How Stack Checking is Done @subsection Specifying How Stack Checking is Done
......
2003-12-12 Jakub Jelinek <jakub@redhat.com>
* g++.dg/eh/ia64-1.C: New test.
2003-12-12 Roger Sayle <roger@eyesopen.com> 2003-12-12 Roger Sayle <roger@eyesopen.com>
PR optimization/13037 PR optimization/13037
......
// 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment