1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* ARM EABI compliant unwinding routines
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   Copyright (C) 2004, 2005 Free Software Foundation, Inc.
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   Contributed by Paul Brook
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   This file is free software; you can redistribute it and/or modify it
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   under the terms of the GNU General Public License as published by the
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   Free Software Foundation; either version 2, or (at your option) any
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   later version.
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   In addition to the permissions in the GNU General Public License, the
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   Free Software Foundation gives you unlimited permission to link the
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   compiled version of this file into combinations with other programs,
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   and to distribute those combinations without any restriction coming
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   from the use of this file.  (The General Public License restrictions
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   do apply in other respects; for example, they cover modification of
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   the file, and distribution when not linked into a combine
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   executable.)
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   This file is distributed in the hope that it will be useful, but
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   WITHOUT ANY WARRANTY; without even the implied warranty of
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   General Public License for more details.
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   You should have received a copy of the GNU General Public License
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   along with this program; see the file COPYING.  If not, write to
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   the Free Software Foundation, 51 Franklin Street, Fifth Floor,
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   Boston, MA 02110-1301, USA.  */
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/****************************************************************************
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * The functions here are derived from gcc/config/arm/pr-support.c from the
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 4.3.x release. The main changes here involve the use of ptrace to retrieve
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * memory/processor states from a remote process.
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ****************************************************************************/
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/types.h>
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unwind.h>
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "utility.h"
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* We add a prototype for abort here to avoid creating a dependency on
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   target headers.  */
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectextern void abort (void);
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* Derived from _Unwind_VRS_Pop to use ptrace */
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectextern _Unwind_VRS_Result
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectunwind_VRS_Pop_with_ptrace (_Unwind_Context *context,
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                            _Unwind_VRS_RegClass regclass,
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                            _uw discriminator,
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                            _Unwind_VRS_DataRepresentation representation,
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                            pid_t pid);
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttypedef struct _ZSt9type_info type_info; /* This names C++ type_info type */
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* Misc constants.  */
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define R_IP    12
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define R_SP    13
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define R_LR    14
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define R_PC    15
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define uint32_highbit (((_uw) 1) << 31)
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid __attribute__((weak)) __cxa_call_unexpected(_Unwind_Control_Block *ucbp);
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* Unwind descriptors.  */
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttypedef struct
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project  _uw16 length;
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project  _uw16 offset;
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} EHT16;
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttypedef struct
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project  _uw length;
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project  _uw offset;
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} EHT32;
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* Personality routine helper functions.  */
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define CODE_FINISH (0xb0)
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* Derived from next_unwind_byte to use ptrace */
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* Return the next byte of unwinding information, or CODE_FINISH if there is
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   no data remaining.  */
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic inline _uw8
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectnext_unwind_byte_with_ptrace (__gnu_unwind_state * uws, pid_t pid)
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project  _uw8 b;
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project  if (uws->bytes_left == 0)
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    {
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      /* Load another word */
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      if (uws->words_left == 0)
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	return CODE_FINISH; /* Nothing left.  */
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      uws->words_left--;
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      uws->data = get_remote_word(pid, uws->next);
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      uws->next++;
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      uws->bytes_left = 3;
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project  else
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    uws->bytes_left--;
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project  /* Extract the most significant byte.  */
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project  b = (uws->data >> 24) & 0xff;
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project  uws->data <<= 8;
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project  return b;
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* Execute the unwinding instructions described by UWS.  */
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project_Unwind_Reason_Code
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectunwind_execute_with_ptrace(_Unwind_Context * context, __gnu_unwind_state * uws,
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                           pid_t pid)
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project  _uw op;
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project  int set_pc;
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project  _uw reg;
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project  set_pc = 0;
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project  for (;;)
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    {
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      op = next_unwind_byte_with_ptrace (uws, pid);
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      if (op == CODE_FINISH)
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	{
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  /* If we haven't already set pc then copy it from lr.  */
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  if (!set_pc)
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    {
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      _Unwind_VRS_Get (context, _UVRSC_CORE, R_LR, _UVRSD_UINT32,
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			       &reg);
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      _Unwind_VRS_Set (context, _UVRSC_CORE, R_PC, _UVRSD_UINT32,
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			       &reg);
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      set_pc = 1;
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    }
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  /* Drop out of the loop.  */
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  break;
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      if ((op & 0x80) == 0)
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	{
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  /* vsp = vsp +- (imm6 << 2 + 4).  */
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  _uw offset;
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  offset = ((op & 0x3f) << 2) + 4;
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  if (op & 0x40)
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    reg -= offset;
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  else
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    reg += offset;
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  continue;
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      if ((op & 0xf0) == 0x80)
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	{
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  op = (op << 8) | next_unwind_byte_with_ptrace (uws, pid);
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  if (op == 0x8000)
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    {
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      /* Refuse to unwind.  */
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      return _URC_FAILURE;
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    }
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  /* Pop r4-r15 under mask.  */
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  op = (op << 4) & 0xfff0;
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  if (unwind_VRS_Pop_with_ptrace (context, _UVRSC_CORE, op, _UVRSD_UINT32,
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                      pid)
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      != _UVRSR_OK)
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    return _URC_FAILURE;
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  if (op & (1 << R_PC))
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    set_pc = 1;
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  continue;
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      if ((op & 0xf0) == 0x90)
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	{
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  op &= 0xf;
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  if (op == 13 || op == 15)
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    /* Reserved.  */
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    return _URC_FAILURE;
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  /* vsp = r[nnnn].  */
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  _Unwind_VRS_Get (context, _UVRSC_CORE, op, _UVRSD_UINT32, &reg);
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  continue;
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      if ((op & 0xf0) == 0xa0)
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	{
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  /* Pop r4-r[4+nnn], [lr].  */
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  _uw mask;
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  mask = (0xff0 >> (7 - (op & 7))) & 0xff0;
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  if (op & 8)
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    mask |= (1 << R_LR);
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  if (unwind_VRS_Pop_with_ptrace (context, _UVRSC_CORE, mask, _UVRSD_UINT32,
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                      pid)
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      != _UVRSR_OK)
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    return _URC_FAILURE;
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  continue;
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      if ((op & 0xf0) == 0xb0)
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	{
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  /* op == 0xb0 already handled.  */
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  if (op == 0xb1)
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    {
199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      op = next_unwind_byte_with_ptrace (uws, pid);
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      if (op == 0 || ((op & 0xf0) != 0))
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		/* Spare.  */
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return _URC_FAILURE;
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      /* Pop r0-r4 under mask.  */
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      if (unwind_VRS_Pop_with_ptrace (context, _UVRSC_CORE, op,
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                          _UVRSD_UINT32, pid)
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		  != _UVRSR_OK)
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return _URC_FAILURE;
208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      continue;
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    }
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  if (op == 0xb2)
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    {
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      /* vsp = vsp + 0x204 + (uleb128 << 2).  */
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      int shift;
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32,
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			       &reg);
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      op = next_unwind_byte_with_ptrace (uws, pid);
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      shift = 2;
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      while (op & 0x80)
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		{
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		  reg += ((op & 0x7f) << shift);
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		  shift += 7;
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		  op = next_unwind_byte_with_ptrace (uws, pid);
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      reg += ((op & 0x7f) << shift) + 0x204;
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32,
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			       &reg);
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      continue;
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    }
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  if (op == 0xb3)
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    {
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      /* Pop VFP registers with fldmx.  */
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      op = next_unwind_byte_with_ptrace (uws, pid);
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      op = ((op & 0xf0) << 12) | ((op & 0xf) + 1);
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      if (unwind_VRS_Pop_with_ptrace (context, _UVRSC_VFP, op, _UVRSD_VFPX,
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                          pid)
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		  != _UVRSR_OK)
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return _URC_FAILURE;
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      continue;
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    }
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  if ((op & 0xfc) == 0xb4)
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    {
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      /* Pop FPA E[4]-E[4+nn].  */
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      op = 0x40000 | ((op & 3) + 1);
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      if (unwind_VRS_Pop_with_ptrace (context, _UVRSC_FPA, op, _UVRSD_FPAX,
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                          pid)
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		  != _UVRSR_OK)
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return _URC_FAILURE;
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      continue;
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    }
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  /* op & 0xf8 == 0xb8.  */
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  /* Pop VFP D[8]-D[8+nnn] with fldmx.  */
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  op = 0x80000 | ((op & 7) + 1);
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  if (unwind_VRS_Pop_with_ptrace (context, _UVRSC_VFP, op, _UVRSD_VFPX, pid)
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      != _UVRSR_OK)
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    return _URC_FAILURE;
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  continue;
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      if ((op & 0xf0) == 0xc0)
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	{
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  if (op == 0xc6)
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    {
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      /* Pop iWMMXt D registers.  */
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      op = next_unwind_byte_with_ptrace (uws, pid);
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      op = ((op & 0xf0) << 12) | ((op & 0xf) + 1);
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      if (unwind_VRS_Pop_with_ptrace (context, _UVRSC_WMMXD, op,
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                          _UVRSD_UINT64, pid)
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		  != _UVRSR_OK)
269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return _URC_FAILURE;
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      continue;
271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    }
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  if (op == 0xc7)
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    {
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      op = next_unwind_byte_with_ptrace (uws, pid);
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      if (op == 0 || (op & 0xf0) != 0)
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		/* Spare.  */
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return _URC_FAILURE;
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      /* Pop iWMMXt wCGR{3,2,1,0} under mask.  */
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      if (unwind_VRS_Pop_with_ptrace (context, _UVRSC_WMMXC, op,
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                          _UVRSD_UINT32, pid)
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		  != _UVRSR_OK)
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return _URC_FAILURE;
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      continue;
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    }
285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  if ((op & 0xf8) == 0xc0)
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    {
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      /* Pop iWMMXt wR[10]-wR[10+nnn].  */
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      op = 0xa0000 | ((op & 0xf) + 1);
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      if (unwind_VRS_Pop_with_ptrace (context, _UVRSC_WMMXD, op,
290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                          _UVRSD_UINT64, pid)
291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		  != _UVRSR_OK)
292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return _URC_FAILURE;
293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      continue;
294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    }
295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  if (op == 0xc8)
296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    {
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifndef __VFP_FP__
298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 	      /* Pop FPA registers.  */
299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 	      op = next_unwind_byte_with_ptrace (uws, pid);
300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      op = ((op & 0xf0) << 12) | ((op & 0xf) + 1);
301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 	      if (unwind_VRS_Pop_with_ptrace (context, _UVRSC_FPA, op, _UVRSD_FPAX,
302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                          pid)
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 		  != _UVRSR_OK)
304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 		return _URC_FAILURE;
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 	      continue;
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else
307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project              /* Pop VFPv3 registers D[16+ssss]-D[16+ssss+cccc] with vldm.  */
308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project              op = next_unwind_byte_with_ptrace (uws, pid);
309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project              op = (((op & 0xf0) + 16) << 12) | ((op & 0xf) + 1);
310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project              if (unwind_VRS_Pop_with_ptrace (context, _UVRSC_VFP, op,
311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                              _UVRSD_DOUBLE, pid)
312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                  != _UVRSR_OK)
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                return _URC_FAILURE;
314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project              continue;
315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    }
317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  if (op == 0xc9)
318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    {
319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      /* Pop VFP registers with fldmd.  */
320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      op = next_unwind_byte_with_ptrace (uws, pid);
321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      op = ((op & 0xf0) << 12) | ((op & 0xf) + 1);
322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      if (unwind_VRS_Pop_with_ptrace (context, _UVRSC_VFP, op,
323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                          _UVRSD_DOUBLE, pid)
324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		  != _UVRSR_OK)
325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return _URC_FAILURE;
326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      continue;
327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    }
328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  /* Spare.  */
329dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  return _URC_FAILURE;
330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      if ((op & 0xf8) == 0xd0)
332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	{
333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  /* Pop VFP D[8]-D[8+nnn] with fldmd.  */
334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  op = 0x80000 | ((op & 7) + 1);
335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  if (unwind_VRS_Pop_with_ptrace (context, _UVRSC_VFP, op, _UVRSD_DOUBLE,
336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                      pid)
337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	      != _UVRSR_OK)
338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    return _URC_FAILURE;
339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  continue;
340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      /* Spare.  */
342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      return _URC_FAILURE;
343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project  return _URC_OK;
345dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
346