163d1a8abSmrg /* C6X ABI compliant unwinding routines
2*ec02198aSmrg Copyright (C) 2011-2020 Free Software Foundation, Inc.
363d1a8abSmrg
463d1a8abSmrg This file is free software; you can redistribute it and/or modify it
563d1a8abSmrg under the terms of the GNU General Public License as published by the
663d1a8abSmrg Free Software Foundation; either version 3, or (at your option) any
763d1a8abSmrg later version.
863d1a8abSmrg
963d1a8abSmrg This file is distributed in the hope that it will be useful, but
1063d1a8abSmrg WITHOUT ANY WARRANTY; without even the implied warranty of
1163d1a8abSmrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1263d1a8abSmrg General Public License for more details.
1363d1a8abSmrg
1463d1a8abSmrg Under Section 7 of GPL version 3, you are granted additional
1563d1a8abSmrg permissions described in the GCC Runtime Library Exception, version
1663d1a8abSmrg 3.1, as published by the Free Software Foundation.
1763d1a8abSmrg
1863d1a8abSmrg You should have received a copy of the GNU General Public License and
1963d1a8abSmrg a copy of the GCC Runtime Library Exception along with this program;
2063d1a8abSmrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
2163d1a8abSmrg <http://www.gnu.org/licenses/>. */
2263d1a8abSmrg
2363d1a8abSmrg #include "unwind.h"
2463d1a8abSmrg
2563d1a8abSmrg /* We add a prototype for abort here to avoid creating a dependency on
2663d1a8abSmrg target headers. */
2763d1a8abSmrg extern void abort (void);
2863d1a8abSmrg
2963d1a8abSmrg typedef struct _ZSt9type_info type_info; /* This names C++ type_info type */
3063d1a8abSmrg
3163d1a8abSmrg /* Misc constants. */
3263d1a8abSmrg #define R_A0 0
3363d1a8abSmrg #define R_A1 1
3463d1a8abSmrg #define R_A2 2
3563d1a8abSmrg #define R_A3 3
3663d1a8abSmrg #define R_A4 4
3763d1a8abSmrg #define R_A5 5
3863d1a8abSmrg #define R_A6 6
3963d1a8abSmrg #define R_A7 7
4063d1a8abSmrg #define R_A8 8
4163d1a8abSmrg #define R_A9 9
4263d1a8abSmrg #define R_A10 10
4363d1a8abSmrg #define R_A11 11
4463d1a8abSmrg #define R_A12 12
4563d1a8abSmrg #define R_A13 13
4663d1a8abSmrg #define R_A14 14
4763d1a8abSmrg #define R_A15 15
4863d1a8abSmrg #define R_B0 16
4963d1a8abSmrg #define R_B1 17
5063d1a8abSmrg #define R_B2 18
5163d1a8abSmrg #define R_B3 19
5263d1a8abSmrg #define R_B4 20
5363d1a8abSmrg #define R_B5 21
5463d1a8abSmrg #define R_B6 22
5563d1a8abSmrg #define R_B7 23
5663d1a8abSmrg #define R_B8 24
5763d1a8abSmrg #define R_B9 25
5863d1a8abSmrg #define R_B10 26
5963d1a8abSmrg #define R_B11 27
6063d1a8abSmrg #define R_B12 28
6163d1a8abSmrg #define R_B13 29
6263d1a8abSmrg #define R_B14 30
6363d1a8abSmrg #define R_B15 31
6463d1a8abSmrg
6563d1a8abSmrg #define R_SP R_B15
6663d1a8abSmrg #define R_PC 33
6763d1a8abSmrg
6863d1a8abSmrg #define uint32_highbit (((_uw) 1) << 31)
6963d1a8abSmrg
7063d1a8abSmrg void __attribute__((weak)) __cxa_call_unexpected(_Unwind_Control_Block *ucbp);
7163d1a8abSmrg
7263d1a8abSmrg /* Unwind descriptors. */
7363d1a8abSmrg
7463d1a8abSmrg typedef struct
7563d1a8abSmrg {
7663d1a8abSmrg _uw16 length;
7763d1a8abSmrg _uw16 offset;
7863d1a8abSmrg } EHT16;
7963d1a8abSmrg
8063d1a8abSmrg typedef struct
8163d1a8abSmrg {
8263d1a8abSmrg _uw length;
8363d1a8abSmrg _uw offset;
8463d1a8abSmrg } EHT32;
8563d1a8abSmrg
8663d1a8abSmrg /* Calculate the address encoded by a 31-bit self-relative offset at address
8763d1a8abSmrg P. Copy of routine in unwind-arm.c. */
8863d1a8abSmrg
8963d1a8abSmrg static inline _uw
selfrel_offset31(const _uw * p)9063d1a8abSmrg selfrel_offset31 (const _uw *p)
9163d1a8abSmrg {
9263d1a8abSmrg _uw offset;
9363d1a8abSmrg
9463d1a8abSmrg offset = *p;
9563d1a8abSmrg /* Sign extend to 32 bits. */
9663d1a8abSmrg if (offset & (1 << 30))
9763d1a8abSmrg offset |= 1u << 31;
9863d1a8abSmrg
9963d1a8abSmrg return offset + (_uw) p;
10063d1a8abSmrg }
10163d1a8abSmrg
10263d1a8abSmrg
10363d1a8abSmrg /* Personality routine helper functions. */
10463d1a8abSmrg
10563d1a8abSmrg #define CODE_FINISH (0xe7)
10663d1a8abSmrg
10763d1a8abSmrg /* Return the next byte of unwinding information, or CODE_FINISH if there is
10863d1a8abSmrg no data remaining. */
10963d1a8abSmrg static inline _uw8
next_unwind_byte(__gnu_unwind_state * uws)11063d1a8abSmrg next_unwind_byte (__gnu_unwind_state * uws)
11163d1a8abSmrg {
11263d1a8abSmrg _uw8 b;
11363d1a8abSmrg
11463d1a8abSmrg if (uws->bytes_left == 0)
11563d1a8abSmrg {
11663d1a8abSmrg /* Load another word */
11763d1a8abSmrg if (uws->words_left == 0)
11863d1a8abSmrg return CODE_FINISH; /* Nothing left. */
11963d1a8abSmrg uws->words_left--;
12063d1a8abSmrg uws->data = *(uws->next++);
12163d1a8abSmrg uws->bytes_left = 3;
12263d1a8abSmrg }
12363d1a8abSmrg else
12463d1a8abSmrg uws->bytes_left--;
12563d1a8abSmrg
12663d1a8abSmrg /* Extract the most significant byte. */
12763d1a8abSmrg b = (uws->data >> 24) & 0xff;
12863d1a8abSmrg uws->data <<= 8;
12963d1a8abSmrg return b;
13063d1a8abSmrg }
13163d1a8abSmrg
13263d1a8abSmrg static void
unwind_restore_pair(_Unwind_Context * context,int reg,_uw * ptr)13363d1a8abSmrg unwind_restore_pair (_Unwind_Context * context, int reg, _uw *ptr)
13463d1a8abSmrg {
13563d1a8abSmrg #ifdef _BIG_ENDIAN
13663d1a8abSmrg _Unwind_VRS_Set (context, _UVRSC_CORE, reg, _UVRSD_UINT32, ptr + 1);
13763d1a8abSmrg _Unwind_VRS_Set (context, _UVRSC_CORE, reg + 1, _UVRSD_UINT32, ptr);
13863d1a8abSmrg #else
13963d1a8abSmrg _Unwind_VRS_Set (context, _UVRSC_CORE, reg, _UVRSD_UINT32, ptr);
14063d1a8abSmrg _Unwind_VRS_Set (context, _UVRSC_CORE, reg + 1, _UVRSD_UINT32, ptr + 1);
14163d1a8abSmrg #endif
14263d1a8abSmrg }
14363d1a8abSmrg
14463d1a8abSmrg static const int
14563d1a8abSmrg unwind_frame_regs[13] =
14663d1a8abSmrg {
14763d1a8abSmrg R_A15, R_B15, R_B14, R_B13, R_B12, R_B11, R_B10, R_B3,
14863d1a8abSmrg R_A14, R_A13, R_A12, R_A11, R_A10
14963d1a8abSmrg };
15063d1a8abSmrg
15163d1a8abSmrg static void
pop_compact_frame(_Unwind_Context * context,_uw mask,_uw * ptr,int inc_sp)15263d1a8abSmrg pop_compact_frame (_Unwind_Context * context, _uw mask, _uw *ptr, int inc_sp)
15363d1a8abSmrg {
15463d1a8abSmrg int size;
15563d1a8abSmrg _uw test;
15663d1a8abSmrg int i, regno, nregs;
15763d1a8abSmrg
15863d1a8abSmrg size = 0;
15963d1a8abSmrg nregs = __builtin_popcount (mask);
16063d1a8abSmrg for (i = 0; i < 13; i++)
16163d1a8abSmrg {
16263d1a8abSmrg test = 1 << i;
16363d1a8abSmrg if ((mask & test) == 0)
16463d1a8abSmrg continue;
16563d1a8abSmrg
16663d1a8abSmrg regno = unwind_frame_regs[12 - i];
16763d1a8abSmrg
16863d1a8abSmrg if (i < 12 && nregs > 2
16963d1a8abSmrg && (mask & (test << 1)) != 0
17063d1a8abSmrg && unwind_frame_regs[11 - i] == regno + 1
17163d1a8abSmrg && (regno & 1) == 0)
17263d1a8abSmrg {
17363d1a8abSmrg i++;
17463d1a8abSmrg nregs--;
17563d1a8abSmrg }
17663d1a8abSmrg
17763d1a8abSmrg nregs--;
17863d1a8abSmrg size += 2;
17963d1a8abSmrg }
18063d1a8abSmrg
18163d1a8abSmrg if (!inc_sp)
18263d1a8abSmrg ptr -= size;
18363d1a8abSmrg
18463d1a8abSmrg /* SP points just past the end of the stack. */
18563d1a8abSmrg ptr += 2;
18663d1a8abSmrg nregs = __builtin_popcount (mask);
18763d1a8abSmrg for (i = 0; i < 13; i++)
18863d1a8abSmrg {
18963d1a8abSmrg test = 1 << i;
19063d1a8abSmrg if ((mask & test) == 0)
19163d1a8abSmrg continue;
19263d1a8abSmrg
19363d1a8abSmrg regno = unwind_frame_regs[12 - i];
19463d1a8abSmrg
19563d1a8abSmrg if (i < 12 && nregs > 2
19663d1a8abSmrg && (mask & (test << 1)) != 0
19763d1a8abSmrg && unwind_frame_regs[11 - i] == regno + 1
19863d1a8abSmrg && (regno & 1) == 0)
19963d1a8abSmrg {
20063d1a8abSmrg /* Register pair. */
20163d1a8abSmrg unwind_restore_pair (context, regno, ptr);
20263d1a8abSmrg i++;
20363d1a8abSmrg nregs--;
20463d1a8abSmrg }
20563d1a8abSmrg else
20663d1a8abSmrg {
20763d1a8abSmrg /* Single register with padding. */
20863d1a8abSmrg _Unwind_VRS_Set (context, _UVRSC_CORE, regno, _UVRSD_UINT32, ptr);
20963d1a8abSmrg }
21063d1a8abSmrg
21163d1a8abSmrg nregs--;
21263d1a8abSmrg ptr += 2;
21363d1a8abSmrg }
21463d1a8abSmrg
21563d1a8abSmrg ptr -= 2;
21663d1a8abSmrg if ((mask & (1 << 11)) == 0)
21763d1a8abSmrg _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &ptr);
21863d1a8abSmrg }
21963d1a8abSmrg
22063d1a8abSmrg static void
pop_frame(_Unwind_Context * context,_uw mask,_uw * ptr,int inc_sp)22163d1a8abSmrg pop_frame (_Unwind_Context * context, _uw mask, _uw *ptr, int inc_sp)
22263d1a8abSmrg {
22363d1a8abSmrg int i;
22463d1a8abSmrg int regno;
22563d1a8abSmrg int nregs;
22663d1a8abSmrg
22763d1a8abSmrg nregs = __builtin_popcount (mask);
22863d1a8abSmrg
22963d1a8abSmrg if (!inc_sp)
23063d1a8abSmrg ptr -= nregs;
23163d1a8abSmrg else if (nregs & 1)
23263d1a8abSmrg ptr++;
23363d1a8abSmrg
23463d1a8abSmrg ptr++;
23563d1a8abSmrg for (i = 0; i < 13; i++)
23663d1a8abSmrg {
23763d1a8abSmrg if ((mask & (1 << i)) == 0)
23863d1a8abSmrg continue;
23963d1a8abSmrg regno = unwind_frame_regs[12 - i];
24063d1a8abSmrg if (i < 12 && unwind_frame_regs[11 - i] == (regno + 1)
24163d1a8abSmrg && (mask & (1 << (i + 1))) != 0
24263d1a8abSmrg && (((_uw)ptr) & 4) == 0
24363d1a8abSmrg && (regno & 1) == 0)
24463d1a8abSmrg {
24563d1a8abSmrg unwind_restore_pair (context, regno, ptr);
24663d1a8abSmrg i++;
24763d1a8abSmrg ptr += 2;
24863d1a8abSmrg }
24963d1a8abSmrg else
25063d1a8abSmrg {
25163d1a8abSmrg _Unwind_VRS_Set (context, _UVRSC_CORE, regno, _UVRSD_UINT32,
25263d1a8abSmrg ptr);
25363d1a8abSmrg ptr++;
25463d1a8abSmrg }
25563d1a8abSmrg }
25663d1a8abSmrg
25763d1a8abSmrg ptr--;
25863d1a8abSmrg if ((mask & (1 << 11)) == 0)
25963d1a8abSmrg _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &ptr);
26063d1a8abSmrg }
26163d1a8abSmrg
26263d1a8abSmrg /* Unwind a 24-bit encoded frame. */
26363d1a8abSmrg _Unwind_Reason_Code
__gnu_unwind_24bit(_Unwind_Context * context,_uw data,int compact)26463d1a8abSmrg __gnu_unwind_24bit (_Unwind_Context * context, _uw data, int compact)
26563d1a8abSmrg {
26663d1a8abSmrg _uw offset;
26763d1a8abSmrg _uw mask;
26863d1a8abSmrg _uw *ptr;
26963d1a8abSmrg _uw tmp;
27063d1a8abSmrg int ret_reg = unwind_frame_regs[data & 0xf];
27163d1a8abSmrg
27263d1a8abSmrg if (ret_reg != R_B3)
27363d1a8abSmrg {
27463d1a8abSmrg _Unwind_VRS_Get (context, _UVRSC_CORE, unwind_frame_regs[data & 0xf],
27563d1a8abSmrg _UVRSD_UINT32, &tmp);
27663d1a8abSmrg _Unwind_VRS_Set (context, _UVRSC_CORE, R_B3, _UVRSD_UINT32, &tmp);
27763d1a8abSmrg }
27863d1a8abSmrg
27963d1a8abSmrg mask = (data >> 4) & 0x1fff;
28063d1a8abSmrg
28163d1a8abSmrg offset = (data >> 17) & 0x7f;
28263d1a8abSmrg if (offset == 0x7f)
28363d1a8abSmrg _Unwind_VRS_Get (context, _UVRSC_CORE, R_A15, _UVRSD_UINT32, &ptr);
28463d1a8abSmrg else
28563d1a8abSmrg {
28663d1a8abSmrg _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &ptr);
28763d1a8abSmrg ptr += offset * 2;
28863d1a8abSmrg }
28963d1a8abSmrg
29063d1a8abSmrg
29163d1a8abSmrg if (compact)
29263d1a8abSmrg pop_compact_frame (context, mask, ptr, offset != 0x7f);
29363d1a8abSmrg else
29463d1a8abSmrg pop_frame (context, mask, ptr, offset != 0x7f);
29563d1a8abSmrg
29663d1a8abSmrg _Unwind_VRS_Get (context, _UVRSC_CORE, R_B3, _UVRSD_UINT32, &tmp);
29763d1a8abSmrg _Unwind_VRS_Set (context, _UVRSC_CORE, R_PC, _UVRSD_UINT32, &tmp);
29863d1a8abSmrg
29963d1a8abSmrg return _URC_OK;
30063d1a8abSmrg }
30163d1a8abSmrg
30263d1a8abSmrg static void
unwind_pop_rts(_Unwind_Context * context)30363d1a8abSmrg unwind_pop_rts (_Unwind_Context * context)
30463d1a8abSmrg {
30563d1a8abSmrg _uw *ptr;
30663d1a8abSmrg
30763d1a8abSmrg _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &ptr);
30863d1a8abSmrg #ifdef _BIG_ENDIAN
30963d1a8abSmrg _Unwind_VRS_Set (context, _UVRSC_CORE, R_B3, _UVRSD_UINT32, ptr + 1);
31063d1a8abSmrg #else
31163d1a8abSmrg _Unwind_VRS_Set (context, _UVRSC_CORE, R_B3, _UVRSD_UINT32, ptr + 2);
31263d1a8abSmrg #endif
31363d1a8abSmrg ptr += 3;
31463d1a8abSmrg unwind_restore_pair (context, R_A10, ptr);
31563d1a8abSmrg ptr += 2;
31663d1a8abSmrg unwind_restore_pair (context, R_B10, ptr);
31763d1a8abSmrg ptr += 2;
31863d1a8abSmrg unwind_restore_pair (context, R_A12, ptr);
31963d1a8abSmrg ptr += 2;
32063d1a8abSmrg unwind_restore_pair (context, R_B12, ptr);
32163d1a8abSmrg ptr += 2;
32263d1a8abSmrg unwind_restore_pair (context, R_A14, ptr);
32363d1a8abSmrg ptr += 2;
32463d1a8abSmrg _Unwind_VRS_Set (context, _UVRSC_CORE, R_B14, _UVRSD_UINT32, ptr);
32563d1a8abSmrg _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &ptr);
32663d1a8abSmrg /* PC will be set by implicit RETURN opcode. */
32763d1a8abSmrg }
32863d1a8abSmrg
32963d1a8abSmrg /* Execute the unwinding instructions described by UWS. */
33063d1a8abSmrg _Unwind_Reason_Code
__gnu_unwind_execute(_Unwind_Context * context,__gnu_unwind_state * uws)33163d1a8abSmrg __gnu_unwind_execute (_Unwind_Context * context, __gnu_unwind_state * uws)
33263d1a8abSmrg {
33363d1a8abSmrg _uw op;
33463d1a8abSmrg int inc_sp;
33563d1a8abSmrg _uw reg;
33663d1a8abSmrg _uw *ptr;
33763d1a8abSmrg
33863d1a8abSmrg inc_sp = 1;
33963d1a8abSmrg for (;;)
34063d1a8abSmrg {
34163d1a8abSmrg op = next_unwind_byte (uws);
34263d1a8abSmrg if (op == CODE_FINISH)
34363d1a8abSmrg {
34463d1a8abSmrg /* Drop out of the loop. */
34563d1a8abSmrg break;
34663d1a8abSmrg }
34763d1a8abSmrg if ((op & 0xc0) == 0)
34863d1a8abSmrg {
34963d1a8abSmrg /* sp += (imm6 << 3) + 8. */
35063d1a8abSmrg _uw offset;
35163d1a8abSmrg
35263d1a8abSmrg offset = ((op & 0x3f) << 3) + 8;
35363d1a8abSmrg _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, ®);
35463d1a8abSmrg reg += offset;
35563d1a8abSmrg _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, ®);
35663d1a8abSmrg continue;
35763d1a8abSmrg }
35863d1a8abSmrg
35963d1a8abSmrg if (op == 0xd2)
36063d1a8abSmrg {
36163d1a8abSmrg /* vsp = vsp + 0x204 + (uleb128 << 2). */
36263d1a8abSmrg int shift;
36363d1a8abSmrg
36463d1a8abSmrg _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, ®);
36563d1a8abSmrg op = next_unwind_byte (uws);
36663d1a8abSmrg shift = 3;
36763d1a8abSmrg while (op & 0x80)
36863d1a8abSmrg {
36963d1a8abSmrg reg += ((op & 0x7f) << shift);
37063d1a8abSmrg shift += 7;
37163d1a8abSmrg op = next_unwind_byte (uws);
37263d1a8abSmrg }
37363d1a8abSmrg reg += ((op & 0x7f) << shift) + 0x408;
37463d1a8abSmrg _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, ®);
37563d1a8abSmrg continue;
37663d1a8abSmrg }
37763d1a8abSmrg
37863d1a8abSmrg if ((op & 0xe0) == 0x80)
37963d1a8abSmrg {
38063d1a8abSmrg /* POP bitmask */
38163d1a8abSmrg _uw mask = ((op & 0x1f) << 8) | next_unwind_byte (uws);
38263d1a8abSmrg
38363d1a8abSmrg if (mask == 0)
38463d1a8abSmrg {
38563d1a8abSmrg /* CANTUNWIND */
38663d1a8abSmrg return _URC_FAILURE;
38763d1a8abSmrg }
38863d1a8abSmrg
38963d1a8abSmrg _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &ptr);
39063d1a8abSmrg pop_frame (context, mask, ptr, inc_sp);
39163d1a8abSmrg continue;
39263d1a8abSmrg }
39363d1a8abSmrg
39463d1a8abSmrg if ((op & 0xe0) == 0xa0)
39563d1a8abSmrg {
39663d1a8abSmrg /* POP bitmask (compact) */
39763d1a8abSmrg _uw mask = ((op & 0x1f) << 8) | next_unwind_byte (uws);
39863d1a8abSmrg
39963d1a8abSmrg _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &ptr);
40063d1a8abSmrg pop_compact_frame (context, mask, ptr, inc_sp);
40163d1a8abSmrg continue;
40263d1a8abSmrg }
40363d1a8abSmrg
40463d1a8abSmrg if ((op & 0xf0) == 0xc0)
40563d1a8abSmrg {
40663d1a8abSmrg /* POP registers */
40763d1a8abSmrg int nregs = op & 0xf;
40863d1a8abSmrg
40963d1a8abSmrg _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &ptr);
41063d1a8abSmrg while (nregs > 0)
41163d1a8abSmrg {
41263d1a8abSmrg op = next_unwind_byte (uws);
41363d1a8abSmrg if ((op >> 4) != 0xf)
41463d1a8abSmrg {
41563d1a8abSmrg reg = unwind_frame_regs[op >> 4];
41663d1a8abSmrg _Unwind_VRS_Set (context, _UVRSC_CORE, reg, _UVRSD_UINT32,
41763d1a8abSmrg ptr);
41863d1a8abSmrg nregs--;
41963d1a8abSmrg }
42063d1a8abSmrg ptr--;
42163d1a8abSmrg if ((op & 0xf) != 0xf)
42263d1a8abSmrg {
42363d1a8abSmrg reg = unwind_frame_regs[op & 0xf];
42463d1a8abSmrg _Unwind_VRS_Set (context, _UVRSC_CORE, reg, _UVRSD_UINT32,
42563d1a8abSmrg ptr);
42663d1a8abSmrg nregs--;
42763d1a8abSmrg }
42863d1a8abSmrg ptr--;
42963d1a8abSmrg }
43063d1a8abSmrg
43163d1a8abSmrg continue;
43263d1a8abSmrg }
43363d1a8abSmrg
43463d1a8abSmrg if (op == 0xd0)
43563d1a8abSmrg {
43663d1a8abSmrg /* MV FP, SP */
43763d1a8abSmrg inc_sp = 0;
43863d1a8abSmrg _Unwind_VRS_Get (context, _UVRSC_CORE, R_A15, _UVRSD_UINT32, ®);
43963d1a8abSmrg _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, ®);
44063d1a8abSmrg continue;
44163d1a8abSmrg }
44263d1a8abSmrg
44363d1a8abSmrg if (op == 0xd1)
44463d1a8abSmrg {
44563d1a8abSmrg /* __cx6abi_pop_rts */
44663d1a8abSmrg unwind_pop_rts (context);
44763d1a8abSmrg break;
44863d1a8abSmrg }
44963d1a8abSmrg
45063d1a8abSmrg if ((op & 0xf0) == 0xe0)
45163d1a8abSmrg {
45263d1a8abSmrg /* B3 = reg. RETURN case already handled above. */
45363d1a8abSmrg int regno = unwind_frame_regs[op & 0xf];
45463d1a8abSmrg
45563d1a8abSmrg _Unwind_VRS_Get (context, _UVRSC_CORE, regno, _UVRSD_UINT32, ®);
45663d1a8abSmrg _Unwind_VRS_Set (context, _UVRSC_CORE, R_B3, _UVRSD_UINT32, ®);
45763d1a8abSmrg continue;
45863d1a8abSmrg }
45963d1a8abSmrg
46063d1a8abSmrg /* Reserved. */
46163d1a8abSmrg return _URC_FAILURE;
46263d1a8abSmrg }
46363d1a8abSmrg
46463d1a8abSmrg /* Implicit RETURN. */
46563d1a8abSmrg _Unwind_VRS_Get (context, _UVRSC_CORE, R_B3, _UVRSD_UINT32, ®);
46663d1a8abSmrg _Unwind_VRS_Set (context, _UVRSC_CORE, R_PC, _UVRSD_UINT32, ®);
46763d1a8abSmrg return _URC_OK;
46863d1a8abSmrg }
46963d1a8abSmrg
47063d1a8abSmrg
47163d1a8abSmrg /* Execute the unwinding instructions associated with a frame. UCBP and
47263d1a8abSmrg CONTEXT are the current exception object and virtual CPU state
47363d1a8abSmrg respectively. */
47463d1a8abSmrg
47563d1a8abSmrg _Unwind_Reason_Code
__gnu_unwind_frame(_Unwind_Control_Block * ucbp,_Unwind_Context * context)47663d1a8abSmrg __gnu_unwind_frame (_Unwind_Control_Block * ucbp, _Unwind_Context * context)
47763d1a8abSmrg {
47863d1a8abSmrg _uw *ptr;
47963d1a8abSmrg __gnu_unwind_state uws;
48063d1a8abSmrg
48163d1a8abSmrg ptr = (_uw *) ucbp->pr_cache.ehtp;
48263d1a8abSmrg /* Skip over the personality routine address. */
48363d1a8abSmrg ptr++;
48463d1a8abSmrg /* Setup the unwinder state. */
48563d1a8abSmrg uws.data = (*ptr) << 8;
48663d1a8abSmrg uws.next = ptr + 1;
48763d1a8abSmrg uws.bytes_left = 3;
48863d1a8abSmrg uws.words_left = ((*ptr) >> 24) & 0xff;
48963d1a8abSmrg
49063d1a8abSmrg return __gnu_unwind_execute (context, &uws);
49163d1a8abSmrg }
49263d1a8abSmrg
49363d1a8abSmrg /* Data segment base pointer corresponding to the function catching
49463d1a8abSmrg the exception. */
49563d1a8abSmrg
49663d1a8abSmrg _Unwind_Ptr
_Unwind_GetDataRelBase(_Unwind_Context * context)49763d1a8abSmrg _Unwind_GetDataRelBase (_Unwind_Context *context)
49863d1a8abSmrg {
49963d1a8abSmrg return _Unwind_GetGR (context, R_B14);
50063d1a8abSmrg }
50163d1a8abSmrg
50263d1a8abSmrg /* This should never be used. */
50363d1a8abSmrg
50463d1a8abSmrg _Unwind_Ptr
_Unwind_GetTextRelBase(_Unwind_Context * context)50563d1a8abSmrg _Unwind_GetTextRelBase (_Unwind_Context *context __attribute__ ((unused)))
50663d1a8abSmrg {
50763d1a8abSmrg abort ();
50863d1a8abSmrg }
50963d1a8abSmrg
51063d1a8abSmrg /* Only used by gcc personality routines, so can rely on a value they hid
51163d1a8abSmrg there earlier. */
51263d1a8abSmrg _Unwind_Ptr
_Unwind_GetRegionStart(_Unwind_Context * context)51363d1a8abSmrg _Unwind_GetRegionStart (_Unwind_Context *context)
51463d1a8abSmrg {
51563d1a8abSmrg _Unwind_Control_Block *ucbp;
51663d1a8abSmrg
51763d1a8abSmrg ucbp = (_Unwind_Control_Block *) _Unwind_GetGR (context, UNWIND_POINTER_REG);
51863d1a8abSmrg return (_Unwind_Ptr) ucbp->pr_cache.fnstart;
51963d1a8abSmrg }
52063d1a8abSmrg
52163d1a8abSmrg _Unwind_Ptr
_Unwind_GetLanguageSpecificData(_Unwind_Context * context)52263d1a8abSmrg _Unwind_GetLanguageSpecificData (_Unwind_Context *context)
52363d1a8abSmrg {
52463d1a8abSmrg _Unwind_Control_Block *ucbp;
52563d1a8abSmrg _uw *ptr;
52663d1a8abSmrg
52763d1a8abSmrg ucbp = (_Unwind_Control_Block *) _Unwind_GetGR (context, UNWIND_POINTER_REG);
52863d1a8abSmrg ptr = (_uw *) ucbp->pr_cache.ehtp;
52963d1a8abSmrg /* Skip the personality routine address. */
53063d1a8abSmrg ptr++;
53163d1a8abSmrg /* Skip the unwind opcodes. */
53263d1a8abSmrg ptr += (((*ptr) >> 24) & 0xff) + 1;
53363d1a8abSmrg
53463d1a8abSmrg return (_Unwind_Ptr) ptr;
53563d1a8abSmrg }
536