diff options
Diffstat (limited to 'gcc/config/ia64/linux.h')
-rw-r--r-- | gcc/config/ia64/linux.h | 68 |
1 files changed, 62 insertions, 6 deletions
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 */ |