111
|
1 /* C6X EABI compliant unwinding routines.
|
145
|
2 Copyright (C) 2011-2020 Free Software Foundation, Inc.
|
111
|
3
|
|
4 This file is free software; you can redistribute it and/or modify it
|
|
5 under the terms of the GNU General Public License as published by the
|
|
6 Free Software Foundation; either version 3, or (at your option) any
|
|
7 later version.
|
|
8
|
|
9 This file is distributed in the hope that it will be useful, but
|
|
10 WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
12 General Public License for more details.
|
|
13
|
|
14 Under Section 7 of GPL version 3, you are granted additional
|
|
15 permissions described in the GCC Runtime Library Exception, version
|
|
16 3.1, as published by the Free Software Foundation.
|
|
17
|
|
18 You should have received a copy of the GNU General Public License and
|
|
19 a copy of the GCC Runtime Library Exception along with this program;
|
|
20 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
|
21 <http://www.gnu.org/licenses/>. */
|
|
22
|
|
23 #include "unwind.h"
|
|
24
|
|
25 /* Misc constants. */
|
|
26 #define NUM_SAVED_REGS 32
|
|
27 #define R_B0 16
|
|
28 #define R_B3 (R_B0 + 3)
|
|
29 #define R_B15 (R_B0 + 15)
|
|
30 #define R_SP R_B15
|
|
31 #define R_LR R_B3
|
|
32 #define R_PC 33
|
|
33
|
|
34 #define VRS_PC(vrs) ((vrs)->core.pc)
|
|
35 #define VRS_SP(vrs) ((vrs)->core.reg[R_SP])
|
|
36 #define VRS_RETURN(vrs) ((vrs)->core.reg[R_B3])
|
|
37
|
|
38 struct core_regs
|
|
39 {
|
|
40 _uw reg[NUM_SAVED_REGS];
|
|
41 _uw pc;
|
|
42 };
|
|
43
|
|
44 typedef struct
|
|
45 {
|
|
46 /* The first fields must be the same as a phase2_vrs. */
|
|
47 _uw demand_save_flags; /* Currently always zero. */
|
|
48 struct core_regs core;
|
|
49 _uw prev_sp; /* Only valid during forced unwinding. */
|
|
50 } phase1_vrs;
|
|
51
|
|
52 /* This must match the structure created by the assembly wrappers. */
|
|
53 typedef struct
|
|
54 {
|
|
55 _uw demand_save_flags;
|
|
56 struct core_regs core;
|
|
57 } phase2_vrs;
|
|
58
|
|
59 /* Coprocessor register state manipulation functions. */
|
|
60
|
|
61 /* Restore coprocessor state after phase1 unwinding. */
|
|
62 static void
|
|
63 restore_non_core_regs (phase1_vrs * vrs __attribute__((unused)))
|
|
64 {
|
|
65 }
|
|
66
|
|
67 #include "unwind-arm-common.inc"
|
|
68
|
|
69 /* ABI defined personality routines. */
|
|
70 extern _Unwind_Reason_Code __c6xabi_unwind_cpp_pr0 (_Unwind_State,
|
|
71 _Unwind_Control_Block *, _Unwind_Context *);// __attribute__((weak));
|
|
72 extern _Unwind_Reason_Code __c6xabi_unwind_cpp_pr1 (_Unwind_State,
|
|
73 _Unwind_Control_Block *, _Unwind_Context *) __attribute__((weak));
|
|
74 extern _Unwind_Reason_Code __c6xabi_unwind_cpp_pr2 (_Unwind_State,
|
|
75 _Unwind_Control_Block *, _Unwind_Context *) __attribute__((weak));
|
|
76 extern _Unwind_Reason_Code __c6xabi_unwind_cpp_pr3 (_Unwind_State,
|
|
77 _Unwind_Control_Block *, _Unwind_Context *) __attribute__((weak));
|
|
78 extern _Unwind_Reason_Code __c6xabi_unwind_cpp_pr4 (_Unwind_State,
|
|
79 _Unwind_Control_Block *, _Unwind_Context *) __attribute__((weak));
|
|
80
|
|
81 /* ABI defined routine to store a virtual register to memory. */
|
|
82
|
|
83 _Unwind_VRS_Result _Unwind_VRS_Get (_Unwind_Context *context,
|
|
84 _Unwind_VRS_RegClass regclass,
|
|
85 _uw regno,
|
|
86 _Unwind_VRS_DataRepresentation representation,
|
|
87 void *valuep)
|
|
88 {
|
|
89 phase1_vrs *vrs = (phase1_vrs *) context;
|
|
90
|
|
91 switch (regclass)
|
|
92 {
|
|
93 case _UVRSC_CORE:
|
|
94 if (representation != _UVRSD_UINT32)
|
|
95 return _UVRSR_FAILED;
|
|
96 if (regno == R_PC)
|
|
97 {
|
|
98 *(_uw *) valuep = vrs->core.pc;
|
|
99 return _UVRSR_OK;
|
|
100 }
|
|
101 if (regno >= NUM_SAVED_REGS)
|
|
102 return _UVRSR_FAILED;
|
|
103 *(_uw *) valuep = vrs->core.reg[regno];
|
|
104 return _UVRSR_OK;
|
|
105
|
|
106 default:
|
|
107 return _UVRSR_FAILED;
|
|
108 }
|
|
109 }
|
|
110
|
|
111
|
|
112 /* ABI defined function to load a virtual register from memory. */
|
|
113
|
|
114 _Unwind_VRS_Result _Unwind_VRS_Set (_Unwind_Context *context,
|
|
115 _Unwind_VRS_RegClass regclass,
|
|
116 _uw regno,
|
|
117 _Unwind_VRS_DataRepresentation representation,
|
|
118 void *valuep)
|
|
119 {
|
|
120 phase1_vrs *vrs = (phase1_vrs *) context;
|
|
121
|
|
122 switch (regclass)
|
|
123 {
|
|
124 case _UVRSC_CORE:
|
|
125 if (representation != _UVRSD_UINT32)
|
|
126 return _UVRSR_FAILED;
|
|
127 if (regno == R_PC)
|
|
128 {
|
|
129 vrs->core.pc = *(_uw *) valuep;
|
|
130 return _UVRSR_OK;
|
|
131 }
|
|
132 if (regno >= NUM_SAVED_REGS)
|
|
133 return _UVRSR_FAILED;
|
|
134
|
|
135 vrs->core.reg[regno] = *(_uw *) valuep;
|
|
136 return _UVRSR_OK;
|
|
137
|
|
138 default:
|
|
139 return _UVRSR_FAILED;
|
|
140 }
|
|
141 }
|
|
142
|
|
143
|
|
144 /* Core unwinding functions. */
|
|
145
|
|
146 /* Calculate the address encoded by a 31-bit self-relative offset at address
|
|
147 P. */
|
|
148 static inline _uw
|
|
149 selfrel_offset31 (const _uw *p)
|
|
150 {
|
|
151 _uw offset;
|
|
152
|
|
153 offset = *p << 1;
|
|
154 return offset + (_uw) p;
|
|
155 }
|
|
156
|
|
157
|
|
158 static _uw
|
|
159 __gnu_unwind_get_pr_addr (int idx)
|
|
160 {
|
|
161 switch (idx)
|
|
162 {
|
|
163 case 0:
|
|
164 return (_uw) &__c6xabi_unwind_cpp_pr0;
|
|
165
|
|
166 case 1:
|
|
167 return (_uw) &__c6xabi_unwind_cpp_pr1;
|
|
168
|
|
169 case 2:
|
|
170 return (_uw) &__c6xabi_unwind_cpp_pr2;
|
|
171
|
|
172 case 3:
|
|
173 return (_uw) &__c6xabi_unwind_cpp_pr3;
|
|
174
|
|
175 case 4:
|
|
176 return (_uw) &__c6xabi_unwind_cpp_pr4;
|
|
177
|
|
178 default:
|
|
179 return 0;
|
|
180 }
|
|
181 }
|
|
182
|
|
183
|
|
184 /* ABI defined personality routine entry points. */
|
|
185
|
|
186 _Unwind_Reason_Code
|
|
187 __c6xabi_unwind_cpp_pr0 (_Unwind_State state,
|
|
188 _Unwind_Control_Block *ucbp,
|
|
189 _Unwind_Context *context)
|
|
190 {
|
|
191 return __gnu_unwind_pr_common (state, ucbp, context, 0);
|
|
192 }
|
|
193
|
|
194 _Unwind_Reason_Code
|
|
195 __c6xabi_unwind_cpp_pr1 (_Unwind_State state,
|
|
196 _Unwind_Control_Block *ucbp,
|
|
197 _Unwind_Context *context)
|
|
198 {
|
|
199 return __gnu_unwind_pr_common (state, ucbp, context, 1);
|
|
200 }
|
|
201
|
|
202 _Unwind_Reason_Code
|
|
203 __c6xabi_unwind_cpp_pr2 (_Unwind_State state,
|
|
204 _Unwind_Control_Block *ucbp,
|
|
205 _Unwind_Context *context)
|
|
206 {
|
|
207 return __gnu_unwind_pr_common (state, ucbp, context, 2);
|
|
208 }
|
|
209
|
|
210 _Unwind_Reason_Code
|
|
211 __c6xabi_unwind_cpp_pr3 (_Unwind_State state,
|
|
212 _Unwind_Control_Block *ucbp,
|
|
213 _Unwind_Context *context)
|
|
214 {
|
|
215 return __gnu_unwind_pr_common (state, ucbp, context, 3);
|
|
216 }
|
|
217
|
|
218 _Unwind_Reason_Code
|
|
219 __c6xabi_unwind_cpp_pr4 (_Unwind_State state,
|
|
220 _Unwind_Control_Block *ucbp,
|
|
221 _Unwind_Context *context)
|
|
222 {
|
|
223 return __gnu_unwind_pr_common (state, ucbp, context, 4);
|
|
224 }
|