1169689Skan/* DWARF2 EH unwinding support for SPARC Linux. 2169689Skan Copyright 2004, 2005 Free Software Foundation, Inc. 3169689Skan 4169689SkanThis file is part of GCC. 5169689Skan 6169689SkanGCC is free software; you can redistribute it and/or modify 7169689Skanit under the terms of the GNU General Public License as published by 8169689Skanthe Free Software Foundation; either version 2, or (at your option) 9169689Skanany later version. 10169689Skan 11169689SkanIn addition to the permissions in the GNU General Public License, the 12169689SkanFree Software Foundation gives you unlimited permission to link the 13169689Skancompiled version of this file with other programs, and to distribute 14169689Skanthose programs without any restriction coming from the use of this 15169689Skanfile. (The General Public License restrictions do apply in other 16169689Skanrespects; for example, they cover modification of the file, and 17169689Skandistribution when not linked into another program.) 18169689Skan 19169689SkanGCC is distributed in the hope that it will be useful, 20169689Skanbut WITHOUT ANY WARRANTY; without even the implied warranty of 21169689SkanMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22169689SkanGNU General Public License for more details. 23169689Skan 24169689SkanYou should have received a copy of the GNU General Public License 25169689Skanalong with GCC; see the file COPYING. If not, write to 26169689Skanthe Free Software Foundation, 51 Franklin Street, Fifth Floor, 27169689SkanBoston, MA 02110-1301, USA. */ 28169689Skan 29169689Skan/* Do code reading to identify a signal frame, and set the frame 30169689Skan state data appropriately. See unwind-dw2.c for the structs. */ 31169689Skan 32169689Skan/* Handle multilib correctly. */ 33169689Skan#if defined(__arch64__) 34169689Skan 35169689Skan/* 64-bit SPARC version */ 36169689Skan#define MD_FALLBACK_FRAME_STATE_FOR sparc64_fallback_frame_state 37169689Skan 38169689Skanstatic _Unwind_Reason_Code 39169689Skansparc64_fallback_frame_state (struct _Unwind_Context *context, 40169689Skan _Unwind_FrameState *fs) 41169689Skan{ 42169689Skan unsigned int *pc = context->ra; 43169689Skan long new_cfa, i; 44169689Skan long regs_off, fpu_save_off; 45169689Skan long this_cfa, fpu_save; 46169689Skan 47169689Skan if (pc[0] != 0x82102065 /* mov NR_rt_sigreturn, %g1 */ 48169689Skan || pc[1] != 0x91d0206d) /* ta 0x6d */ 49169689Skan return _URC_END_OF_STACK; 50169689Skan regs_off = 192 + 128; 51169689Skan fpu_save_off = regs_off + (16 * 8) + (3 * 8) + (2 * 4); 52169689Skan this_cfa = (long) context->cfa; 53169689Skan new_cfa = *(long *)((context->cfa) + (regs_off + (14 * 8))); 54169689Skan new_cfa += 2047; /* Stack bias */ 55169689Skan fpu_save = *(long *)((this_cfa) + (fpu_save_off)); 56169689Skan fs->cfa_how = CFA_REG_OFFSET; 57169689Skan fs->cfa_reg = 14; 58169689Skan fs->cfa_offset = new_cfa - (long) context->cfa; 59169689Skan for (i = 1; i < 16; ++i) 60169689Skan { 61169689Skan fs->regs.reg[i].how = REG_SAVED_OFFSET; 62169689Skan fs->regs.reg[i].loc.offset = 63169689Skan this_cfa + (regs_off + (i * 8)) - new_cfa; 64169689Skan } 65169689Skan for (i = 0; i < 16; ++i) 66169689Skan { 67169689Skan fs->regs.reg[i + 16].how = REG_SAVED_OFFSET; 68169689Skan fs->regs.reg[i + 16].loc.offset = 69169689Skan this_cfa + (i * 8) - new_cfa; 70169689Skan } 71169689Skan if (fpu_save) 72169689Skan { 73169689Skan for (i = 0; i < 64; ++i) 74169689Skan { 75169689Skan if (i > 32 && (i & 0x1)) 76169689Skan continue; 77169689Skan fs->regs.reg[i + 32].how = REG_SAVED_OFFSET; 78169689Skan fs->regs.reg[i + 32].loc.offset = 79169689Skan (fpu_save + (i * 4)) - new_cfa; 80169689Skan } 81169689Skan } 82169689Skan /* Stick return address into %g0, same trick Alpha uses. */ 83169689Skan fs->regs.reg[0].how = REG_SAVED_OFFSET; 84169689Skan fs->regs.reg[0].loc.offset = 85169689Skan this_cfa + (regs_off + (16 * 8) + 8) - new_cfa; 86169689Skan fs->retaddr_column = 0; 87169689Skan return _URC_NO_REASON; 88169689Skan} 89169689Skan 90169689Skan#else 91169689Skan 92169689Skan/* 32-bit SPARC version */ 93169689Skan#define MD_FALLBACK_FRAME_STATE_FOR sparc_fallback_frame_state 94169689Skan 95169689Skanstatic _Unwind_Reason_Code 96169689Skansparc_fallback_frame_state (struct _Unwind_Context *context, 97169689Skan _Unwind_FrameState *fs) 98169689Skan{ 99169689Skan unsigned int *pc = context->ra; 100169689Skan int new_cfa, i, oldstyle; 101169689Skan int regs_off, fpu_save_off; 102169689Skan int fpu_save, this_cfa; 103169689Skan 104169689Skan if (pc[1] != 0x91d02010) /* ta 0x10 */ 105169689Skan return _URC_END_OF_STACK; 106169689Skan if (pc[0] == 0x821020d8) /* mov NR_sigreturn, %g1 */ 107169689Skan oldstyle = 1; 108169689Skan else if (pc[0] == 0x82102065) /* mov NR_rt_sigreturn, %g1 */ 109169689Skan oldstyle = 0; 110169689Skan else 111169689Skan return _URC_END_OF_STACK; 112169689Skan if (oldstyle) 113169689Skan { 114169689Skan regs_off = 96; 115169689Skan fpu_save_off = regs_off + (4 * 4) + (16 * 4); 116169689Skan } 117169689Skan else 118169689Skan { 119169689Skan regs_off = 96 + 128; 120169689Skan fpu_save_off = regs_off + (4 * 4) + (16 * 4) + (2 * 4); 121169689Skan } 122169689Skan this_cfa = (int) context->cfa; 123169689Skan new_cfa = *(int *)((context->cfa) + (regs_off+(4*4)+(14 * 4))); 124169689Skan fpu_save = *(int *)((this_cfa) + (fpu_save_off)); 125169689Skan fs->cfa_how = CFA_REG_OFFSET; 126169689Skan fs->cfa_reg = 14; 127169689Skan fs->cfa_offset = new_cfa - (int) context->cfa; 128169689Skan for (i = 1; i < 16; ++i) 129169689Skan { 130169689Skan if (i == 14) 131169689Skan continue; 132169689Skan fs->regs.reg[i].how = REG_SAVED_OFFSET; 133169689Skan fs->regs.reg[i].loc.offset = 134169689Skan this_cfa + (regs_off+(4 * 4)+(i * 4)) - new_cfa; 135169689Skan } 136169689Skan for (i = 0; i < 16; ++i) 137169689Skan { 138169689Skan fs->regs.reg[i + 16].how = REG_SAVED_OFFSET; 139169689Skan fs->regs.reg[i + 16].loc.offset = 140169689Skan this_cfa + (i * 4) - new_cfa; 141169689Skan } 142169689Skan if (fpu_save) 143169689Skan { 144169689Skan for (i = 0; i < 32; ++i) 145169689Skan { 146169689Skan fs->regs.reg[i + 32].how = REG_SAVED_OFFSET; 147169689Skan fs->regs.reg[i + 32].loc.offset = 148169689Skan (fpu_save + (i * 4)) - new_cfa; 149169689Skan } 150169689Skan } 151169689Skan /* Stick return address into %g0, same trick Alpha uses. */ 152169689Skan fs->regs.reg[0].how = REG_SAVED_OFFSET; 153169689Skan fs->regs.reg[0].loc.offset = this_cfa+(regs_off+4)-new_cfa; 154169689Skan fs->retaddr_column = 0; 155169689Skan return _URC_NO_REASON; 156169689Skan} 157169689Skan 158169689Skan#endif 159