]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/rs6000/darwin-fallback.c
haifa-sched.c (insn_finishes_cycle_p): New static function.
[thirdparty/gcc.git] / gcc / config / rs6000 / darwin-fallback.c
CommitLineData
f8a57be8 1/* Fallback frame-state unwinder for Darwin.
748086b7 2 Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
f8a57be8
GK
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
748086b7 8 the Free Software Foundation; either version 3, or (at your option)
f8a57be8
GK
9 any later version.
10
f8a57be8
GK
11 GCC is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
15
748086b7
JJ
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/>. */
f8a57be8 24
49522de2
GK
25#ifdef __ppc__
26
f8a57be8
GK
27#include "tconfig.h"
28#include "tsystem.h"
29#include "coretypes.h"
30#include "tm.h"
bbf531f0 31#include "elf/dwarf2.h"
f8a57be8
GK
32#include "unwind.h"
33#include "unwind-dw2.h"
34#include <stdint.h>
35#include <stdbool.h>
7880e30b 36#include <sys/types.h>
f8a57be8 37#include <signal.h>
f8a57be8 38
1de43f85
DE
39#define R_LR 65
40#define R_CTR 66
41#define R_CR2 70
42#define R_XER 76
43#define R_VR0 77
44#define R_VRSAVE 109
45#define R_VSCR 110
46#define R_SPEFSCR 112
47
f8a57be8
GK
48typedef unsigned long reg_unit;
49
50/* Place in GPRS the parameters to the first 'sc' instruction that would
51 have been executed if we were returning from this CONTEXT, or
52 return false if an unexpected instruction is encountered. */
53
54static bool
55interpret_libc (reg_unit gprs[32], struct _Unwind_Context *context)
56{
57 uint32_t *pc = (uint32_t *)_Unwind_GetIP (context);
58 uint32_t cr;
59 reg_unit lr = (reg_unit) pc;
60 reg_unit ctr = 0;
61 uint32_t *invalid_address = NULL;
62
63 int i;
64
65 for (i = 0; i < 13; i++)
66 gprs[i] = 1;
67 gprs[1] = _Unwind_GetCFA (context);
68 for (; i < 32; i++)
69 gprs[i] = _Unwind_GetGR (context, i);
fb0671a8 70 cr = _Unwind_GetGR (context, R_CR2);
f8a57be8
GK
71
72 /* For each supported Libc, we have to track the code flow
73 all the way back into the kernel.
74
75 This code is believed to support all released Libc/Libsystem builds since
76 Jaguar 6C115, including all the security updates. To be precise,
77
78 Libc Libsystem Build(s)
79 262~1 60~37 6C115
80 262~1 60.2~4 6D52
81 262~1 61~3 6F21-6F22
82 262~1 63~24 6G30-6G37
83 262~1 63~32 6I34-6I35
84 262~1 63~64 6L29-6L60
85 262.4.1~1 63~84 6L123-6R172
86
87 320~1 71~101 7B85-7D28
88 320~1 71~266 7F54-7F56
89 320~1 71~288 7F112
90 320~1 71~289 7F113
91 320.1.3~1 71.1.1~29 7H60-7H105
92 320.1.3~1 71.1.1~30 7H110-7H113
93 320.1.3~1 71.1.1~31 7H114
94
95 That's a big table! It would be insane to try to keep track of
96 every little detail, so we just read the code itself and do what
97 it would do.
98 */
99
100 for (;;)
101 {
102 uint32_t ins = *pc++;
103
104 if ((ins & 0xFC000003) == 0x48000000) /* b instruction */
105 {
106 pc += ((((int32_t) ins & 0x3FFFFFC) ^ 0x2000000) - 0x2000004) / 4;
107 continue;
108 }
109 if ((ins & 0xFC600000) == 0x2C000000) /* cmpwi */
110 {
111 int32_t val1 = (int16_t) ins;
112 int32_t val2 = gprs[ins >> 16 & 0x1F];
113 /* Only beq and bne instructions are supported, so we only
114 need to set the EQ bit. */
115 uint32_t mask = 0xF << ((ins >> 21 & 0x1C) ^ 0x1C);
116 if (val1 == val2)
117 cr |= mask;
118 else
119 cr &= ~mask;
120 continue;
121 }
122 if ((ins & 0xFEC38003) == 0x40820000) /* forwards beq/bne */
123 {
124 if ((cr >> ((ins >> 16 & 0x1F) ^ 0x1F) & 1) == (ins >> 24 & 1))
125 pc += (ins & 0x7FFC) / 4 - 1;
126 continue;
127 }
128 if ((ins & 0xFC0007FF) == 0x7C000378) /* or, including mr */
129 {
130 gprs [ins >> 16 & 0x1F] = (gprs [ins >> 11 & 0x1F]
131 | gprs [ins >> 21 & 0x1F]);
132 continue;
133 }
134 if (ins >> 26 == 0x0E) /* addi, including li */
135 {
136 reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
137 gprs [ins >> 21 & 0x1F] = src + (int16_t) ins;
138 continue;
139 }
140 if (ins >> 26 == 0x0F) /* addis, including lis */
141 {
142 reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
143 gprs [ins >> 21 & 0x1F] = src + ((int16_t) ins << 16);
144 continue;
145 }
146 if (ins >> 26 == 0x20) /* lwz */
147 {
148 reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
149 uint32_t *p = (uint32_t *)(src + (int16_t) ins);
150 if (p == invalid_address)
151 return false;
152 gprs [ins >> 21 & 0x1F] = *p;
153 continue;
154 }
155 if (ins >> 26 == 0x21) /* lwzu */
156 {
157 uint32_t *p = (uint32_t *)(gprs [ins >> 16 & 0x1F] += (int16_t) ins);
158 if (p == invalid_address)
159 return false;
160 gprs [ins >> 21 & 0x1F] = *p;
161 continue;
162 }
163 if (ins >> 26 == 0x24) /* stw */
164 /* What we hope this is doing is '--in_sigtramp'. We don't want
165 to actually store to memory, so just make a note of the
166 address and refuse to load from it. */
167 {
168 reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
169 uint32_t *p = (uint32_t *)(src + (int16_t) ins);
170 if (p == NULL || invalid_address != NULL)
171 return false;
172 invalid_address = p;
173 continue;
174 }
175 if (ins >> 26 == 0x2E) /* lmw */
176 {
177 reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
178 uint32_t *p = (uint32_t *)(src + (int16_t) ins);
179 int i;
180
181 for (i = (ins >> 21 & 0x1F); i < 32; i++)
182 {
183 if (p == invalid_address)
184 return false;
185 gprs[i] = *p++;
186 }
187 continue;
188 }
189 if ((ins & 0xFC1FFFFF) == 0x7c0803a6) /* mtlr */
190 {
191 lr = gprs [ins >> 21 & 0x1F];
192 continue;
193 }
194 if ((ins & 0xFC1FFFFF) == 0x7c0802a6) /* mflr */
195 {
196 gprs [ins >> 21 & 0x1F] = lr;
197 continue;
198 }
199 if ((ins & 0xFC1FFFFF) == 0x7c0903a6) /* mtctr */
200 {
201 ctr = gprs [ins >> 21 & 0x1F];
202 continue;
203 }
204 /* The PowerPC User's Manual says that bit 11 of the mtcrf
205 instruction is reserved and should be set to zero, but it
206 looks like the Darwin assembler doesn't do that... */
207 if ((ins & 0xFC000FFF) == 0x7c000120) /* mtcrf */
208 {
209 int i;
210 uint32_t mask = 0;
211 for (i = 0; i < 8; i++)
212 mask |= ((-(ins >> (12 + i) & 1)) & 0xF) << 4 * i;
213 cr = (cr & ~mask) | (gprs [ins >> 21 & 0x1F] & mask);
214 continue;
215 }
216 if (ins == 0x429f0005) /* bcl- 20,4*cr7+so,.+4, loads pc into LR */
217 {
218 lr = (reg_unit) pc;
219 continue;
220 }
221 if (ins == 0x4e800420) /* bctr */
222 {
223 pc = (uint32_t *) ctr;
224 continue;
225 }
226 if (ins == 0x44000002) /* sc */
227 return true;
228
229 return false;
230 }
231}
232
7880e30b
GK
233/* We used to include <ucontext.h> and <mach/thread_status.h>,
234 but they change so much between different Darwin system versions
235 that it's much easier to just write the structures involved here
236 directly. */
237
f8a57be8
GK
238/* These defines are from the kernel's bsd/dev/ppc/unix_signal.c. */
239#define UC_TRAD 1
240#define UC_TRAD_VEC 6
241#define UC_TRAD64 20
242#define UC_TRAD64_VEC 25
243#define UC_FLAVOR 30
244#define UC_FLAVOR_VEC 35
245#define UC_FLAVOR64 40
246#define UC_FLAVOR64_VEC 45
247#define UC_DUAL 50
248#define UC_DUAL_VEC 55
249
7880e30b
GK
250struct gcc_ucontext
251{
252 int onstack;
253 sigset_t sigmask;
254 void * stack_sp;
255 size_t stack_sz;
256 int stack_flags;
257 struct gcc_ucontext *link;
258 size_t mcsize;
259 struct gcc_mcontext32 *mcontext;
260};
261
262struct gcc_float_vector_state
263{
264 double fpregs[32];
265 uint32_t fpscr_pad;
266 uint32_t fpscr;
267 uint32_t save_vr[32][4];
268 uint32_t save_vscr[4];
269};
270
271struct gcc_mcontext32 {
272 uint32_t dar;
273 uint32_t dsisr;
274 uint32_t exception;
275 uint32_t padding1[5];
276 uint32_t srr0;
277 uint32_t srr1;
278 uint32_t gpr[32];
279 uint32_t cr;
280 uint32_t xer;
281 uint32_t lr;
282 uint32_t ctr;
283 uint32_t mq;
284 uint32_t vrsave;
285 struct gcc_float_vector_state fvs;
286};
287
f8a57be8
GK
288/* These are based on /usr/include/ppc/ucontext.h and
289 /usr/include/mach/ppc/thread_status.h, but rewritten to be more
290 convenient, to compile on Jaguar, and to work around Radar 3712064
291 on Panther, which is that the 'es' field of 'struct mcontext64' has
292 the wrong type (doh!). */
293
294struct gcc_mcontext64 {
295 uint64_t dar;
296 uint32_t dsisr;
297 uint32_t exception;
298 uint32_t padding1[4];
299 uint64_t srr0;
300 uint64_t srr1;
301 uint32_t gpr[32][2];
302 uint32_t cr;
303 uint32_t xer[2]; /* These are arrays because the original structure has them misaligned. */
304 uint32_t lr[2];
305 uint32_t ctr[2];
306 uint32_t vrsave;
7880e30b 307 struct gcc_float_vector_state fvs;
f8a57be8
GK
308};
309
310#define UC_FLAVOR_SIZE \
7880e30b 311 (sizeof (struct gcc_mcontext32) - 33*16)
f8a57be8 312
7880e30b 313#define UC_FLAVOR_VEC_SIZE (sizeof (struct gcc_mcontext32))
f8a57be8
GK
314
315#define UC_FLAVOR64_SIZE \
7880e30b 316 (sizeof (struct gcc_mcontext64) - 33*16)
f8a57be8
GK
317
318#define UC_FLAVOR64_VEC_SIZE (sizeof (struct gcc_mcontext64))
319
320/* Given GPRS as input to a 'sc' instruction, and OLD_CFA, update FS
321 to represent the execution of a signal return; or, if not a signal
322 return, return false. */
323
324static bool
325handle_syscall (_Unwind_FrameState *fs, const reg_unit gprs[32],
326 _Unwind_Ptr old_cfa)
327{
7880e30b 328 struct gcc_ucontext *uctx;
f8a57be8 329 bool is_64, is_vector;
7880e30b 330 struct gcc_float_vector_state * float_vector_state;
f8a57be8
GK
331 _Unwind_Ptr new_cfa;
332 int i;
333 static _Unwind_Ptr return_addr;
334
335 /* Yay! We're in a Libc that we understand, and it's made a
49522de2
GK
336 system call. In Jaguar, this is a direct system call with value 103;
337 in Panther and Tiger it is a SYS_syscall call for system call number 184,
338 and in Leopard it is a direct syscall with number 184. */
f8a57be8
GK
339
340 if (gprs[0] == 0x67 /* SYS_SIGRETURN */)
341 {
7880e30b
GK
342 uctx = (struct gcc_ucontext *) gprs[3];
343 is_vector = (uctx->mcsize == UC_FLAVOR64_VEC_SIZE
344 || uctx->mcsize == UC_FLAVOR_VEC_SIZE);
345 is_64 = (uctx->mcsize == UC_FLAVOR64_VEC_SIZE
346 || uctx->mcsize == UC_FLAVOR64_SIZE);
f8a57be8 347 }
49522de2 348 else if (gprs[0] == 0 /* SYS_syscall */ && gprs[3] == 184)
f8a57be8
GK
349 {
350 int ctxstyle = gprs[5];
7880e30b 351 uctx = (struct gcc_ucontext *) gprs[4];
f8a57be8
GK
352 is_vector = (ctxstyle == UC_FLAVOR_VEC || ctxstyle == UC_FLAVOR64_VEC
353 || ctxstyle == UC_TRAD_VEC || ctxstyle == UC_TRAD64_VEC);
354 is_64 = (ctxstyle == UC_FLAVOR64_VEC || ctxstyle == UC_TRAD64_VEC
355 || ctxstyle == UC_FLAVOR64 || ctxstyle == UC_TRAD64);
356 }
49522de2
GK
357 else if (gprs[0] == 184 /* SYS_sigreturn */)
358 {
359 int ctxstyle = gprs[4];
360 uctx = (struct gcc_ucontext *) gprs[3];
361 is_vector = (ctxstyle == UC_FLAVOR_VEC || ctxstyle == UC_FLAVOR64_VEC
362 || ctxstyle == UC_TRAD_VEC || ctxstyle == UC_TRAD64_VEC);
363 is_64 = (ctxstyle == UC_FLAVOR64_VEC || ctxstyle == UC_TRAD64_VEC
364 || ctxstyle == UC_FLAVOR64 || ctxstyle == UC_TRAD64);
365 }
f8a57be8
GK
366 else
367 return false;
368
369#define set_offset(r, addr) \
370 (fs->regs.reg[r].how = REG_SAVED_OFFSET, \
371 fs->regs.reg[r].loc.offset = (_Unwind_Ptr)(addr) - new_cfa)
372
373 /* Restore even the registers that are not call-saved, since they
374 might be being used in the prologue to save other registers,
375 for instance GPR0 is sometimes used to save LR. */
376
377 /* Handle the GPRs, and produce the information needed to do the rest. */
378 if (is_64)
379 {
380 /* The context is 64-bit, but it doesn't carry any extra information
381 for us because only the low 32 bits of the registers are
382 call-saved. */
7880e30b 383 struct gcc_mcontext64 *m64 = (struct gcc_mcontext64 *)uctx->mcontext;
f8a57be8
GK
384 int i;
385
7880e30b 386 float_vector_state = &m64->fvs;
f8a57be8
GK
387
388 new_cfa = m64->gpr[1][1];
389
1de43f85 390 set_offset (R_CR2, &m64->cr);
f8a57be8
GK
391 for (i = 0; i < 32; i++)
392 set_offset (i, m64->gpr[i] + 1);
1de43f85
DE
393 set_offset (R_XER, m64->xer + 1);
394 set_offset (R_LR, m64->lr + 1);
395 set_offset (R_CTR, m64->ctr + 1);
f8a57be8 396 if (is_vector)
1de43f85 397 set_offset (R_VRSAVE, &m64->vrsave);
f8a57be8
GK
398
399 /* Sometimes, srr0 points to the instruction that caused the exception,
400 and sometimes to the next instruction to be executed; we want
401 the latter. */
402 if (m64->exception == 3 || m64->exception == 4
403 || m64->exception == 6
404 || (m64->exception == 7 && !(m64->srr1 & 0x10000)))
405 return_addr = m64->srr0 + 4;
406 else
407 return_addr = m64->srr0;
408 }
409 else
410 {
7880e30b 411 struct gcc_mcontext32 *m = uctx->mcontext;
f8a57be8
GK
412 int i;
413
7880e30b 414 float_vector_state = &m->fvs;
f8a57be8 415
7880e30b 416 new_cfa = m->gpr[1];
f8a57be8 417
1de43f85 418 set_offset (R_CR2, &m->cr);
f8a57be8 419 for (i = 0; i < 32; i++)
7880e30b 420 set_offset (i, m->gpr + i);
1de43f85
DE
421 set_offset (R_XER, &m->xer);
422 set_offset (R_LR, &m->lr);
423 set_offset (R_CTR, &m->ctr);
f8a57be8
GK
424
425 if (is_vector)
1de43f85 426 set_offset (R_VRSAVE, &m->vrsave);
f8a57be8
GK
427
428 /* Sometimes, srr0 points to the instruction that caused the exception,
429 and sometimes to the next instruction to be executed; we want
430 the latter. */
7880e30b
GK
431 if (m->exception == 3 || m->exception == 4
432 || m->exception == 6
433 || (m->exception == 7 && !(m->srr1 & 0x10000)))
434 return_addr = m->srr0 + 4;
f8a57be8 435 else
7880e30b 436 return_addr = m->srr0;
f8a57be8
GK
437 }
438
6673f90b
NF
439 fs->regs.cfa_how = CFA_REG_OFFSET;
440 fs->regs.cfa_reg = STACK_POINTER_REGNUM;
441 fs->regs.cfa_offset = new_cfa - old_cfa;;
f8a57be8
GK
442
443 /* The choice of column for the return address is somewhat tricky.
444 Fortunately, the actual choice is private to this file, and
445 the space it's reserved from is the GCC register space, not the
446 DWARF2 numbering. So any free element of the right size is an OK
447 choice. Thus: */
448 fs->retaddr_column = ARG_POINTER_REGNUM;
449 /* FIXME: this should really be done using a DWARF2 location expression,
450 not using a static variable. In fact, this entire file should
451 be implemented in DWARF2 expressions. */
452 set_offset (ARG_POINTER_REGNUM, &return_addr);
453
454 for (i = 0; i < 32; i++)
7880e30b 455 set_offset (32 + i, float_vector_state->fpregs + i);
1de43f85 456 set_offset (R_SPEFSCR, &float_vector_state->fpscr);
f8a57be8
GK
457
458 if (is_vector)
459 {
460 for (i = 0; i < 32; i++)
1de43f85
DE
461 set_offset (R_VR0 + i, float_vector_state->save_vr + i);
462 set_offset (R_VSCR, float_vector_state->save_vscr);
f8a57be8
GK
463 }
464
465 return true;
466}
467
468/* This is also prototyped in rs6000/darwin.h, inside the
469 MD_FALLBACK_FRAME_STATE_FOR macro. */
470extern bool _Unwind_fallback_frame_state_for (struct _Unwind_Context *context,
471 _Unwind_FrameState *fs);
472
473/* Implement the MD_FALLBACK_FRAME_STATE_FOR macro,
474 returning true iff the frame was a sigreturn() frame that we
475 can understand. */
476
477bool
478_Unwind_fallback_frame_state_for (struct _Unwind_Context *context,
479 _Unwind_FrameState *fs)
480{
481 reg_unit gprs[32];
482
483 if (!interpret_libc (gprs, context))
484 return false;
485 return handle_syscall (fs, gprs, _Unwind_GetCFA (context));
486}
49522de2 487#endif