1234353Sdim/* DWARF2 EH unwinding support for Blackfin.
2193323Sed   Copyright (C) 2007-2022 Free Software Foundation, Inc.
3193323Sed
4193323SedThis file is part of GCC.
5193323Sed
6193323SedGCC is free software; you can redistribute it and/or modify
7193323Sedit under the terms of the GNU General Public License as published by
8193323Sedthe Free Software Foundation; either version 3, or (at your option)
9193323Sedany later version.
10193323Sed
11193323SedGCC is distributed in the hope that it will be useful,
12193323Sedbut WITHOUT ANY WARRANTY; without even the implied warranty of
13193323SedMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14234353SdimGNU General Public License for more details.
15193323Sed
16193323SedUnder Section 7 of GPL version 3, you are granted additional
17193323Sedpermissions described in the GCC Runtime Library Exception, version
18193323Sed3.1, as published by the Free Software Foundation.
19193323Sed
20193323SedYou should have received a copy of the GNU General Public License and
21193323Seda copy of the GCC Runtime Library Exception along with this program;
22198090Srdivackysee the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23226633Sdim<http://www.gnu.org/licenses/>.  */
24193323Sed
25224145Sdim/* Do code reading to identify a signal frame, and set the frame
26224145Sdim   state data appropriately.  See unwind-dw2.c for the structs.
27224145Sdim   Don't use this at all if inhibit_libc is used.  */
28193323Sed
29193323Sed#ifndef inhibit_libc
30193323Sed
31224145Sdim#include <signal.h>
32193323Sed#include <sys/ucontext.h>
33193323Sed
34193323Sed#define MD_FALLBACK_FRAME_STATE_FOR bfin_fallback_frame_state
35193323Sed
36193323Sedstatic _Unwind_Reason_Code
37208599Srdivackybfin_fallback_frame_state (struct _Unwind_Context *context,
38208599Srdivacky			   _Unwind_FrameState *fs)
39206124Srdivacky{
40193323Sed  unsigned char *pc = context->ra;
41199481Srdivacky  struct sigcontext *sc;
42199481Srdivacky  long new_cfa;
43193323Sed
44199481Srdivacky  /* P0=__NR_rt_sigreturn (X); EXCPT  0x0; */
45234353Sdim  if (*(unsigned short *)pc == 0xe128
46218893Sdim      && *(unsigned short *)(pc + 2) == 0x00ad
47199481Srdivacky      && *(unsigned short *)(pc + 4) == 0x00a0)
48199481Srdivacky    {
49199481Srdivacky      struct rt_sigframe {
50193323Sed	int sig;
51193323Sed	siginfo_t *pinfo;
52193323Sed	void *puc;
53199481Srdivacky	char retcode[8];
54193323Sed	siginfo_t info;
55193323Sed	ucontext_t uc;
56193323Sed      } *rt_ = context->cfa;
57199481Srdivacky
58193323Sed      /* The void * cast is necessary to avoid an aliasing warning.
59198090Srdivacky         The aliasing warning is correct, but should not be a problem
60193323Sed         because it does not alias anything.  */
61193323Sed      sc = (struct sigcontext *)(void *)&rt_->uc.uc_mcontext.gregs;
62193323Sed    }
63193323Sed  else
64193323Sed    return _URC_END_OF_STACK;
65208599Srdivacky
66208599Srdivacky  new_cfa = sc->sc_usp;
67206124Srdivacky  fs->regs.cfa_how = CFA_REG_OFFSET;
68193323Sed  fs->regs.cfa_reg = 14;
69199481Srdivacky  fs->regs.cfa_offset = new_cfa - (long) context->cfa;
70199481Srdivacky
71193323Sed  fs->regs.reg[0].how = REG_SAVED_OFFSET;
72199481Srdivacky  fs->regs.reg[0].loc.offset = (long)&sc->sc_r0 - new_cfa;
73234353Sdim  fs->regs.reg[1].how = REG_SAVED_OFFSET;
74218893Sdim  fs->regs.reg[1].loc.offset = (long)&sc->sc_r1 - new_cfa;
75199481Srdivacky  fs->regs.reg[2].how = REG_SAVED_OFFSET;
76199481Srdivacky  fs->regs.reg[2].loc.offset = (long)&sc->sc_r2 - new_cfa;
77199481Srdivacky  fs->regs.reg[3].how = REG_SAVED_OFFSET;
78193323Sed  fs->regs.reg[3].loc.offset = (long)&sc->sc_r3 - new_cfa;
79193323Sed  fs->regs.reg[4].how = REG_SAVED_OFFSET;
80199481Srdivacky  fs->regs.reg[4].loc.offset = (long)&sc->sc_r4 - new_cfa;
81193323Sed  fs->regs.reg[5].how = REG_SAVED_OFFSET;
82193323Sed  fs->regs.reg[5].loc.offset = (long)&sc->sc_r5 - new_cfa;
83199481Srdivacky  fs->regs.reg[6].how = REG_SAVED_OFFSET;
84193323Sed  fs->regs.reg[6].loc.offset = (long)&sc->sc_r6 - new_cfa;
85198090Srdivacky  fs->regs.reg[7].how = REG_SAVED_OFFSET;
86193323Sed  fs->regs.reg[7].loc.offset = (long)&sc->sc_r7 - new_cfa;
87193323Sed  fs->regs.reg[8].how = REG_SAVED_OFFSET;
88210299Sed  fs->regs.reg[8].loc.offset = (long)&sc->sc_p0 - new_cfa;
89210299Sed  fs->regs.reg[9].how = REG_SAVED_OFFSET;
90210299Sed  fs->regs.reg[9].loc.offset = (long)&sc->sc_p1 - new_cfa;
91210299Sed  fs->regs.reg[10].how = REG_SAVED_OFFSET;
92210299Sed  fs->regs.reg[10].loc.offset = (long)&sc->sc_p2 - new_cfa;
93210299Sed  fs->regs.reg[11].how = REG_SAVED_OFFSET;
94210299Sed  fs->regs.reg[11].loc.offset = (long)&sc->sc_p3 - new_cfa;
95210299Sed  fs->regs.reg[12].how = REG_SAVED_OFFSET;
96210299Sed  fs->regs.reg[12].loc.offset = (long)&sc->sc_p4 - new_cfa;
97210299Sed  fs->regs.reg[13].how = REG_SAVED_OFFSET;
98210299Sed  fs->regs.reg[13].loc.offset = (long)&sc->sc_p5 - new_cfa;
99193323Sed
100210299Sed  fs->regs.reg[15].how = REG_SAVED_OFFSET;
101210299Sed  fs->regs.reg[15].loc.offset = (long)&sc->sc_fp - new_cfa;
102193323Sed  fs->regs.reg[16].how = REG_SAVED_OFFSET;
103193323Sed  fs->regs.reg[16].loc.offset = (long)&sc->sc_i0 - new_cfa;
104198396Srdivacky  fs->regs.reg[17].how = REG_SAVED_OFFSET;
105198396Srdivacky  fs->regs.reg[17].loc.offset = (long)&sc->sc_i1 - new_cfa;
106198396Srdivacky  fs->regs.reg[18].how = REG_SAVED_OFFSET;
107198396Srdivacky  fs->regs.reg[18].loc.offset = (long)&sc->sc_i2 - new_cfa;
108198396Srdivacky  fs->regs.reg[19].how = REG_SAVED_OFFSET;
109198396Srdivacky  fs->regs.reg[19].loc.offset = (long)&sc->sc_i3 - new_cfa;
110206083Srdivacky  fs->regs.reg[20].how = REG_SAVED_OFFSET;
111206083Srdivacky  fs->regs.reg[20].loc.offset = (long)&sc->sc_b0 - new_cfa;
112198396Srdivacky  fs->regs.reg[21].how = REG_SAVED_OFFSET;
113207618Srdivacky  fs->regs.reg[21].loc.offset = (long)&sc->sc_b1 - new_cfa;
114207618Srdivacky  fs->regs.reg[22].how = REG_SAVED_OFFSET;
115207618Srdivacky  fs->regs.reg[22].loc.offset = (long)&sc->sc_b2 - new_cfa;
116198396Srdivacky  fs->regs.reg[23].how = REG_SAVED_OFFSET;
117198396Srdivacky  fs->regs.reg[23].loc.offset = (long)&sc->sc_b3 - new_cfa;
118198396Srdivacky  fs->regs.reg[24].how = REG_SAVED_OFFSET;
119198396Srdivacky  fs->regs.reg[24].loc.offset = (long)&sc->sc_l0 - new_cfa;
120198396Srdivacky  fs->regs.reg[25].how = REG_SAVED_OFFSET;
121198396Srdivacky  fs->regs.reg[25].loc.offset = (long)&sc->sc_l1 - new_cfa;
122198396Srdivacky  fs->regs.reg[26].how = REG_SAVED_OFFSET;
123198396Srdivacky  fs->regs.reg[26].loc.offset = (long)&sc->sc_l2 - new_cfa;
124198396Srdivacky  fs->regs.reg[27].how = REG_SAVED_OFFSET;
125198396Srdivacky  fs->regs.reg[27].loc.offset = (long)&sc->sc_l3 - new_cfa;
126198396Srdivacky  fs->regs.reg[28].how = REG_SAVED_OFFSET;
127198396Srdivacky  fs->regs.reg[28].loc.offset = (long)&sc->sc_m0 - new_cfa;
128198396Srdivacky  fs->regs.reg[29].how = REG_SAVED_OFFSET;
129198396Srdivacky  fs->regs.reg[29].loc.offset = (long)&sc->sc_m1 - new_cfa;
130198396Srdivacky  fs->regs.reg[30].how = REG_SAVED_OFFSET;
131198396Srdivacky  fs->regs.reg[30].loc.offset = (long)&sc->sc_m2 - new_cfa;
132198396Srdivacky  fs->regs.reg[31].how = REG_SAVED_OFFSET;
133234353Sdim  fs->regs.reg[31].loc.offset = (long)&sc->sc_m3 - new_cfa;
134198396Srdivacky  /* FIXME: Handle A0, A1, CC.  */
135198396Srdivacky  fs->regs.reg[35].how = REG_SAVED_OFFSET;
136198396Srdivacky  fs->regs.reg[35].loc.offset = (long)&sc->sc_rets - new_cfa;
137198396Srdivacky  fs->regs.reg[36].how = REG_SAVED_OFFSET;
138198396Srdivacky  fs->regs.reg[36].loc.offset = (long)&sc->sc_pc - new_cfa;
139198396Srdivacky  fs->regs.reg[37].how = REG_SAVED_OFFSET;
140198396Srdivacky  fs->regs.reg[37].loc.offset = (long)&sc->sc_retx - new_cfa;
141198396Srdivacky
142198396Srdivacky  fs->regs.reg[40].how = REG_SAVED_OFFSET;
143198396Srdivacky  fs->regs.reg[40].loc.offset = (long)&sc->sc_astat - new_cfa;
144198396Srdivacky  fs->regs.reg[41].how = REG_SAVED_OFFSET;
145198396Srdivacky  fs->regs.reg[41].loc.offset = (long)&sc->sc_seqstat - new_cfa;
146198396Srdivacky
147198396Srdivacky  fs->regs.reg[44].how = REG_SAVED_OFFSET;
148198396Srdivacky  fs->regs.reg[44].loc.offset = (long)&sc->sc_lt0 - new_cfa;
149198396Srdivacky  fs->regs.reg[45].how = REG_SAVED_OFFSET;
150198396Srdivacky  fs->regs.reg[45].loc.offset = (long)&sc->sc_lt1 - new_cfa;
151198396Srdivacky  fs->regs.reg[46].how = REG_SAVED_OFFSET;
152198396Srdivacky  fs->regs.reg[46].loc.offset = (long)&sc->sc_lc0 - new_cfa;
153198396Srdivacky  fs->regs.reg[47].how = REG_SAVED_OFFSET;
154198396Srdivacky  fs->regs.reg[47].loc.offset = (long)&sc->sc_lc1 - new_cfa;
155198396Srdivacky  fs->regs.reg[48].how = REG_SAVED_OFFSET;
156198396Srdivacky  fs->regs.reg[48].loc.offset = (long)&sc->sc_lb0 - new_cfa;
157198396Srdivacky  fs->regs.reg[49].how = REG_SAVED_OFFSET;
158198396Srdivacky  fs->regs.reg[49].loc.offset = (long)&sc->sc_lb1 - new_cfa;
159234353Sdim  fs->retaddr_column = 35;
160198396Srdivacky
161198396Srdivacky  return _URC_NO_REASON;
162234353Sdim}
163198396Srdivacky
164234353Sdim#endif /* ifdef inhibit_libc */
165198396Srdivacky