aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDavid S. Miller <davem@redhat.com>2002-04-19 21:47:49 -0700
committerDavid S. Miller <davem@gcc.gnu.org>2002-04-19 21:47:49 -0700
commitdb430d2664d9f13b8ef7cd41fad8e8270c618491 (patch)
tree00655c84e120607419106de1a2041e82840f4ec3 /gcc
parent19367215056227b261f2670e01be338c65c1cefe (diff)
downloadgcc-db430d2664d9f13b8ef7cd41fad8e8270c618491.zip
gcc-db430d2664d9f13b8ef7cd41fad8e8270c618491.tar.gz
gcc-db430d2664d9f13b8ef7cd41fad8e8270c618491.tar.bz2
linux.h (MD_FALLBACK_FRAME_STATE_FOR): Define.
2002-04-19 David S. Miller <davem@redhat.com> * config/sparc/linux.h (MD_FALLBACK_FRAME_STATE_FOR): Define. * config/sparc/linux64.h (MD_FALLBACK_FRAME_STATE_FOR): Likewise. From-SVN: r52546
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/config/sparc/linux.h69
-rw-r--r--gcc/config/sparc/linux64.h125
3 files changed, 199 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b9dee8f..004339e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2002-04-19 David S. Miller <davem@redhat.com>
+
+ * 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 <jakub@redhat.com>
PR optimization/3756
diff --git a/gcc/config/sparc/linux.h b/gcc/config/sparc/linux.h
index 69b7618..3e7e061 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 <signal.h>
+#include <sys/ucontext.h>
+#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 806d1b0..0ab61c2 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 <signal.h>
+#include <sys/ucontext.h>
+#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