Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/sh/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 SH Linux. | |
2 Copyright (C) 2004, 2005, 2006, 2007, 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 #include <signal.h> | |
30 #include <sys/ucontext.h> | |
31 #include "insn-constants.h" | |
32 | |
33 # if defined (__SH5__) | |
34 #define SH_DWARF_FRAME_GP0 0 | |
35 #define SH_DWARF_FRAME_FP0 77 | |
36 #define SH_DWARF_FRAME_BT0 68 | |
37 #define SH_DWARF_FRAME_PR_MEDIA 18 | |
38 #define SH_DWARF_FRAME_SR 65 | |
39 #define SH_DWARF_FRAME_FPSCR 76 | |
40 #else | |
41 #define SH_DWARF_FRAME_GP0 0 | |
42 #define SH_DWARF_FRAME_FP0 25 | |
43 #define SH_DWARF_FRAME_XD0 87 | |
44 #define SH_DWARF_FRAME_PR 17 | |
45 #define SH_DWARF_FRAME_GBR 18 | |
46 #define SH_DWARF_FRAME_MACH 20 | |
47 #define SH_DWARF_FRAME_MACL 21 | |
48 #define SH_DWARF_FRAME_PC 16 | |
49 #define SH_DWARF_FRAME_SR 22 | |
50 #define SH_DWARF_FRAME_FPUL 23 | |
51 #define SH_DWARF_FRAME_FPSCR 24 | |
52 #endif /* defined (__SH5__) */ | |
53 | |
54 #if defined (__SH5__) | |
55 | |
56 #define MD_FALLBACK_FRAME_STATE_FOR shmedia_fallback_frame_state | |
57 | |
58 static _Unwind_Reason_Code | |
59 shmedia_fallback_frame_state (struct _Unwind_Context *context, | |
60 _Unwind_FrameState *fs) | |
61 { | |
62 unsigned char *pc = context->ra; | |
63 struct sigcontext *sc; | |
64 long new_cfa; | |
65 int i, r; | |
66 | |
67 /* movi 0x10,r9; shori 0x77,r9; trapa r9; nop (sigreturn) */ | |
68 /* movi 0x10,r9; shori 0xad,r9; trapa r9; nop (rt_sigreturn) */ | |
69 if ((*(unsigned long *) (pc-1) == 0xcc004090) | |
70 && (*(unsigned long *) (pc+3) == 0xc801dc90) | |
71 && (*(unsigned long *) (pc+7) == 0x6c91fff0) | |
72 && (*(unsigned long *) (pc+11) == 0x6ff0fff0)) | |
73 sc = context->cfa; | |
74 else if ((*(unsigned long *) (pc-1) == 0xcc004090) | |
75 && (*(unsigned long *) (pc+3) == 0xc802b490) | |
76 && (*(unsigned long *) (pc+7) == 0x6c91fff0) | |
77 && (*(unsigned long *) (pc+11) == 0x6ff0fff0)) | |
78 { | |
79 struct rt_sigframe { | |
80 struct siginfo *pinfo; | |
81 void *puc; | |
82 struct siginfo info; | |
83 struct ucontext uc; | |
84 } *rt_ = context->cfa; | |
85 /* The void * cast is necessary to avoid an aliasing warning. | |
86 The aliasing warning is correct, but should not be a problem | |
87 because it does not alias anything. */ | |
88 sc = (struct sigcontext *) (void *) &rt_->uc.uc_mcontext; | |
89 } | |
90 else | |
91 return _URC_END_OF_STACK; | |
92 | |
93 new_cfa = sc->sc_regs[15]; | |
94 fs->regs.cfa_how = CFA_REG_OFFSET; | |
95 fs->regs.cfa_reg = 15; | |
96 fs->regs.cfa_offset = new_cfa - (long) context->cfa; | |
97 | |
98 for (i = 0; i < 63; i++) | |
99 { | |
100 if (i == 15) | |
101 continue; | |
102 | |
103 fs->regs.reg[i].how = REG_SAVED_OFFSET; | |
104 fs->regs.reg[i].loc.offset | |
105 = (long)&(sc->sc_regs[i]) - new_cfa; | |
106 } | |
107 | |
108 fs->regs.reg[SH_DWARF_FRAME_SR].how = REG_SAVED_OFFSET; | |
109 fs->regs.reg[SH_DWARF_FRAME_SR].loc.offset | |
110 = (long)&(sc->sc_sr) - new_cfa; | |
111 | |
112 r = SH_DWARF_FRAME_BT0; | |
113 for (i = 0; i < 8; i++) | |
114 { | |
115 fs->regs.reg[r+i].how = REG_SAVED_OFFSET; | |
116 fs->regs.reg[r+i].loc.offset | |
117 = (long)&(sc->sc_tregs[i]) - new_cfa; | |
118 } | |
119 | |
120 r = SH_DWARF_FRAME_FP0; | |
121 for (i = 0; i < 32; i++) | |
122 { | |
123 fs->regs.reg[r+i].how = REG_SAVED_OFFSET; | |
124 fs->regs.reg[r+i].loc.offset | |
125 = (long)&(sc->sc_fpregs[i]) - new_cfa; | |
126 } | |
127 | |
128 fs->regs.reg[SH_DWARF_FRAME_FPSCR].how = REG_SAVED_OFFSET; | |
129 fs->regs.reg[SH_DWARF_FRAME_FPSCR].loc.offset | |
130 = (long)&(sc->sc_fpscr) - new_cfa; | |
131 | |
132 /* We use the slot for the zero register to save return address. */ | |
133 fs->regs.reg[63].how = REG_SAVED_OFFSET; | |
134 fs->regs.reg[63].loc.offset | |
135 = (long)&(sc->sc_pc) - new_cfa; | |
136 fs->retaddr_column = 63; | |
137 fs->signal_frame = 1; | |
138 return _URC_NO_REASON; | |
139 } | |
140 | |
141 #else /* defined (__SH5__) */ | |
142 | |
143 #define MD_FALLBACK_FRAME_STATE_FOR sh_fallback_frame_state | |
144 | |
145 static _Unwind_Reason_Code | |
146 sh_fallback_frame_state (struct _Unwind_Context *context, | |
147 _Unwind_FrameState *fs) | |
148 { | |
149 unsigned char *pc = context->ra; | |
150 struct sigcontext *sc; | |
151 long new_cfa; | |
152 int i; | |
153 #if defined (__SH3E__) || defined (__SH4__) | |
154 int r; | |
155 #endif | |
156 | |
157 /* mov.w 1f,r3; trapa #0x10; 1: .short 0x77 (sigreturn) */ | |
158 /* mov.w 1f,r3; trapa #0x10; 1: .short 0xad (rt_sigreturn) */ | |
159 /* Newer kernel uses pad instructions to avoid an SH-4 core bug. */ | |
160 /* mov.w 1f,r3; trapa #0x10; or r0,r0; or r0,r0; or r0,r0; or r0,r0; | |
161 or r0,r0; 1: .short 0x77 (sigreturn) */ | |
162 /* mov.w 1f,r3; trapa #0x10; or r0,r0; or r0,r0; or r0,r0; or r0,r0; | |
163 or r0,r0; 1: .short 0xad (rt_sigreturn) */ | |
164 if (((*(unsigned short *) (pc+0) == 0x9300) | |
165 && (*(unsigned short *) (pc+2) == 0xc310) | |
166 && (*(unsigned short *) (pc+4) == 0x0077)) | |
167 || (((*(unsigned short *) (pc+0) == 0x9305) | |
168 && (*(unsigned short *) (pc+2) == 0xc310) | |
169 && (*(unsigned short *) (pc+14) == 0x0077)))) | |
170 sc = context->cfa; | |
171 else if (((*(unsigned short *) (pc+0) == 0x9300) | |
172 && (*(unsigned short *) (pc+2) == 0xc310) | |
173 && (*(unsigned short *) (pc+4) == 0x00ad)) | |
174 || (((*(unsigned short *) (pc+0) == 0x9305) | |
175 && (*(unsigned short *) (pc+2) == 0xc310) | |
176 && (*(unsigned short *) (pc+14) == 0x00ad)))) | |
177 { | |
178 struct rt_sigframe { | |
179 struct siginfo info; | |
180 struct ucontext uc; | |
181 } *rt_ = context->cfa; | |
182 /* The void * cast is necessary to avoid an aliasing warning. | |
183 The aliasing warning is correct, but should not be a problem | |
184 because it does not alias anything. */ | |
185 sc = (struct sigcontext *) (void *) &rt_->uc.uc_mcontext; | |
186 } | |
187 else | |
188 return _URC_END_OF_STACK; | |
189 | |
190 new_cfa = sc->sc_regs[15]; | |
191 fs->regs.cfa_how = CFA_REG_OFFSET; | |
192 fs->regs.cfa_reg = 15; | |
193 fs->regs.cfa_offset = new_cfa - (long) context->cfa; | |
194 | |
195 for (i = 0; i < 15; i++) | |
196 { | |
197 fs->regs.reg[i].how = REG_SAVED_OFFSET; | |
198 fs->regs.reg[i].loc.offset | |
199 = (long)&(sc->sc_regs[i]) - new_cfa; | |
200 } | |
201 | |
202 fs->regs.reg[SH_DWARF_FRAME_PR].how = REG_SAVED_OFFSET; | |
203 fs->regs.reg[SH_DWARF_FRAME_PR].loc.offset | |
204 = (long)&(sc->sc_pr) - new_cfa; | |
205 fs->regs.reg[SH_DWARF_FRAME_SR].how = REG_SAVED_OFFSET; | |
206 fs->regs.reg[SH_DWARF_FRAME_SR].loc.offset | |
207 = (long)&(sc->sc_sr) - new_cfa; | |
208 fs->regs.reg[SH_DWARF_FRAME_GBR].how = REG_SAVED_OFFSET; | |
209 fs->regs.reg[SH_DWARF_FRAME_GBR].loc.offset | |
210 = (long)&(sc->sc_gbr) - new_cfa; | |
211 fs->regs.reg[SH_DWARF_FRAME_MACH].how = REG_SAVED_OFFSET; | |
212 fs->regs.reg[SH_DWARF_FRAME_MACH].loc.offset | |
213 = (long)&(sc->sc_mach) - new_cfa; | |
214 fs->regs.reg[SH_DWARF_FRAME_MACL].how = REG_SAVED_OFFSET; | |
215 fs->regs.reg[SH_DWARF_FRAME_MACL].loc.offset | |
216 = (long)&(sc->sc_macl) - new_cfa; | |
217 | |
218 #if defined (__SH3E__) || defined (__SH4__) | |
219 r = SH_DWARF_FRAME_FP0; | |
220 for (i = 0; i < 16; i++) | |
221 { | |
222 fs->regs.reg[r+i].how = REG_SAVED_OFFSET; | |
223 fs->regs.reg[r+i].loc.offset | |
224 = (long)&(sc->sc_fpregs[i]) - new_cfa; | |
225 } | |
226 | |
227 r = SH_DWARF_FRAME_XD0; | |
228 for (i = 0; i < 8; i++) | |
229 { | |
230 fs->regs.reg[r+i].how = REG_SAVED_OFFSET; | |
231 fs->regs.reg[r+i].loc.offset | |
232 = (long)&(sc->sc_xfpregs[2*i]) - new_cfa; | |
233 } | |
234 | |
235 fs->regs.reg[SH_DWARF_FRAME_FPUL].how = REG_SAVED_OFFSET; | |
236 fs->regs.reg[SH_DWARF_FRAME_FPUL].loc.offset | |
237 = (long)&(sc->sc_fpul) - new_cfa; | |
238 fs->regs.reg[SH_DWARF_FRAME_FPSCR].how = REG_SAVED_OFFSET; | |
239 fs->regs.reg[SH_DWARF_FRAME_FPSCR].loc.offset | |
240 = (long)&(sc->sc_fpscr) - new_cfa; | |
241 #endif | |
242 | |
243 fs->regs.reg[SH_DWARF_FRAME_PC].how = REG_SAVED_OFFSET; | |
244 fs->regs.reg[SH_DWARF_FRAME_PC].loc.offset | |
245 = (long)&(sc->sc_pc) - new_cfa; | |
246 fs->retaddr_column = SH_DWARF_FRAME_PC; | |
247 fs->signal_frame = 1; | |
248 return _URC_NO_REASON; | |
249 } | |
250 #endif /* defined (__SH5__) */ |