[NDS32] Support Linux target for nds32.
[official-gcc.git] / libgcc / config / nds32 / linux-unwind.h
blob921edf906ea7a6b55335710f5cc883a1ce7984cc
1 /* DWARF2 EH unwinding support for NDS32 Linux signal frame.
2 Copyright (C) 2014-2015 Free Software Foundation, Inc.
3 Contributed by Andes Technology Corporation.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published
9 by the Free Software Foundation; either version 3, or (at your
10 option) any later version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
26 #ifndef inhibit_libc
28 /* Do code reading to identify a signal frame, and set the frame
29 state data appropriately. See unwind-dw2.c for the structs.
30 The corresponding bits in the Linux kernel are in
31 arch/nds32/kernel/signal.c. */
33 #include <signal.h>
34 #include <asm/unistd.h>
36 /* Exactly the same layout as the kernel structures, unique names. */
38 /* arch/nds32/kernel/signal.c */
39 struct _sigframe {
40 struct ucontext uc;
41 unsigned long retcode;
44 struct _rt_sigframe {
45 siginfo_t info;
46 struct _sigframe sig;
48 #define SIGRETURN 0xeb0e0a64
49 #define RT_SIGRETURN 0xab150a64
51 #define MD_FALLBACK_FRAME_STATE_FOR nds32_fallback_frame_state
53 /* This function is supposed to be invoked by uw_frame_state_for()
54 when there is no unwind data available.
56 Generally, given the _Unwind_Context CONTEXT for a stack frame,
57 we need to look up its caller and decode information into FS.
58 However, if the exception handling happens within a signal handler,
59 the return address of signal handler is a special module, which
60 contains signal return syscall and has no FDE in the .eh_frame section.
61 We need to implement MD_FALLBACK_FRAME_STATE_FOR so that we can
62 unwind through signal frames. */
63 static _Unwind_Reason_Code
64 nds32_fallback_frame_state (struct _Unwind_Context *context,
65 _Unwind_FrameState *fs)
67 u_int32_t *pc = (u_int32_t *) context->ra;
68 struct sigcontext *sc_;
69 _Unwind_Ptr new_cfa;
71 #ifdef __NDS32_EB__
72 #error "Signal handler is not supported for force unwind."
73 #endif
75 if ((_Unwind_Ptr) pc & 3)
76 return _URC_END_OF_STACK;
78 /* Check if we are going through a signal handler.
79 See arch/nds32/kernel/signal.c implementation.
80 SWI_SYS_SIGRETURN -> (0xeb0e0a64)
81 SWI_SYS_RT_SIGRETURN -> (0xab150a64)
82 FIXME: Currently we only handle little endian (EL) case. */
83 if (pc[0] == SIGRETURN)
85 /* Using '_sigfame' memory address to locate kernal's sigcontext.
86 The sigcontext structures in arch/nds32/include/asm/sigcontext.h. */
87 struct _sigframe *rt_;
88 rt_ = context->cfa;
89 sc_ = &rt_->uc.uc_mcontext;
91 else if (pc[0] == RT_SIGRETURN)
93 /* Using '_sigfame' memory address to locate kernal's sigcontext. */
94 struct _rt_sigframe *rt_;
95 rt_ = context->cfa;
96 sc_ = &rt_->sig.uc.uc_mcontext;
98 else
99 return _URC_END_OF_STACK;
101 /* Update cfa from sigcontext. */
102 new_cfa = (_Unwind_Ptr) sc_;
103 fs->regs.cfa_how = CFA_REG_OFFSET;
104 fs->regs.cfa_reg = STACK_POINTER_REGNUM;
105 fs->regs.cfa_offset = new_cfa - (_Unwind_Ptr) context->cfa;
107 #define NDS32_PUT_FS_REG(NUM, NAME) \
108 (fs->regs.reg[NUM].how = REG_SAVED_OFFSET, \
109 fs->regs.reg[NUM].loc.offset = (_Unwind_Ptr) &(sc_->NAME) - new_cfa)
111 /* Restore all registers value. */
112 NDS32_PUT_FS_REG (0, nds32_r0);
113 NDS32_PUT_FS_REG (1, nds32_r1);
114 NDS32_PUT_FS_REG (2, nds32_r2);
115 NDS32_PUT_FS_REG (3, nds32_r3);
116 NDS32_PUT_FS_REG (4, nds32_r4);
117 NDS32_PUT_FS_REG (5, nds32_r5);
118 NDS32_PUT_FS_REG (6, nds32_r6);
119 NDS32_PUT_FS_REG (7, nds32_r7);
120 NDS32_PUT_FS_REG (8, nds32_r8);
121 NDS32_PUT_FS_REG (9, nds32_r9);
122 NDS32_PUT_FS_REG (10, nds32_r10);
123 NDS32_PUT_FS_REG (11, nds32_r11);
124 NDS32_PUT_FS_REG (12, nds32_r12);
125 NDS32_PUT_FS_REG (13, nds32_r13);
126 NDS32_PUT_FS_REG (14, nds32_r14);
127 NDS32_PUT_FS_REG (15, nds32_r15);
128 NDS32_PUT_FS_REG (16, nds32_r16);
129 NDS32_PUT_FS_REG (17, nds32_r17);
130 NDS32_PUT_FS_REG (18, nds32_r18);
131 NDS32_PUT_FS_REG (19, nds32_r19);
132 NDS32_PUT_FS_REG (20, nds32_r20);
133 NDS32_PUT_FS_REG (21, nds32_r21);
134 NDS32_PUT_FS_REG (22, nds32_r22);
135 NDS32_PUT_FS_REG (23, nds32_r23);
136 NDS32_PUT_FS_REG (24, nds32_r24);
137 NDS32_PUT_FS_REG (25, nds32_r25);
139 NDS32_PUT_FS_REG (28, nds32_fp);
140 NDS32_PUT_FS_REG (29, nds32_gp);
141 NDS32_PUT_FS_REG (30, nds32_lp);
142 NDS32_PUT_FS_REG (31, nds32_sp);
144 /* Restore PC, point to trigger signal instruction. */
145 NDS32_PUT_FS_REG (32, nds32_ipc);
147 #undef NDS32_PUT_FS_REG
149 /* The retaddr is PC, use PC to find FDE. */
150 fs->retaddr_column = 32;
151 fs->signal_frame = 1;
153 return _URC_NO_REASON;
156 #endif