1/* C6X ABI compliant unwinding routines
2   Copyright (C) 2011-2015 Free Software Foundation, Inc.
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/* We add a prototype for abort here to avoid creating a dependency on
26   target headers.  */
27extern void abort (void);
28
29typedef struct _ZSt9type_info type_info; /* This names C++ type_info type */
30
31/* Misc constants.  */
32#define R_A0 0
33#define R_A1 1
34#define R_A2 2
35#define R_A3 3
36#define R_A4 4
37#define R_A5 5
38#define R_A6 6
39#define R_A7 7
40#define R_A8 8
41#define R_A9 9
42#define R_A10 10
43#define R_A11 11
44#define R_A12 12
45#define R_A13 13
46#define R_A14 14
47#define R_A15 15
48#define R_B0 16
49#define R_B1 17
50#define R_B2 18
51#define R_B3 19
52#define R_B4 20
53#define R_B5 21
54#define R_B6 22
55#define R_B7 23
56#define R_B8 24
57#define R_B9 25
58#define R_B10 26
59#define R_B11 27
60#define R_B12 28
61#define R_B13 29
62#define R_B14 30
63#define R_B15 31
64
65#define R_SP R_B15
66#define R_PC 33
67
68#define uint32_highbit (((_uw) 1) << 31)
69
70void __attribute__((weak)) __cxa_call_unexpected(_Unwind_Control_Block *ucbp);
71
72/* Unwind descriptors.  */
73
74typedef struct
75{
76  _uw16 length;
77  _uw16 offset;
78} EHT16;
79
80typedef struct
81{
82  _uw length;
83  _uw offset;
84} EHT32;
85
86/* Calculate the address encoded by a 31-bit self-relative offset at address
87   P.  Copy of routine in unwind-arm.c.  */
88
89static inline _uw
90selfrel_offset31 (const _uw *p)
91{
92  _uw offset;
93
94  offset = *p;
95  /* Sign extend to 32 bits.  */
96  if (offset & (1 << 30))
97    offset |= 1u << 31;
98
99  return offset + (_uw) p;
100}
101
102
103/* Personality routine helper functions.  */
104
105#define CODE_FINISH (0xe7)
106
107/* Return the next byte of unwinding information, or CODE_FINISH if there is
108   no data remaining.  */
109static inline _uw8
110next_unwind_byte (__gnu_unwind_state * uws)
111{
112  _uw8 b;
113
114  if (uws->bytes_left == 0)
115    {
116      /* Load another word */
117      if (uws->words_left == 0)
118	return CODE_FINISH; /* Nothing left.  */
119      uws->words_left--;
120      uws->data = *(uws->next++);
121      uws->bytes_left = 3;
122    }
123  else
124    uws->bytes_left--;
125
126  /* Extract the most significant byte.  */
127  b = (uws->data >> 24) & 0xff;
128  uws->data <<= 8;
129  return b;
130}
131
132static void
133unwind_restore_pair (_Unwind_Context * context, int reg, _uw *ptr)
134{
135#ifdef _BIG_ENDIAN
136  _Unwind_VRS_Set (context, _UVRSC_CORE, reg, _UVRSD_UINT32, ptr + 1);
137  _Unwind_VRS_Set (context, _UVRSC_CORE, reg + 1, _UVRSD_UINT32, ptr);
138#else
139  _Unwind_VRS_Set (context, _UVRSC_CORE, reg, _UVRSD_UINT32, ptr);
140  _Unwind_VRS_Set (context, _UVRSC_CORE, reg + 1, _UVRSD_UINT32, ptr + 1);
141#endif
142}
143
144static const int
145unwind_frame_regs[13] =
146{
147  R_A15, R_B15, R_B14, R_B13, R_B12, R_B11, R_B10, R_B3,
148  R_A14, R_A13, R_A12, R_A11, R_A10
149};
150
151static void
152pop_compact_frame (_Unwind_Context * context, _uw mask, _uw *ptr, int inc_sp)
153{
154  int size;
155  _uw test;
156  int i, regno, nregs;
157
158  size = 0;
159  nregs = __builtin_popcount (mask);
160  for (i = 0; i < 13; i++)
161    {
162      test = 1 << i;
163      if ((mask & test) == 0)
164	continue;
165
166      regno = unwind_frame_regs[12 - i];
167
168      if (i < 12 && nregs > 2
169	  && (mask & (test << 1)) != 0
170	  && unwind_frame_regs[11 - i] == regno + 1
171	  && (regno & 1) == 0)
172	{
173	  i++;
174	  nregs--;
175	}
176
177      nregs--;
178      size += 2;
179    }
180
181  if (!inc_sp)
182    ptr -= size;
183
184  /* SP points just past the end of the stack.  */
185  ptr += 2;
186  nregs = __builtin_popcount (mask);
187  for (i = 0; i < 13; i++)
188    {
189      test = 1 << i;
190      if ((mask & test) == 0)
191	continue;
192
193      regno = unwind_frame_regs[12 - i];
194
195      if (i < 12 && nregs > 2
196	  && (mask & (test << 1)) != 0
197	  && unwind_frame_regs[11 - i] == regno + 1
198	  && (regno & 1) == 0)
199	{
200	  /* Register pair.  */
201	  unwind_restore_pair (context, regno, ptr);
202	  i++;
203	  nregs--;
204	}
205      else
206	{
207	  /* Single register with padding.  */
208	  _Unwind_VRS_Set (context, _UVRSC_CORE, regno, _UVRSD_UINT32, ptr);
209	}
210
211      nregs--;
212      ptr += 2;
213    }
214
215  ptr -= 2;
216  if ((mask & (1 << 11)) == 0)
217    _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &ptr);
218}
219
220static void
221pop_frame (_Unwind_Context * context, _uw mask, _uw *ptr, int inc_sp)
222{
223  int i;
224  int regno;
225  int nregs;
226
227  nregs = __builtin_popcount (mask);
228
229  if (!inc_sp)
230    ptr -= nregs;
231  else if (nregs & 1)
232    ptr++;
233
234  ptr++;
235  for (i = 0; i < 13; i++)
236    {
237      if ((mask & (1 << i)) == 0)
238	continue;
239      regno = unwind_frame_regs[12 - i];
240      if (i < 12 && unwind_frame_regs[11 - i] == (regno + 1)
241	  && (mask & (1 << (i + 1))) != 0
242	  && (((_uw)ptr) & 4) == 0
243	  && (regno & 1) == 0)
244	{
245	  unwind_restore_pair (context, regno, ptr);
246	  i++;
247	  ptr += 2;
248	}
249      else
250	{
251	  _Unwind_VRS_Set (context, _UVRSC_CORE, regno, _UVRSD_UINT32,
252			   ptr);
253	  ptr++;
254	}
255    }
256
257  ptr--;
258  if ((mask & (1 << 11)) == 0)
259    _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &ptr);
260}
261
262/* Unwind a 24-bit encoded frame.  */
263_Unwind_Reason_Code
264__gnu_unwind_24bit (_Unwind_Context * context, _uw data, int compact)
265{
266  _uw offset;
267  _uw mask;
268  _uw *ptr;
269  _uw tmp;
270  int ret_reg = unwind_frame_regs[data & 0xf];
271
272  if (ret_reg != R_B3)
273    {
274      _Unwind_VRS_Get (context, _UVRSC_CORE, unwind_frame_regs[data & 0xf],
275		       _UVRSD_UINT32, &tmp);
276      _Unwind_VRS_Set (context, _UVRSC_CORE, R_B3, _UVRSD_UINT32, &tmp);
277    }
278
279  mask = (data >> 4) & 0x1fff;
280
281  offset = (data >> 17) & 0x7f;
282  if (offset == 0x7f)
283    _Unwind_VRS_Get (context, _UVRSC_CORE, R_A15, _UVRSD_UINT32, &ptr);
284  else
285    {
286      _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &ptr);
287      ptr += offset * 2;
288    }
289
290
291  if (compact)
292    pop_compact_frame (context, mask, ptr, offset != 0x7f);
293  else
294    pop_frame (context, mask, ptr, offset != 0x7f);
295
296  _Unwind_VRS_Get (context, _UVRSC_CORE, R_B3, _UVRSD_UINT32, &tmp);
297  _Unwind_VRS_Set (context, _UVRSC_CORE, R_PC, _UVRSD_UINT32, &tmp);
298
299  return _URC_OK;
300}
301
302static void
303unwind_pop_rts (_Unwind_Context * context)
304{
305  _uw *ptr;
306
307  _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &ptr);
308#ifdef _BIG_ENDIAN
309  _Unwind_VRS_Set (context, _UVRSC_CORE, R_B3, _UVRSD_UINT32, ptr + 1);
310#else
311  _Unwind_VRS_Set (context, _UVRSC_CORE, R_B3, _UVRSD_UINT32, ptr + 2);
312#endif
313  ptr += 3;
314  unwind_restore_pair (context, R_A10, ptr);
315  ptr += 2;
316  unwind_restore_pair (context, R_B10, ptr);
317  ptr += 2;
318  unwind_restore_pair (context, R_A12, ptr);
319  ptr += 2;
320  unwind_restore_pair (context, R_B12, ptr);
321  ptr += 2;
322  unwind_restore_pair (context, R_A14, ptr);
323  ptr += 2;
324  _Unwind_VRS_Set (context, _UVRSC_CORE, R_B14, _UVRSD_UINT32, ptr);
325  _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &ptr);
326  /* PC will be set by implicit RETURN opcode.  */
327}
328
329/* Execute the unwinding instructions described by UWS.  */
330_Unwind_Reason_Code
331__gnu_unwind_execute (_Unwind_Context * context, __gnu_unwind_state * uws)
332{
333  _uw op;
334  int inc_sp;
335  _uw reg;
336  _uw *ptr;
337
338  inc_sp = 1;
339  for (;;)
340    {
341      op = next_unwind_byte (uws);
342      if (op == CODE_FINISH)
343	{
344	  /* Drop out of the loop.  */
345	  break;
346	}
347      if ((op & 0xc0) == 0)
348	{
349	  /* sp += (imm6 << 3) + 8.  */
350	  _uw offset;
351
352	  offset = ((op & 0x3f) << 3) + 8;
353	  _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
354	  reg += offset;
355	  _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
356	  continue;
357	}
358
359      if (op == 0xd2)
360	{
361	  /* vsp = vsp + 0x204 + (uleb128 << 2).  */
362	  int shift;
363
364	  _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
365	  op = next_unwind_byte (uws);
366	  shift = 3;
367	  while (op & 0x80)
368	    {
369	      reg += ((op & 0x7f) << shift);
370	      shift += 7;
371	      op = next_unwind_byte (uws);
372	    }
373	  reg += ((op & 0x7f) << shift) + 0x408;
374	  _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
375	  continue;
376	}
377
378      if ((op & 0xe0) == 0x80)
379	{
380	  /* POP bitmask */
381	  _uw mask = ((op & 0x1f) << 8) | next_unwind_byte (uws);
382
383	  if (mask == 0)
384	    {
385	      /* CANTUNWIND */
386	      return _URC_FAILURE;
387	    }
388
389	  _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &ptr);
390	  pop_frame (context, mask, ptr, inc_sp);
391	  continue;
392	}
393
394      if ((op & 0xe0) == 0xa0)
395	{
396	  /* POP bitmask (compact) */
397	  _uw mask = ((op & 0x1f) << 8) | next_unwind_byte (uws);
398
399	  _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &ptr);
400	  pop_compact_frame (context, mask, ptr, inc_sp);
401	  continue;
402	}
403
404      if ((op & 0xf0) == 0xc0)
405	{
406	  /* POP registers */
407	  int nregs = op & 0xf;
408
409	  _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &ptr);
410	  while (nregs > 0)
411	    {
412	      op = next_unwind_byte (uws);
413	      if ((op >> 4) != 0xf)
414		{
415		  reg = unwind_frame_regs[op >> 4];
416		  _Unwind_VRS_Set (context, _UVRSC_CORE, reg, _UVRSD_UINT32,
417				   ptr);
418		  nregs--;
419		}
420	      ptr--;
421	      if ((op & 0xf) != 0xf)
422		{
423		  reg = unwind_frame_regs[op & 0xf];
424		  _Unwind_VRS_Set (context, _UVRSC_CORE, reg, _UVRSD_UINT32,
425				   ptr);
426		  nregs--;
427		}
428	      ptr--;
429	    }
430
431	  continue;
432	}
433
434      if (op == 0xd0)
435	{
436	  /* MV FP, SP */
437	  inc_sp = 0;
438	  _Unwind_VRS_Get (context, _UVRSC_CORE, R_A15, _UVRSD_UINT32, &reg);
439	  _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
440	  continue;
441	}
442
443      if (op == 0xd1)
444	{
445	  /* __cx6abi_pop_rts */
446	  unwind_pop_rts (context);
447	  break;
448	}
449
450      if ((op & 0xf0) == 0xe0)
451	{
452	  /* B3 = reg.  RETURN case alreadh handled above.  */
453	  int regno = unwind_frame_regs[op & 0xf];
454
455	  _Unwind_VRS_Get (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &reg);
456	  _Unwind_VRS_Set (context, _UVRSC_CORE, R_B3, _UVRSD_UINT32, &reg);
457	  continue;
458	}
459
460      /* Reserved.  */
461      return _URC_FAILURE;
462    }
463
464  /* Implicit RETURN.  */
465  _Unwind_VRS_Get (context, _UVRSC_CORE, R_B3, _UVRSD_UINT32, &reg);
466  _Unwind_VRS_Set (context, _UVRSC_CORE, R_PC, _UVRSD_UINT32, &reg);
467  return _URC_OK;
468}
469
470
471/* Execute the unwinding instructions associated with a frame.  UCBP and
472   CONTEXT are the current exception object and virtual CPU state
473   respectively.  */
474
475_Unwind_Reason_Code
476__gnu_unwind_frame (_Unwind_Control_Block * ucbp, _Unwind_Context * context)
477{
478  _uw *ptr;
479  __gnu_unwind_state uws;
480
481  ptr = (_uw *) ucbp->pr_cache.ehtp;
482  /* Skip over the personality routine address.  */
483  ptr++;
484  /* Setup the unwinder state.  */
485  uws.data = (*ptr) << 8;
486  uws.next = ptr + 1;
487  uws.bytes_left = 3;
488  uws.words_left = ((*ptr) >> 24) & 0xff;
489
490  return __gnu_unwind_execute (context, &uws);
491}
492
493/* Data segment base pointer corresponding to the function catching
494   the exception.  */
495
496_Unwind_Ptr
497_Unwind_GetDataRelBase (_Unwind_Context *context)
498{
499  return _Unwind_GetGR (context, R_B14);
500}
501
502/* This should never be used.  */
503
504_Unwind_Ptr
505_Unwind_GetTextRelBase (_Unwind_Context *context __attribute__ ((unused)))
506{
507  abort ();
508}
509
510/* Only used by gcc personality routines, so can rely on a value they hid
511   there earlier.  */
512_Unwind_Ptr
513_Unwind_GetRegionStart (_Unwind_Context *context)
514{
515  _Unwind_Control_Block *ucbp;
516
517  ucbp = (_Unwind_Control_Block *) _Unwind_GetGR (context, UNWIND_POINTER_REG);
518  return (_Unwind_Ptr) ucbp->pr_cache.fnstart;
519}
520
521void *
522_Unwind_GetLanguageSpecificData (_Unwind_Context *context)
523{
524  _Unwind_Control_Block *ucbp;
525  _uw *ptr;
526
527  ucbp = (_Unwind_Control_Block *) _Unwind_GetGR (context, UNWIND_POINTER_REG);
528  ptr = (_uw *) ucbp->pr_cache.ehtp;
529  /* Skip the personality routine address.  */
530  ptr++;
531  /* Skip the unwind opcodes.  */
532  ptr += (((*ptr) >> 24) & 0xff) + 1;
533
534  return ptr;
535}
536