1 /* C6X ABI compliant unwinding routines
2 Copyright (C) 2011-2018 Free Software Foundation, Inc.
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
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.
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.
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/>. */
25 /* We add a prototype for abort here to avoid creating a dependency on
27 extern void abort (void);
29 typedef struct _ZSt9type_info type_info
; /* This names C++ type_info type */
68 #define uint32_highbit (((_uw) 1) << 31)
70 void __attribute__((weak
)) __cxa_call_unexpected(_Unwind_Control_Block
*ucbp
);
72 /* Unwind descriptors. */
86 /* Calculate the address encoded by a 31-bit self-relative offset at address
87 P. Copy of routine in unwind-arm.c. */
90 selfrel_offset31 (const _uw
*p
)
95 /* Sign extend to 32 bits. */
96 if (offset
& (1 << 30))
99 return offset
+ (_uw
) p
;
103 /* Personality routine helper functions. */
105 #define CODE_FINISH (0xe7)
107 /* Return the next byte of unwinding information, or CODE_FINISH if there is
108 no data remaining. */
110 next_unwind_byte (__gnu_unwind_state
* uws
)
114 if (uws
->bytes_left
== 0)
116 /* Load another word */
117 if (uws
->words_left
== 0)
118 return CODE_FINISH
; /* Nothing left. */
120 uws
->data
= *(uws
->next
++);
126 /* Extract the most significant byte. */
127 b
= (uws
->data
>> 24) & 0xff;
133 unwind_restore_pair (_Unwind_Context
* context
, int reg
, _uw
*ptr
)
136 _Unwind_VRS_Set (context
, _UVRSC_CORE
, reg
, _UVRSD_UINT32
, ptr
+ 1);
137 _Unwind_VRS_Set (context
, _UVRSC_CORE
, reg
+ 1, _UVRSD_UINT32
, ptr
);
139 _Unwind_VRS_Set (context
, _UVRSC_CORE
, reg
, _UVRSD_UINT32
, ptr
);
140 _Unwind_VRS_Set (context
, _UVRSC_CORE
, reg
+ 1, _UVRSD_UINT32
, ptr
+ 1);
145 unwind_frame_regs
[13] =
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
152 pop_compact_frame (_Unwind_Context
* context
, _uw mask
, _uw
*ptr
, int inc_sp
)
159 nregs
= __builtin_popcount (mask
);
160 for (i
= 0; i
< 13; i
++)
163 if ((mask
& test
) == 0)
166 regno
= unwind_frame_regs
[12 - i
];
168 if (i
< 12 && nregs
> 2
169 && (mask
& (test
<< 1)) != 0
170 && unwind_frame_regs
[11 - i
] == regno
+ 1
184 /* SP points just past the end of the stack. */
186 nregs
= __builtin_popcount (mask
);
187 for (i
= 0; i
< 13; i
++)
190 if ((mask
& test
) == 0)
193 regno
= unwind_frame_regs
[12 - i
];
195 if (i
< 12 && nregs
> 2
196 && (mask
& (test
<< 1)) != 0
197 && unwind_frame_regs
[11 - i
] == regno
+ 1
201 unwind_restore_pair (context
, regno
, ptr
);
207 /* Single register with padding. */
208 _Unwind_VRS_Set (context
, _UVRSC_CORE
, regno
, _UVRSD_UINT32
, ptr
);
216 if ((mask
& (1 << 11)) == 0)
217 _Unwind_VRS_Set (context
, _UVRSC_CORE
, R_SP
, _UVRSD_UINT32
, &ptr
);
221 pop_frame (_Unwind_Context
* context
, _uw mask
, _uw
*ptr
, int inc_sp
)
227 nregs
= __builtin_popcount (mask
);
235 for (i
= 0; i
< 13; i
++)
237 if ((mask
& (1 << i
)) == 0)
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
245 unwind_restore_pair (context
, regno
, ptr
);
251 _Unwind_VRS_Set (context
, _UVRSC_CORE
, regno
, _UVRSD_UINT32
,
258 if ((mask
& (1 << 11)) == 0)
259 _Unwind_VRS_Set (context
, _UVRSC_CORE
, R_SP
, _UVRSD_UINT32
, &ptr
);
262 /* Unwind a 24-bit encoded frame. */
264 __gnu_unwind_24bit (_Unwind_Context
* context
, _uw data
, int compact
)
270 int ret_reg
= unwind_frame_regs
[data
& 0xf];
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
);
279 mask
= (data
>> 4) & 0x1fff;
281 offset
= (data
>> 17) & 0x7f;
283 _Unwind_VRS_Get (context
, _UVRSC_CORE
, R_A15
, _UVRSD_UINT32
, &ptr
);
286 _Unwind_VRS_Get (context
, _UVRSC_CORE
, R_SP
, _UVRSD_UINT32
, &ptr
);
292 pop_compact_frame (context
, mask
, ptr
, offset
!= 0x7f);
294 pop_frame (context
, mask
, ptr
, offset
!= 0x7f);
296 _Unwind_VRS_Get (context
, _UVRSC_CORE
, R_B3
, _UVRSD_UINT32
, &tmp
);
297 _Unwind_VRS_Set (context
, _UVRSC_CORE
, R_PC
, _UVRSD_UINT32
, &tmp
);
303 unwind_pop_rts (_Unwind_Context
* context
)
307 _Unwind_VRS_Get (context
, _UVRSC_CORE
, R_SP
, _UVRSD_UINT32
, &ptr
);
309 _Unwind_VRS_Set (context
, _UVRSC_CORE
, R_B3
, _UVRSD_UINT32
, ptr
+ 1);
311 _Unwind_VRS_Set (context
, _UVRSC_CORE
, R_B3
, _UVRSD_UINT32
, ptr
+ 2);
314 unwind_restore_pair (context
, R_A10
, ptr
);
316 unwind_restore_pair (context
, R_B10
, ptr
);
318 unwind_restore_pair (context
, R_A12
, ptr
);
320 unwind_restore_pair (context
, R_B12
, ptr
);
322 unwind_restore_pair (context
, R_A14
, ptr
);
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. */
329 /* Execute the unwinding instructions described by UWS. */
331 __gnu_unwind_execute (_Unwind_Context
* context
, __gnu_unwind_state
* uws
)
341 op
= next_unwind_byte (uws
);
342 if (op
== CODE_FINISH
)
344 /* Drop out of the loop. */
347 if ((op
& 0xc0) == 0)
349 /* sp += (imm6 << 3) + 8. */
352 offset
= ((op
& 0x3f) << 3) + 8;
353 _Unwind_VRS_Get (context
, _UVRSC_CORE
, R_SP
, _UVRSD_UINT32
, ®
);
355 _Unwind_VRS_Set (context
, _UVRSC_CORE
, R_SP
, _UVRSD_UINT32
, ®
);
361 /* vsp = vsp + 0x204 + (uleb128 << 2). */
364 _Unwind_VRS_Get (context
, _UVRSC_CORE
, R_SP
, _UVRSD_UINT32
, ®
);
365 op
= next_unwind_byte (uws
);
369 reg
+= ((op
& 0x7f) << shift
);
371 op
= next_unwind_byte (uws
);
373 reg
+= ((op
& 0x7f) << shift
) + 0x408;
374 _Unwind_VRS_Set (context
, _UVRSC_CORE
, R_SP
, _UVRSD_UINT32
, ®
);
378 if ((op
& 0xe0) == 0x80)
381 _uw mask
= ((op
& 0x1f) << 8) | next_unwind_byte (uws
);
389 _Unwind_VRS_Get (context
, _UVRSC_CORE
, R_SP
, _UVRSD_UINT32
, &ptr
);
390 pop_frame (context
, mask
, ptr
, inc_sp
);
394 if ((op
& 0xe0) == 0xa0)
396 /* POP bitmask (compact) */
397 _uw mask
= ((op
& 0x1f) << 8) | next_unwind_byte (uws
);
399 _Unwind_VRS_Get (context
, _UVRSC_CORE
, R_SP
, _UVRSD_UINT32
, &ptr
);
400 pop_compact_frame (context
, mask
, ptr
, inc_sp
);
404 if ((op
& 0xf0) == 0xc0)
407 int nregs
= op
& 0xf;
409 _Unwind_VRS_Get (context
, _UVRSC_CORE
, R_SP
, _UVRSD_UINT32
, &ptr
);
412 op
= next_unwind_byte (uws
);
413 if ((op
>> 4) != 0xf)
415 reg
= unwind_frame_regs
[op
>> 4];
416 _Unwind_VRS_Set (context
, _UVRSC_CORE
, reg
, _UVRSD_UINT32
,
421 if ((op
& 0xf) != 0xf)
423 reg
= unwind_frame_regs
[op
& 0xf];
424 _Unwind_VRS_Set (context
, _UVRSC_CORE
, reg
, _UVRSD_UINT32
,
438 _Unwind_VRS_Get (context
, _UVRSC_CORE
, R_A15
, _UVRSD_UINT32
, ®
);
439 _Unwind_VRS_Set (context
, _UVRSC_CORE
, R_SP
, _UVRSD_UINT32
, ®
);
445 /* __cx6abi_pop_rts */
446 unwind_pop_rts (context
);
450 if ((op
& 0xf0) == 0xe0)
452 /* B3 = reg. RETURN case already handled above. */
453 int regno
= unwind_frame_regs
[op
& 0xf];
455 _Unwind_VRS_Get (context
, _UVRSC_CORE
, regno
, _UVRSD_UINT32
, ®
);
456 _Unwind_VRS_Set (context
, _UVRSC_CORE
, R_B3
, _UVRSD_UINT32
, ®
);
464 /* Implicit RETURN. */
465 _Unwind_VRS_Get (context
, _UVRSC_CORE
, R_B3
, _UVRSD_UINT32
, ®
);
466 _Unwind_VRS_Set (context
, _UVRSC_CORE
, R_PC
, _UVRSD_UINT32
, ®
);
471 /* Execute the unwinding instructions associated with a frame. UCBP and
472 CONTEXT are the current exception object and virtual CPU state
476 __gnu_unwind_frame (_Unwind_Control_Block
* ucbp
, _Unwind_Context
* context
)
479 __gnu_unwind_state uws
;
481 ptr
= (_uw
*) ucbp
->pr_cache
.ehtp
;
482 /* Skip over the personality routine address. */
484 /* Setup the unwinder state. */
485 uws
.data
= (*ptr
) << 8;
488 uws
.words_left
= ((*ptr
) >> 24) & 0xff;
490 return __gnu_unwind_execute (context
, &uws
);
493 /* Data segment base pointer corresponding to the function catching
497 _Unwind_GetDataRelBase (_Unwind_Context
*context
)
499 return _Unwind_GetGR (context
, R_B14
);
502 /* This should never be used. */
505 _Unwind_GetTextRelBase (_Unwind_Context
*context
__attribute__ ((unused
)))
510 /* Only used by gcc personality routines, so can rely on a value they hid
513 _Unwind_GetRegionStart (_Unwind_Context
*context
)
515 _Unwind_Control_Block
*ucbp
;
517 ucbp
= (_Unwind_Control_Block
*) _Unwind_GetGR (context
, UNWIND_POINTER_REG
);
518 return (_Unwind_Ptr
) ucbp
->pr_cache
.fnstart
;
522 _Unwind_GetLanguageSpecificData (_Unwind_Context
*context
)
524 _Unwind_Control_Block
*ucbp
;
527 ucbp
= (_Unwind_Control_Block
*) _Unwind_GetGR (context
, UNWIND_POINTER_REG
);
528 ptr
= (_uw
*) ucbp
->pr_cache
.ehtp
;
529 /* Skip the personality routine address. */
531 /* Skip the unwind opcodes. */
532 ptr
+= (((*ptr
) >> 24) & 0xff) + 1;