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, &reg);
35463d1a8abSmrg 	  reg += offset;
35563d1a8abSmrg 	  _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
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, &reg);
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, &reg);
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, &reg);
43963d1a8abSmrg 	  _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
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, &reg);
45663d1a8abSmrg 	  _Unwind_VRS_Set (context, _UVRSC_CORE, R_B3, _UVRSD_UINT32, &reg);
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, &reg);
46663d1a8abSmrg   _Unwind_VRS_Set (context, _UVRSC_CORE, R_PC, _UVRSD_UINT32, &reg);
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