comparison gcc/config/sparc/linux-unwind.h @ 0:a06113de4d67

first commit
author kent <kent@cr.ie.u-ryukyu.ac.jp>
date Fri, 17 Jul 2009 14:47:48 +0900
parents
children 77e2b8dfacca
comparison
equal deleted inserted replaced
-1:000000000000 0:a06113de4d67
1 /* DWARF2 EH unwinding support for SPARC Linux.
2 Copyright 2004, 2005, 2009 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
10
11 GCC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
19
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 <http://www.gnu.org/licenses/>. */
24
25
26 /* Do code reading to identify a signal frame, and set the frame
27 state data appropriately. See unwind-dw2.c for the structs. */
28
29 /* Handle multilib correctly. */
30 #if defined(__arch64__)
31
32 /* 64-bit SPARC version */
33 #define MD_FALLBACK_FRAME_STATE_FOR sparc64_fallback_frame_state
34
35 static _Unwind_Reason_Code
36 sparc64_fallback_frame_state (struct _Unwind_Context *context,
37 _Unwind_FrameState *fs)
38 {
39 unsigned int *pc = context->ra;
40 long new_cfa, i;
41 long regs_off, fpu_save_off;
42 long this_cfa, fpu_save;
43
44 if (pc[0] != 0x82102065 /* mov NR_rt_sigreturn, %g1 */
45 || pc[1] != 0x91d0206d) /* ta 0x6d */
46 return _URC_END_OF_STACK;
47 regs_off = 192 + 128;
48 fpu_save_off = regs_off + (16 * 8) + (3 * 8) + (2 * 4);
49 this_cfa = (long) context->cfa;
50 new_cfa = *(long *)((context->cfa) + (regs_off + (14 * 8)));
51 new_cfa += 2047; /* Stack bias */
52 fpu_save = *(long *)((this_cfa) + (fpu_save_off));
53 fs->regs.cfa_how = CFA_REG_OFFSET;
54 fs->regs.cfa_reg = 14;
55 fs->regs.cfa_offset = new_cfa - (long) context->cfa;
56 for (i = 1; i < 16; ++i)
57 {
58 fs->regs.reg[i].how = REG_SAVED_OFFSET;
59 fs->regs.reg[i].loc.offset =
60 this_cfa + (regs_off + (i * 8)) - new_cfa;
61 }
62 for (i = 0; i < 16; ++i)
63 {
64 fs->regs.reg[i + 16].how = REG_SAVED_OFFSET;
65 fs->regs.reg[i + 16].loc.offset =
66 this_cfa + (i * 8) - new_cfa;
67 }
68 if (fpu_save)
69 {
70 for (i = 0; i < 64; ++i)
71 {
72 if (i > 32 && (i & 0x1))
73 continue;
74 fs->regs.reg[i + 32].how = REG_SAVED_OFFSET;
75 fs->regs.reg[i + 32].loc.offset =
76 (fpu_save + (i * 4)) - new_cfa;
77 }
78 }
79 /* Stick return address into %g0, same trick Alpha uses. */
80 fs->regs.reg[0].how = REG_SAVED_OFFSET;
81 fs->regs.reg[0].loc.offset =
82 this_cfa + (regs_off + (16 * 8) + 8) - new_cfa;
83 fs->retaddr_column = 0;
84 return _URC_NO_REASON;
85 }
86
87 #else
88
89 /* 32-bit SPARC version */
90 #define MD_FALLBACK_FRAME_STATE_FOR sparc_fallback_frame_state
91
92 static _Unwind_Reason_Code
93 sparc_fallback_frame_state (struct _Unwind_Context *context,
94 _Unwind_FrameState *fs)
95 {
96 unsigned int *pc = context->ra;
97 int new_cfa, i, oldstyle;
98 int regs_off, fpu_save_off;
99 int fpu_save, this_cfa;
100
101 if (pc[1] != 0x91d02010) /* ta 0x10 */
102 return _URC_END_OF_STACK;
103 if (pc[0] == 0x821020d8) /* mov NR_sigreturn, %g1 */
104 oldstyle = 1;
105 else if (pc[0] == 0x82102065) /* mov NR_rt_sigreturn, %g1 */
106 oldstyle = 0;
107 else
108 return _URC_END_OF_STACK;
109 if (oldstyle)
110 {
111 regs_off = 96;
112 fpu_save_off = regs_off + (4 * 4) + (16 * 4);
113 }
114 else
115 {
116 regs_off = 96 + 128;
117 fpu_save_off = regs_off + (4 * 4) + (16 * 4) + (2 * 4);
118 }
119 this_cfa = (int) context->cfa;
120 new_cfa = *(int *)((context->cfa) + (regs_off+(4*4)+(14 * 4)));
121 fpu_save = *(int *)((this_cfa) + (fpu_save_off));
122 fs->regs.cfa_how = CFA_REG_OFFSET;
123 fs->regs.cfa_reg = 14;
124 fs->regs.cfa_offset = new_cfa - (int) context->cfa;
125 for (i = 1; i < 16; ++i)
126 {
127 if (i == 14)
128 continue;
129 fs->regs.reg[i].how = REG_SAVED_OFFSET;
130 fs->regs.reg[i].loc.offset =
131 this_cfa + (regs_off+(4 * 4)+(i * 4)) - new_cfa;
132 }
133 for (i = 0; i < 16; ++i)
134 {
135 fs->regs.reg[i + 16].how = REG_SAVED_OFFSET;
136 fs->regs.reg[i + 16].loc.offset =
137 this_cfa + (i * 4) - new_cfa;
138 }
139 if (fpu_save)
140 {
141 for (i = 0; i < 32; ++i)
142 {
143 fs->regs.reg[i + 32].how = REG_SAVED_OFFSET;
144 fs->regs.reg[i + 32].loc.offset =
145 (fpu_save + (i * 4)) - new_cfa;
146 }
147 }
148 /* Stick return address into %g0, same trick Alpha uses. */
149 fs->regs.reg[0].how = REG_SAVED_OFFSET;
150 fs->regs.reg[0].loc.offset = this_cfa+(regs_off+4)-new_cfa;
151 fs->retaddr_column = 0;
152 return _URC_NO_REASON;
153 }
154
155 #endif