diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b9dee8f49bc..004339e757a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2002-04-19 David S. Miller + + * config/sparc/linux.h (MD_FALLBACK_FRAME_STATE_FOR): Define. + * config/sparc/linux64.h (MD_FALLBACK_FRAME_STATE_FOR): Likewise. + 2002-04-19 Jakub Jelinek PR optimization/3756 diff --git a/gcc/config/sparc/linux.h b/gcc/config/sparc/linux.h index 69b7618fe59..3e7e0611a93 100644 --- a/gcc/config/sparc/linux.h +++ b/gcc/config/sparc/linux.h @@ -257,3 +257,72 @@ do { \ /* We use GNU ld so undefine this so that attribute((init_priority)) works. */ #undef CTORS_SECTION_ASM_OP #undef DTORS_SECTION_ASM_OP + +/* 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 +#include +#endif + +#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \ + do { \ + unsigned int *pc_ = (CONTEXT)->ra; \ + int new_cfa_, i_, oldstyle_; \ + int regs_off_, fpu_save_off_; \ + int fpu_save_, this_cfa_; \ + \ + if (pc_[1] != 0x91d02010) /* ta 0x10 */ \ + break; \ + if (pc_[0] == 0x821020d8) /* mov NR_sigreturn, %g1 */ \ + oldstyle_ = 1; \ + else if (pc_[0] == 0x82102065) /* mov NR_rt_sigreturn, %g1 */ \ + oldstyle_ = 0; \ + else \ + break; \ + if (oldstyle_) \ + { \ + regs_off_ = 96; \ + fpu_save_off_ = regs_off_ + (4 * 4) + (16 * 4); \ + } \ + else \ + { \ + regs_off_ = 96 + 128; \ + fpu_save_off_ = regs_off_ + (4 * 4) + (16 * 4) + (2 * 4); \ + } \ + this_cfa_ = (int) (CONTEXT)->cfa; \ + new_cfa_ = *(int *)(((CONTEXT)->cfa) + (regs_off_+(4*4)+(14 * 4))); \ + fpu_save_ = *(int *)((this_cfa_) + (fpu_save_off_)); \ + (FS)->cfa_how = CFA_REG_OFFSET; \ + (FS)->cfa_reg = 14; \ + (FS)->cfa_offset = new_cfa_ - (int) (CONTEXT)->cfa; \ + for (i_ = 1; i_ < 16; ++i_) \ + { \ + if (i_ == 14) \ + continue; \ + (FS)->regs.reg[i_].how = REG_SAVED_OFFSET; \ + (FS)->regs.reg[i_].loc.offset = \ + this_cfa_ + (regs_off_+(4 * 4)+(i_ * 4)) - new_cfa_; \ + } \ + for (i_ = 0; i_ < 16; ++i_) \ + { \ + (FS)->regs.reg[i_ + 16].how = REG_SAVED_OFFSET; \ + (FS)->regs.reg[i_ + 16].loc.offset = \ + this_cfa_ + (i_ * 4) - new_cfa_; \ + } \ + if (fpu_save_) \ + { \ + for (i_ = 0; i_ < 32; ++i_) \ + { \ + (FS)->regs.reg[i_ + 32].how = REG_SAVED_OFFSET; \ + (FS)->regs.reg[i_ + 32].loc.offset = \ + (fpu_save_ + (i_ * 4)) - new_cfa_; \ + } \ + } \ + /* Stick return address into %g0, same trick Alpha uses. */ \ + (FS)->regs.reg[0].how = REG_SAVED_OFFSET; \ + (FS)->regs.reg[0].loc.offset = this_cfa_+(regs_off_+4)-new_cfa_; \ + (FS)->retaddr_column = 0; \ + goto SUCCESS; \ + } while (0) diff --git a/gcc/config/sparc/linux64.h b/gcc/config/sparc/linux64.h index 806d1b02a7d..0ab61c2a7dc 100644 --- a/gcc/config/sparc/linux64.h +++ b/gcc/config/sparc/linux64.h @@ -377,3 +377,128 @@ do { \ /* We use GNU ld so undefine this so that attribute((init_priority)) works. */ #undef CTORS_SECTION_ASM_OP #undef DTORS_SECTION_ASM_OP + +/* 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 +#include +#endif + +/* Handle multilib correctly. */ +#if defined(__arch64__) +/* 64-bit Sparc version */ +#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \ + do { \ + unsigned int *pc_ = (CONTEXT)->ra; \ + long new_cfa_, i_; \ + long regs_off_, fpu_save_off_; \ + long this_cfa_, fpu_save_; \ + \ + if (pc_[0] != 0x82102065 /* mov NR_rt_sigreturn, %g1 */ \ + || pc_[1] != 0x91d0206d) /* ta 0x6d */ \ + break; \ + regs_off_ = 192 + 128; \ + fpu_save_off_ = regs_off_ + (16 * 8) + (3 * 8) + (2 * 4); \ + this_cfa_ = (long) (CONTEXT)->cfa; \ + new_cfa_ = *(long *)(((CONTEXT)->cfa) + (regs_off_ + (14 * 8))); \ + fpu_save_ = *(long *)((this_cfa_) + (fpu_save_off_)); \ + (FS)->cfa_how = CFA_REG_OFFSET; \ + (FS)->cfa_reg = 14; \ + (FS)->cfa_offset = new_cfa_ - (long) (CONTEXT)->cfa; \ + for (i_ = 1; i_ < 16; ++i_) \ + { \ + if (i_ == 14) \ + continue; \ + (FS)->regs.reg[i_].how = REG_SAVED_OFFSET; \ + (FS)->regs.reg[i_].loc.offset = \ + this_cfa_ + (regs_off_ + (i_ * 8)) - new_cfa_; \ + } \ + for (i_ = 0; i_ < 16; ++i_) \ + { \ + (FS)->regs.reg[i_ + 16].how = REG_SAVED_OFFSET; \ + (FS)->regs.reg[i_ + 16].loc.offset = \ + this_cfa_ + (i_ * 8) - new_cfa_; \ + } \ + if (fpu_save_) \ + { \ + for (i_ = 0; i_ < 64; ++i_) \ + { \ + if (i_ > 32 && (i_ & 0x1)) \ + continue; \ + (FS)->regs.reg[i_ + 32].how = REG_SAVED_OFFSET; \ + (FS)->regs.reg[i_ + 32].loc.offset = \ + (fpu_save_ + (i_ * 4)) - new_cfa_; \ + } \ + } \ + /* Stick return address into %g0, same trick Alpha uses. */ \ + (FS)->regs.reg[0].how = REG_SAVED_OFFSET; \ + (FS)->regs.reg[0].loc.offset = \ + this_cfa_ + (regs_off_ + (16 * 8) + 8) - new_cfa_; \ + (FS)->retaddr_column = 0; \ + goto SUCCESS; \ + } while (0) +#else +/* 32-bit Sparc version */ +#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \ + do { \ + unsigned int *pc_ = (CONTEXT)->ra; \ + int new_cfa_, i_, oldstyle_; \ + int regs_off_, fpu_save_off_; \ + int fpu_save_, this_cfa_; \ + \ + if (pc_[1] != 0x91d02010) /* ta 0x10 */ \ + break; \ + if (pc_[0] == 0x821020d8) /* mov NR_sigreturn, %g1 */ \ + oldstyle_ = 1; \ + else if (pc_[0] == 0x82102065) /* mov NR_rt_sigreturn, %g1 */ \ + oldstyle_ = 0; \ + else \ + break; \ + if (oldstyle_) \ + { \ + regs_off_ = 96; \ + fpu_save_off_ = regs_off_ + (4 * 4) + (16 * 4); \ + } \ + else \ + { \ + regs_off_ = 96 + 128; \ + fpu_save_off_ = regs_off_ + (4 * 4) + (16 * 4) + (2 * 4); \ + } \ + this_cfa_ = (int) (CONTEXT)->cfa; \ + new_cfa_ = *(int *)(((CONTEXT)->cfa) + (regs_off_+(4*4)+(14 * 4))); \ + fpu_save_ = *(int *)((this_cfa_) + (fpu_save_off_)); \ + (FS)->cfa_how = CFA_REG_OFFSET; \ + (FS)->cfa_reg = 14; \ + (FS)->cfa_offset = new_cfa_ - (int) (CONTEXT)->cfa; \ + for (i_ = 1; i_ < 16; ++i_) \ + { \ + if (i_ == 14) \ + continue; \ + (FS)->regs.reg[i_].how = REG_SAVED_OFFSET; \ + (FS)->regs.reg[i_].loc.offset = \ + this_cfa_ + (regs_off_+(4 * 4)+(i_ * 4)) - new_cfa_; \ + } \ + for (i_ = 0; i_ < 16; ++i_) \ + { \ + (FS)->regs.reg[i_ + 16].how = REG_SAVED_OFFSET; \ + (FS)->regs.reg[i_ + 16].loc.offset = \ + this_cfa_ + (i_ * 4) - new_cfa_; \ + } \ + if (fpu_save_) \ + { \ + for (i_ = 0; i_ < 32; ++i_) \ + { \ + (FS)->regs.reg[i_ + 32].how = REG_SAVED_OFFSET; \ + (FS)->regs.reg[i_ + 32].loc.offset = \ + (fpu_save_ + (i_ * 4)) - new_cfa_; \ + } \ + } \ + /* Stick return address into %g0, same trick Alpha uses. */ \ + (FS)->regs.reg[0].how = REG_SAVED_OFFSET; \ + (FS)->regs.reg[0].loc.offset = this_cfa_+(regs_off_+4)-new_cfa_; \ + (FS)->retaddr_column = 0; \ + goto SUCCESS; \ + } while (0) +#endif