1 /* DWARF2 EH unwinding support for Linux/m68k.
2 Copyright (C) 2006-2013 Free Software Foundation, Inc.
4 This file is part of GCC.
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)
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.
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.
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/>. */
25 /* Do code reading to identify a signal frame, and set the frame
26 state data appropriately. See unwind-dw2.c for the structs.
27 Don't use this at all if inhibit_libc is used. */
33 /* <sys/ucontext.h> is unfortunately broken right now. */
35 unsigned long uc_flags
;
36 struct ucontext
*uc_link
;
38 mcontext_t uc_mcontext
;
39 unsigned long uc_filler
[80];
40 __sigset_t uc_sigmask
;
43 #define MD_FALLBACK_FRAME_STATE_FOR m68k_fallback_frame_state
46 #define M68K_FP_SIZE 8
48 #define M68K_FP_SIZE 12
51 static _Unwind_Reason_Code
52 m68k_fallback_frame_state (struct _Unwind_Context
*context
,
53 _Unwind_FrameState
*fs
)
55 unsigned short *pc
= context
->ra
;
58 /* moveq #__NR_sigreturn,%d0; trap #0 */
59 if (pc
[0] == 0x7077 && pc
[1] == 0x4e40)
61 struct sigcontext
*sc
;
63 /* Context is passed as the 3rd argument. */
64 sc
= *(struct sigcontext
**) (context
->cfa
+ 8);
67 fs
->regs
.cfa_how
= CFA_REG_OFFSET
;
68 fs
->regs
.cfa_reg
= 15;
69 fs
->regs
.cfa_offset
= cfa
- (long) context
->cfa
;
71 fs
->regs
.reg
[0].how
= REG_SAVED_OFFSET
;
72 fs
->regs
.reg
[0].loc
.offset
= (long) &sc
->sc_d0
- cfa
;
73 fs
->regs
.reg
[1].how
= REG_SAVED_OFFSET
;
74 fs
->regs
.reg
[1].loc
.offset
= (long) &sc
->sc_d1
- cfa
;
75 fs
->regs
.reg
[8].how
= REG_SAVED_OFFSET
;
76 fs
->regs
.reg
[8].loc
.offset
= (long) &sc
->sc_a0
- cfa
;
77 fs
->regs
.reg
[9].how
= REG_SAVED_OFFSET
;
78 fs
->regs
.reg
[9].loc
.offset
= (long) &sc
->sc_a1
- cfa
;
81 fs
->regs
.reg
[13].how
= REG_SAVED_OFFSET
;
82 fs
->regs
.reg
[13].loc
.offset
= (long) &sc
->sc_a5
- cfa
;
85 fs
->regs
.reg
[24].how
= REG_SAVED_OFFSET
;
86 fs
->regs
.reg
[24].loc
.offset
= (long) &sc
->sc_pc
- cfa
;
89 if (*(int *) sc
->sc_fpstate
)
91 int *fpregs
= (int *) sc
->sc_fpregs
;
93 fs
->regs
.reg
[16].how
= REG_SAVED_OFFSET
;
94 fs
->regs
.reg
[16].loc
.offset
= (long) &fpregs
[0] - cfa
;
95 fs
->regs
.reg
[17].how
= REG_SAVED_OFFSET
;
96 fs
->regs
.reg
[17].loc
.offset
= (long) &fpregs
[M68K_FP_SIZE
/4] - cfa
;
98 #elif defined __mcffpu__
99 # error Implement this when uClinux kernel is ported to an FPU architecture
103 /* move.l #__NR_rt_sigreturn,%d0; trap #0 */
104 else if (pc
[0] == 0x203c && pc
[1] == 0x0000 &&
105 pc
[2] == 0x00ad && pc
[3] == 0x4e40)
107 /* moveq #~__NR_rt_sigreturn,%d0; not.b %d0; trap #0 */
108 else if (pc
[0] == 0x7052 && pc
[1] == 0x4600 && pc
[2] == 0x4e40)
111 struct uw_ucontext
*uc
;
115 /* Context is passed as the 3rd argument. */
116 uc
= *(struct uw_ucontext
**) (context
->cfa
+ 8);
118 gregs
= uc
->uc_mcontext
.gregs
;
120 fs
->regs
.cfa_how
= CFA_REG_OFFSET
;
121 fs
->regs
.cfa_reg
= 15;
122 fs
->regs
.cfa_offset
= cfa
- (long) context
->cfa
;
124 /* register %d0-%d7/%a0-%a6 */
125 for (i
= 0; i
<= 14; i
++)
127 fs
->regs
.reg
[i
].how
= REG_SAVED_OFFSET
;
128 fs
->regs
.reg
[i
].loc
.offset
= (long) &gregs
[i
] - cfa
;
132 fs
->regs
.reg
[24].how
= REG_SAVED_OFFSET
;
133 fs
->regs
.reg
[24].loc
.offset
= (long) &gregs
[16] - cfa
;
135 #define uc_fpstate uc_filler[0]
139 long fpregs
= (long) uc
->uc_mcontext
.fpregs
.f_fpregs
;
141 /* register %fp0-%fp7 */
142 for (i
= 16; i
<= 23; i
++)
144 fs
->regs
.reg
[i
].how
= REG_SAVED_OFFSET
;
145 fs
->regs
.reg
[i
].loc
.offset
= fpregs
- cfa
;
146 fpregs
+= M68K_FP_SIZE
;
151 return _URC_END_OF_STACK
;
153 fs
->retaddr_column
= 24;
154 fs
->signal_frame
= 1;
156 return _URC_NO_REASON
;
158 #endif /* ifdef inhibit_libc */