os/kernelhwsrv/kernel/eka/compsupp/symaehabi/unwind_pr.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/* unwind_pr.c - ARM-defined model personality routines
sl@0
     2
 *
sl@0
     3
 * Copyright 2002-2005 ARM Limited. All rights reserved.
sl@0
     4
 *
sl@0
     5
 * Your rights to use this code are set out in the accompanying licence
sl@0
     6
 * text file LICENCE.txt (ARM contract number LEC-ELA-00080 v1.0).
sl@0
     7
 */
sl@0
     8
sl@0
     9
/* Portions copyright Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). */
sl@0
    10
sl@0
    11
/*
sl@0
    12
 * RCS $Revision: 92986 $
sl@0
    13
 * Checkin $Date: 2005-10-13 15:56:12 +0100 (Thu, 13 Oct 2005) $
sl@0
    14
 * Revising $Author: achapman $
sl@0
    15
 */
sl@0
    16
sl@0
    17
#include <cstdlib>
sl@0
    18
/* Environment: */
sl@0
    19
#include "unwind_env.h"
sl@0
    20
/* Language-independent unwinder declarations: */
sl@0
    21
#include "unwinder.h"
sl@0
    22
sl@0
    23
/* Define PR_DIAGNOSTICS for printed diagnostics from the personality routine */
sl@0
    24
sl@0
    25
#ifdef __EPOC32__
sl@0
    26
/* Symbian specific support */
sl@0
    27
#include "symbian_support.h"
sl@0
    28
#endif
sl@0
    29
sl@0
    30
#ifdef PR_DIAGNOSTICS
sl@0
    31
#ifndef __EPOC32__
sl@0
    32
extern int printf(const char *, ...);
sl@0
    33
#endif
sl@0
    34
#endif
sl@0
    35
sl@0
    36
sl@0
    37
/* Forward decl: */
sl@0
    38
extern _Unwind_Reason_Code __ARM_unwind_cpp_prcommon(_Unwind_State state,
sl@0
    39
                                                     _Unwind_Control_Block *ucbp,
sl@0
    40
                                                     _Unwind_Context *context,
sl@0
    41
                                                     uint32_t idx);
sl@0
    42
sl@0
    43
/* Personality routines - external entry points.
sl@0
    44
 * pr0: short unwind description, 16 bit EHT offsets.
sl@0
    45
 * pr1: long unwind description, 16 bit EHT offsets.
sl@0
    46
 * pr2: long unwind description, 32 bit EHT offsets.
sl@0
    47
 */
sl@0
    48
sl@0
    49
#ifdef pr0_c
sl@0
    50
_Unwind_Reason_Code __aeabi_unwind_cpp_pr0(_Unwind_State state,
sl@0
    51
                                           _Unwind_Control_Block *ucbp,
sl@0
    52
                                           _Unwind_Context *context) {
sl@0
    53
  return __ARM_unwind_cpp_prcommon(state, ucbp, context, 0);
sl@0
    54
}
sl@0
    55
#endif
sl@0
    56
sl@0
    57
#ifdef pr1_c
sl@0
    58
EXPORT_C _Unwind_Reason_Code __aeabi_unwind_cpp_pr1(_Unwind_State state,
sl@0
    59
                                                    _Unwind_Control_Block *ucbp,
sl@0
    60
                                                    _Unwind_Context *context) {
sl@0
    61
  return __ARM_unwind_cpp_prcommon(state, ucbp, context, 1);
sl@0
    62
}
sl@0
    63
#endif
sl@0
    64
sl@0
    65
#ifdef pr2_c
sl@0
    66
EXPORT_C _Unwind_Reason_Code __aeabi_unwind_cpp_pr2(_Unwind_State state,
sl@0
    67
                                                    _Unwind_Control_Block *ucbp,
sl@0
    68
                                                    _Unwind_Context *context) {
sl@0
    69
  return __ARM_unwind_cpp_prcommon(state, ucbp, context, 2);
sl@0
    70
}
sl@0
    71
#endif
sl@0
    72
sl@0
    73
/* The rest of the file deals with the common routine */
sl@0
    74
sl@0
    75
#ifdef prcommon_c
sl@0
    76
sl@0
    77
/* C++ exceptions ABI required here:
sl@0
    78
 * Declare protocol routines called by the personality routine.
sl@0
    79
 * These are weak references so that referencing them here is
sl@0
    80
 * insufficient to pull them into the image - they will only be
sl@0
    81
 * included if application code uses a __cxa routine.
sl@0
    82
 */
sl@0
    83
sl@0
    84
typedef unsigned char bool;
sl@0
    85
static const bool false = 0;
sl@0
    86
static const bool true = !false;
sl@0
    87
sl@0
    88
typedef struct _ZSt9type_info type_info; /* This names C++ type_info type */
sl@0
    89
sl@0
    90
IMPORT_C WEAKDECL void __cxa_call_unexpected(_Unwind_Control_Block *ucbp);
sl@0
    91
IMPORT_C WEAKDECL bool __cxa_begin_cleanup(_Unwind_Control_Block *ucbp);
sl@0
    92
typedef enum {
sl@0
    93
    ctm_failed = 0,
sl@0
    94
    ctm_succeeded = 1,
sl@0
    95
    ctm_succeeded_with_ptr_to_base = 2
sl@0
    96
  } __cxa_type_match_result;
sl@0
    97
IMPORT_C WEAKDECL __cxa_type_match_result __cxa_type_match(_Unwind_Control_Block *ucbp,
sl@0
    98
                                                           const type_info *rttip,
sl@0
    99
                                                           bool is_reference_type,
sl@0
   100
                                                           void **matched_object);
sl@0
   101
sl@0
   102
/* ----- Helper routines, private ----- */
sl@0
   103
sl@0
   104
/* R_ARM_PREL31 is a place-relative 31-bit signed relocation.  The
sl@0
   105
 * routine takes the address of a location that was relocated by
sl@0
   106
 * R_ARM_PREL31, and returns an absolute address.
sl@0
   107
 */
sl@0
   108
static FORCEINLINE uint32_t __ARM_resolve_prel31(void *p)
sl@0
   109
{
sl@0
   110
  return (uint32_t)((((*(int32_t *)p) << 1) >> 1) + (int32_t)p);
sl@0
   111
}
sl@0
   112
sl@0
   113
/* --------- VRS manipulation: --------- */
sl@0
   114
sl@0
   115
#define R_SP 13
sl@0
   116
#define R_LR 14
sl@0
   117
#define R_PC 15
sl@0
   118
sl@0
   119
static FORCEINLINE uint32_t core_get(_Unwind_Context *context, uint32_t regno)
sl@0
   120
{
sl@0
   121
  uint32_t val;
sl@0
   122
  /* This call is required to never fail if given a valid regno */
sl@0
   123
  _Unwind_VRS_Get(context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
sl@0
   124
  return val;
sl@0
   125
}
sl@0
   126
sl@0
   127
static FORCEINLINE void core_set(_Unwind_Context *context, uint32_t regno, uint32_t newval)
sl@0
   128
{
sl@0
   129
  /* This call is required to never fail if given a valid regno */
sl@0
   130
  _Unwind_VRS_Set(context, _UVRSC_CORE, regno, _UVRSD_UINT32, &newval);
sl@0
   131
}
sl@0
   132
sl@0
   133
static FORCEINLINE uint32_t count_to_mask(uint32_t count) {
sl@0
   134
  return (1 << count) - 1;
sl@0
   135
}
sl@0
   136
sl@0
   137
/* --------- Support for unwind instruction stream: --------- */
sl@0
   138
sl@0
   139
#define CODE_FINISH (0xb0)
sl@0
   140
sl@0
   141
typedef struct uwdata {
sl@0
   142
  uint32_t unwind_word;                  /* current word of unwind description */
sl@0
   143
  uint32_t *unwind_word_pointer;         /* ptr to next word */
sl@0
   144
  uint8_t unwind_word_bytes_remaining;   /* count of bytes left in current word */
sl@0
   145
  uint8_t unwind_words_remaining;        /* count of words left, at ptr onwards */
sl@0
   146
} uwdata;
sl@0
   147
sl@0
   148
static INLINE uint8_t next_unwind_byte(uwdata *u) {
sl@0
   149
  uint8_t ub;
sl@0
   150
  if (u->unwind_word_bytes_remaining == 0) {  /* Load another word */
sl@0
   151
    if (u->unwind_words_remaining == 0) return CODE_FINISH; /* nothing left - yield NOP */
sl@0
   152
    u->unwind_words_remaining--;
sl@0
   153
    u->unwind_word = *(u->unwind_word_pointer++);
sl@0
   154
    u->unwind_word_bytes_remaining = 4;
sl@0
   155
  }
sl@0
   156
  
sl@0
   157
  u->unwind_word_bytes_remaining--;
sl@0
   158
  ub = (u->unwind_word & 0xff000000) >> 24;
sl@0
   159
  u->unwind_word <<= 8;
sl@0
   160
  return ub;
sl@0
   161
}
sl@0
   162
sl@0
   163
sl@0
   164
/* --------- Personality routines: --------- */
sl@0
   165
sl@0
   166
/* The C++ Standard is silent on what is supposed to happen if an internal
sl@0
   167
 * inconsistency occurs during unwinding. In our design, we return to the
sl@0
   168
 * caller with _URC_FAILURE. During phase 1 this causes a return from the
sl@0
   169
 * language-independent unwinder to its caller (__cxa_throw or __cxa_rethrow)
sl@0
   170
 * which will then call terminate(). If an error occurs during phase 2, the
sl@0
   171
 * caller will call abort().
sl@0
   172
 */
sl@0
   173
sl@0
   174
/* Types to assist with reading EHT's */
sl@0
   175
sl@0
   176
typedef struct {
sl@0
   177
  uint16_t length;
sl@0
   178
  uint16_t offset;
sl@0
   179
} EHT16;
sl@0
   180
sl@0
   181
typedef struct {
sl@0
   182
  uint32_t length;
sl@0
   183
  uint32_t offset;
sl@0
   184
} EHT32;
sl@0
   185
sl@0
   186
typedef uint32_t landingpad_t;
sl@0
   187
sl@0
   188
typedef struct {
sl@0
   189
  landingpad_t landingpad;
sl@0
   190
} EHT_cleanup_tail;
sl@0
   191
sl@0
   192
typedef struct {
sl@0
   193
  landingpad_t landingpad;
sl@0
   194
  uint32_t rtti_ref;
sl@0
   195
} EHT_catch_tail;
sl@0
   196
sl@0
   197
typedef struct {
sl@0
   198
  uint32_t rtti_count;           /* table count (possibly 0) */
sl@0
   199
  uint32_t (rtti_refs[1]);       /* variable length table, possibly followed by landing pad */
sl@0
   200
} EHT_fnspec_tail;
sl@0
   201
sl@0
   202
sl@0
   203
/* Macros: */
sl@0
   204
sl@0
   205
/* Barrier cache: */
sl@0
   206
/* Requirement imposed by C++ semantics module - pointer to match object in slot 0: */
sl@0
   207
#define BARRIER_HANDLEROBJECT (0)
sl@0
   208
/* Requirement imposed by C++ semantics module - function exception spec info */
sl@0
   209
#define BARRIER_FNSPECCOUNT  (1)
sl@0
   210
#define BARRIER_FNSPECBASE   (2)
sl@0
   211
#define BARRIER_FNSPECSTRIDE (3)
sl@0
   212
#define BARRIER_FNSPECARRAY  (4)
sl@0
   213
/* Private use for us until catch handler entry complete: */
sl@0
   214
#define BARRIER_TEMPORARYMATCHOBJECT (1)
sl@0
   215
/* Private use for us between phase 1 & 2: */
sl@0
   216
#define BARRIER_EHTP (2)
sl@0
   217
sl@0
   218
#define SAVE_CATCH_PROPAGATION_BARRIER(UCB_PTR,VSP,EHTP,HANDLEROBJECT) \
sl@0
   219
  (UCB_PTR)->barrier_cache.sp = (VSP);    \
sl@0
   220
  (UCB_PTR)->barrier_cache.bitpattern[BARRIER_EHTP] = (uint32_t)(EHTP); \
sl@0
   221
  (UCB_PTR)->barrier_cache.bitpattern[BARRIER_HANDLEROBJECT] = (uint32_t)(HANDLEROBJECT);
sl@0
   222
sl@0
   223
#define SAVE_CATCH_OF_BASEPTR_PROPAGATION_BARRIER(UCB_PTR,VSP,EHTP,HANDLEROBJECT) \
sl@0
   224
  (UCB_PTR)->barrier_cache.sp = (VSP);    \
sl@0
   225
  (UCB_PTR)->barrier_cache.bitpattern[BARRIER_EHTP] = (uint32_t)(EHTP); \
sl@0
   226
  (UCB_PTR)->barrier_cache.bitpattern[BARRIER_TEMPORARYMATCHOBJECT] = (uint32_t)(HANDLEROBJECT); \
sl@0
   227
  (UCB_PTR)->barrier_cache.bitpattern[BARRIER_HANDLEROBJECT] = (uint32_t)&((UCB_PTR)->barrier_cache.bitpattern[BARRIER_TEMPORARYMATCHOBJECT]);
sl@0
   228
sl@0
   229
#define SAVE_FNSPEC_PROPAGATION_BARRIER(UCB_PTR,VSP,EHTP) \
sl@0
   230
  (UCB_PTR)->barrier_cache.sp = (VSP);    \
sl@0
   231
  (UCB_PTR)->barrier_cache.bitpattern[BARRIER_EHTP] = (uint32_t)(EHTP); \
sl@0
   232
  (UCB_PTR)->barrier_cache.bitpattern[BARRIER_HANDLEROBJECT] = (uint32_t)0;
sl@0
   233
sl@0
   234
#define CHECK_FOR_PROPAGATION_BARRIER(UCB_PTR,VSP,EHTP) \
sl@0
   235
   ((UCB_PTR)->barrier_cache.sp == (VSP) &&    \
sl@0
   236
    (UCB_PTR)->barrier_cache.bitpattern[BARRIER_EHTP] == (uint32_t)(EHTP))
sl@0
   237
sl@0
   238
sl@0
   239
/* Cleanup cache: We only use one field */
sl@0
   240
#define CLEANUP_EHTP (0)
sl@0
   241
sl@0
   242
sl@0
   243
/* Special catch rtti values */
sl@0
   244
#define CATCH_ALL               (0xffffffff)
sl@0
   245
#define CATCH_ALL_AND_TERMINATE (0xfffffffe)
sl@0
   246
/* Landing pad bit for catching a reference type */
sl@0
   247
#define CATCH_REFERENCE         (0x80000000)
sl@0
   248
sl@0
   249
sl@0
   250
/* Common personality routine: receives pr index as an argument.
sl@0
   251
 *
sl@0
   252
 * Note this implementation contains no explicit check against attempting to
sl@0
   253
 * unwind off the top of the stack. Instead it relies (in cooperation with
sl@0
   254
 * the language-independent unwinder) on there being a propagation barrier
sl@0
   255
 * somewhere on the stack, perhaps the caller to main being not
sl@0
   256
 * unwindable. An alternative would be to check for the stack pointer
sl@0
   257
 * addressing a stack limit symbol.
sl@0
   258
 */
sl@0
   259
sl@0
   260
_Unwind_Reason_Code __ARM_unwind_cpp_prcommon(_Unwind_State state,
sl@0
   261
                                              _Unwind_Control_Block *ucbp,
sl@0
   262
                                              _Unwind_Context *context,
sl@0
   263
                                              uint32_t idx)
sl@0
   264
{
sl@0
   265
  _Unwind_EHT_Header *eht_startp;  /* EHT start pointer */
sl@0
   266
  uint8_t *ehtp; /* EHT pointer, incremented as required */
sl@0
   267
  /* Flag for fnspec violations in which the frame should be unwound before calling unexpected() */
sl@0
   268
  bool phase2_call_unexpected_after_unwind;
sl@0
   269
  /* Flag for whether we have loaded r15 (pc) with a return address while executing
sl@0
   270
   * unwind instructions.
sl@0
   271
   * Set this on any write to r15 while executing the unwind instructions.
sl@0
   272
   */
sl@0
   273
  bool wrote_pc = false;
sl@0
   274
  /* Flag for whether we have loaded r14 (lr) with a return address while executing
sl@0
   275
   * unwind instructions.
sl@0
   276
   * Set this on any write to r14 while executing the unwind instructions.
sl@0
   277
   */
sl@0
   278
  bool wrote_lr = false;
sl@0
   279
  /* Flag for whether we loaded r15 from r14 while executing the unwind instructions */
sl@0
   280
  bool wrote_pc_from_lr = false;
sl@0
   281
  uwdata ud;
sl@0
   282
sl@0
   283
  /* Are we version 2 of the EHABI ? */
sl@0
   284
  bool ehabiv2 = EHABI_V2(ucbp);
sl@0
   285
sl@0
   286
  /* Mark all as well and extract the EHT pointer */
sl@0
   287
sl@0
   288
  eht_startp = ucbp->pr_cache.ehtp;
sl@0
   289
sl@0
   290
#ifdef PR_DIAGNOSTICS
sl@0
   291
  printf("PR entered: state=%d, r15=0x%x, fnstart=0x%x\n",
sl@0
   292
         state, core_get(context, R_PC), ucbp->pr_cache.fnstart);
sl@0
   293
#endif
sl@0
   294
  
sl@0
   295
  /* What are we supposed to do? */
sl@0
   296
sl@0
   297
  if (state != _US_VIRTUAL_UNWIND_FRAME &&
sl@0
   298
      state != _US_UNWIND_FRAME_STARTING &&
sl@0
   299
      state != _US_UNWIND_FRAME_RESUME) {
sl@0
   300
    DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_UNSPECIFIED);
sl@0
   301
    return _URC_FAILURE;
sl@0
   302
  }
sl@0
   303
sl@0
   304
  phase2_call_unexpected_after_unwind = false;
sl@0
   305
sl@0
   306
  /* Traverse the current EHT, if there is one.
sl@0
   307
   * The required behaviours are:
sl@0
   308
   * _US_VIRTUAL_UNWIND_FRAME: search for a propagation barrier in this frame.
sl@0
   309
   * otherwise look for the propagation barrier we found in phase 1,
sl@0
   310
   * performing cleanups on the way. In this case if state will be one of:
sl@0
   311
   *   _US_UNWIND_FRAME_STARTING  first time with this frame
sl@0
   312
   *   _US_UNWIND_FRAME_RESUME    not first time, we are part-way through the EHT.
sl@0
   313
   */
sl@0
   314
  
sl@0
   315
  if ((ucbp->pr_cache.additional & 1) == 0) { /* EHT inline in index table? */
sl@0
   316
    /* No: thus there is a real EHT */
sl@0
   317
    
sl@0
   318
    if (state == _US_UNWIND_FRAME_RESUME) {
sl@0
   319
      /* Recover saved pointer to next EHT entry */
sl@0
   320
      ehtp = (uint8_t *)ucbp->cleanup_cache.bitpattern[CLEANUP_EHTP];
sl@0
   321
#ifdef PR_DIAGNOSTICS
sl@0
   322
      printf("PR EHT recovered pointer 0x%x\n", (int)ehtp);
sl@0
   323
#endif
sl@0
   324
    } else {
sl@0
   325
      /* Point at the first EHT entry.
sl@0
   326
       * For pr0, the unwind description is entirely within the header word.
sl@0
   327
       * For pr1 & pr2, an unwind description extension word count is
sl@0
   328
       * held in bits 16-23 of the header word.
sl@0
   329
       */
sl@0
   330
      uint32_t unwind_extension_word_count = (idx == 0 ? 0 : ((*eht_startp) >> 16) & 0xff);
sl@0
   331
      ehtp = (uint8_t *)(eht_startp + 1 + unwind_extension_word_count);
sl@0
   332
      
sl@0
   333
#ifdef PR_DIAGNOSTICS
sl@0
   334
      printf("PR EHT first entry at 0x%x\n", (int)ehtp);
sl@0
   335
#endif
sl@0
   336
    }
sl@0
   337
    
sl@0
   338
    /* scan ... */
sl@0
   339
sl@0
   340
    while (1) {
sl@0
   341
      
sl@0
   342
      /* Extract 32 bit length and offset */
sl@0
   343
      uint32_t length;
sl@0
   344
      uint32_t offset;
sl@0
   345
      if (idx == 2) {
sl@0
   346
        /* 32 bit offsets */
sl@0
   347
        length = ((EHT32 *)ehtp)->length;
sl@0
   348
        if (length == 0) break; /* end of table */
sl@0
   349
        offset = ((EHT32 *)ehtp)->offset;
sl@0
   350
        ehtp += sizeof(EHT32);
sl@0
   351
      } else {
sl@0
   352
        /* 16 bit offsets */
sl@0
   353
        length = ((EHT16 *)ehtp)->length;
sl@0
   354
        if (length == 0) break; /* end of table */
sl@0
   355
        offset = ((EHT16 *)ehtp)->offset;
sl@0
   356
        ehtp += sizeof(EHT16);
sl@0
   357
      }
sl@0
   358
      
sl@0
   359
#ifdef PR_DIAGNOSTICS
sl@0
   360
      printf("PR Got entry at 0x%x code=%d, length=0x%x, offset=0x%x\n",
sl@0
   361
             (int)(ehtp-4), ((offset & 1) << 1) | (length & 1),
sl@0
   362
             length & ~1, offset & ~1);
sl@0
   363
#endif
sl@0
   364
sl@0
   365
      /* Dispatch on the kind of entry */
sl@0
   366
      switch (((offset & 1) << 1) | (length & 1)) {
sl@0
   367
      case 0: /* cleanup */
sl@0
   368
        if (state == _US_VIRTUAL_UNWIND_FRAME) {
sl@0
   369
          /* Not a propagation barrier - skip */
sl@0
   370
        } else {
sl@0
   371
          /* Phase 2: call the cleanup if the return address is in range */
sl@0
   372
          uint32_t padaddress;
sl@0
   373
          uint32_t rangestartaddr = ucbp->pr_cache.fnstart + offset;
sl@0
   374
          uint32_t rtn_addr = core_get(context, R_PC);
sl@0
   375
          if (rangestartaddr <= rtn_addr && rtn_addr < rangestartaddr + length) {
sl@0
   376
            /* It is in range. */
sl@0
   377
	    /* We need both of these to support v1 and v2 */
sl@0
   378
            landingpad_t *landingpadp = &((EHT_cleanup_tail *)ehtp)->landingpad;
sl@0
   379
            landingpad_t landingpad = *landingpadp;
sl@0
   380
            ehtp += sizeof(EHT_cleanup_tail);
sl@0
   381
            /* Dump state into the ECO so we resume correctly after the cleanup. */
sl@0
   382
            /* We simply save the address of the next EHT entry. */
sl@0
   383
            ucbp->cleanup_cache.bitpattern[CLEANUP_EHTP] = (uint32_t)ehtp;
sl@0
   384
            if (!__cxa_begin_cleanup(ucbp)) {
sl@0
   385
              /* Should be impossible, using ARM's library */
sl@0
   386
              DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_UNSPECIFIED);
sl@0
   387
              return _URC_FAILURE;
sl@0
   388
            }
sl@0
   389
            /* Set up the VRS to enter the landing pad. */
sl@0
   390
            padaddress = ehabiv2 ?
sl@0
   391
	      __ARM_resolve_prel31(landingpadp) :
sl@0
   392
	      ER_RO_OFFSET_TO_ADDR(landingpad,ucbp);
sl@0
   393
            core_set(context, R_PC, padaddress);
sl@0
   394
#ifdef PR_DIAGNOSTICS
sl@0
   395
            printf("PR Got cleanup in range, cleanup addr=0x%x\n", core_get(context, R_PC));
sl@0
   396
            printf("PR Saving EHT pointer 0x%x\n", (int)ehtp);
sl@0
   397
#endif
sl@0
   398
            DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_PADENTRY, padaddress);
sl@0
   399
            /* Exit requesting upload the VRS to the real machine. */
sl@0
   400
           return _URC_INSTALL_CONTEXT;
sl@0
   401
          }
sl@0
   402
        }
sl@0
   403
        /* Phase 1, or phase 2 and not in range */
sl@0
   404
        ehtp += sizeof(EHT_cleanup_tail);
sl@0
   405
        break;
sl@0
   406
      case 1: /* catch */
sl@0
   407
        {
sl@0
   408
          if (state == _US_VIRTUAL_UNWIND_FRAME) {
sl@0
   409
            /* In range, and with a matching type? */
sl@0
   410
            uint32_t rangestartaddr = ucbp->pr_cache.fnstart + offset;
sl@0
   411
            uint32_t rtn_addr = core_get(context, R_PC);
sl@0
   412
            void *matched_object;
sl@0
   413
            length -= 1;   /* length had low bit set - clear it */
sl@0
   414
            if (rangestartaddr <= rtn_addr && rtn_addr < rangestartaddr + length) {
sl@0
   415
              /* In range */
sl@0
   416
              __cxa_type_match_result matched_result;
sl@0
   417
              uint32_t *rtti_ref = &((EHT_catch_tail *)ehtp)->rtti_ref;
sl@0
   418
              uint32_t rtti_val = *rtti_ref;
sl@0
   419
              if (rtti_val == CATCH_ALL_AND_TERMINATE) {
sl@0
   420
                /* Always matches and causes propagation failure in phase 1 */
sl@0
   421
#ifdef PR_DIAGNOSTICS
sl@0
   422
                printf("PR Got CATCH_ALL_AND_TERMINATE in phase 1\n");
sl@0
   423
#endif
sl@0
   424
                DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_NOUNWIND);
sl@0
   425
                return _URC_FAILURE;    
sl@0
   426
              } else if (rtti_val == CATCH_ALL) {
sl@0
   427
                matched_object = ucbp + 1;
sl@0
   428
                matched_result = ctm_succeeded;
sl@0
   429
              } else {
sl@0
   430
                bool is_reference_type = ((uint32_t)(((EHT_catch_tail *)ehtp)->landingpad) & CATCH_REFERENCE)
sl@0
   431
                                                           == CATCH_REFERENCE;
sl@0
   432
                rtti_val = ehabiv2 ?
sl@0
   433
		  (uint32_t)__ARM_resolve_target2((void *)rtti_ref) :
sl@0
   434
		  (uint32_t)ER_RO_OFFSET_TO_ADDR(rtti_val, ucbp);
sl@0
   435
                matched_result =__cxa_type_match(ucbp,
sl@0
   436
                                                 (type_info *)rtti_val,
sl@0
   437
                                                 is_reference_type,
sl@0
   438
                                                 &matched_object);
sl@0
   439
              }
sl@0
   440
              if (matched_result != ctm_failed) {
sl@0
   441
                /* In range and matches.
sl@0
   442
                 * Record the propagation barrier details for ease of detection in phase 2.
sl@0
   443
                 * We save a pointer to the middle of the handler entry -
sl@0
   444
                 * this is fine, so long as we are consistent about it.
sl@0
   445
                 */
sl@0
   446
#ifdef PR_DIAGNOSTICS
sl@0
   447
                printf("PR Got barrier in phase 1, result %d\n", (int)matched_result);
sl@0
   448
                printf("PR Matched object address 0x%8.8x\n", matched_object); 
sl@0
   449
#endif
sl@0
   450
                if (matched_result == ctm_succeeded_with_ptr_to_base) {
sl@0
   451
                  SAVE_CATCH_OF_BASEPTR_PROPAGATION_BARRIER(ucbp, core_get(context, R_SP),
sl@0
   452
                                                            ehtp, matched_object);
sl@0
   453
sl@0
   454
                } else {
sl@0
   455
                  SAVE_CATCH_PROPAGATION_BARRIER(ucbp, core_get(context, R_SP),
sl@0
   456
                                                 ehtp, matched_object);
sl@0
   457
                }
sl@0
   458
                DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_BARRIERFOUND,
sl@0
   459
                                    (ehabiv2 ?
sl@0
   460
				      __ARM_resolve_prel31(&((EHT_catch_tail *)ehtp)->landingpad) :
sl@0
   461
				      ER_RO_OFFSET_TO_ADDR(((EHT_catch_tail *)ehtp)->landingpad, ucbp)));
sl@0
   462
                DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_CPP_TYPEINFO, rtti_val);
sl@0
   463
                return _URC_HANDLER_FOUND;
sl@0
   464
              }
sl@0
   465
            }
sl@0
   466
            /* Not in range or no type match - fall thru to carry on scanning the table */
sl@0
   467
          } else {
sl@0
   468
            /* Else this is phase 2: have we encountered the saved barrier? */
sl@0
   469
            if (CHECK_FOR_PROPAGATION_BARRIER(ucbp, core_get(context, R_SP), ehtp)) {
sl@0
   470
              /* Yes we have.
sl@0
   471
               * Set up the VRS to enter the landing pad,
sl@0
   472
               * and upload the VRS to the real machine.
sl@0
   473
               */
sl@0
   474
              landingpad_t *landingpadp = &((EHT_catch_tail *)ehtp)->landingpad;
sl@0
   475
              landingpad_t landingpad = *landingpadp;
sl@0
   476
              uint32_t padaddress = ehabiv2 ?
sl@0
   477
		__ARM_resolve_prel31(landingpadp) :
sl@0
   478
		ER_RO_OFFSET_TO_ADDR(landingpad, ucbp);
sl@0
   479
#ifdef PR_DIAGNOSTICS
sl@0
   480
              printf("PR Got catch barrier in phase 2\n");
sl@0
   481
#endif
sl@0
   482
              core_set(context, R_PC, padaddress);
sl@0
   483
              core_set(context, 0, (uint32_t)ucbp);
sl@0
   484
              DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_PADENTRY, padaddress);
sl@0
   485
              /* Exit requesting upload the VRS to the real machine. */
sl@0
   486
              return _URC_INSTALL_CONTEXT;
sl@0
   487
            }
sl@0
   488
          }
sl@0
   489
          /* Else carry on scanning the table */
sl@0
   490
          ehtp += sizeof(EHT_catch_tail);
sl@0
   491
          break;
sl@0
   492
        }
sl@0
   493
      case 2: /* function exception specification (fnspec) */
sl@0
   494
        {
sl@0
   495
          uint32_t counter_word = ((EHT_fnspec_tail *)ehtp)->rtti_count;
sl@0
   496
          uint32_t rtti_count = counter_word & 0x7fffffff;   /* Extract offset count */
sl@0
   497
          if (state == _US_VIRTUAL_UNWIND_FRAME) {
sl@0
   498
            /* Phase 1 */
sl@0
   499
            /* In range? Offset had low bit set - clear it */
sl@0
   500
            uint32_t rangestartaddr = ucbp->pr_cache.fnstart + offset - 1;
sl@0
   501
            uint32_t rtn_addr = core_get(context, R_PC);
sl@0
   502
            if (rangestartaddr <= rtn_addr && rtn_addr < rangestartaddr + length) {
sl@0
   503
              /* See if any type matches */
sl@0
   504
              uint32_t *rttipp = &((EHT_fnspec_tail *)ehtp)->rtti_refs[0];
sl@0
   505
              uint32_t i;
sl@0
   506
              for (i = 0; i < rtti_count; i++) {
sl@0
   507
                 void *matched_object;
sl@0
   508
		 type_info * artti;
sl@0
   509
		 if (ehabiv2)
sl@0
   510
		   artti = (type_info *)__ARM_resolve_target2(rttipp);
sl@0
   511
		 else
sl@0
   512
		   artti = (type_info *)ER_RO_OFFSET_TO_ADDR(*rttipp, ucbp);
sl@0
   513
                 if (__cxa_type_match(ucbp, artti, false, &matched_object)) {
sl@0
   514
#ifdef PR_DIAGNOSTICS
sl@0
   515
                   printf("PR Fnspec matched in phase 1\n");
sl@0
   516
#endif
sl@0
   517
                   break;
sl@0
   518
                 }
sl@0
   519
                 rttipp++;
sl@0
   520
              }
sl@0
   521
sl@0
   522
              if (i == rtti_count) { /* NB case rtti_count==0 forces no match [for throw()] */
sl@0
   523
                /* No match - fnspec violation is a propagation barrier */
sl@0
   524
#ifdef PR_DIAGNOSTICS
sl@0
   525
                printf("PR Got fnspec barrier in phase 1\n");
sl@0
   526
#endif
sl@0
   527
                SAVE_FNSPEC_PROPAGATION_BARRIER(ucbp, core_get(context, R_SP), ehtp); /* save ptr to the count of types */
sl@0
   528
                /* Even if this is a fnspec with a landing pad, we always end up in
sl@0
   529
                 * __cxa_call_unexpected so tell the debugger thats where we're going
sl@0
   530
                 */
sl@0
   531
                DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_BARRIERFOUND, &__cxa_call_unexpected);
sl@0
   532
                return _URC_HANDLER_FOUND;
sl@0
   533
              }
sl@0
   534
            } /* if (in range...) */
sl@0
   535
sl@0
   536
            /* Fall out of the 'if' to continue table scanning */
sl@0
   537
sl@0
   538
          } else {
sl@0
   539
            /* Else this is phase 2: have we encountered the saved barrier? */
sl@0
   540
            if (CHECK_FOR_PROPAGATION_BARRIER(ucbp, core_get(context, R_SP), ehtp)) {
sl@0
   541
              /* Yes we have. Fill in the UCB barrier_cache for entry to __cxa_call_unexpected */
sl@0
   542
              uint32_t *p = (uint32_t *)ehtp; /* ptr to rtti count */
sl@0
   543
              ucbp->barrier_cache.bitpattern[BARRIER_FNSPECCOUNT] = rtti_count;
sl@0
   544
              ucbp->barrier_cache.bitpattern[BARRIER_FNSPECBASE] = ehabiv2 ? 0 :ER_RO_OFFSET_TO_ADDR(0, ucbp);
sl@0
   545
              ucbp->barrier_cache.bitpattern[BARRIER_FNSPECSTRIDE] = 4; /* stride */
sl@0
   546
              ucbp->barrier_cache.bitpattern[BARRIER_FNSPECARRAY]  = (uint32_t)(p + 1); /* address of rtti offset list */
sl@0
   547
sl@0
   548
              /* If this is a fnspec with an attached landing pad, we must enter
sl@0
   549
               * the pad immediately. Otherwise we need to unwind the frame before
sl@0
   550
               * calling __cxa_call_unexpected() so set a flag to make this happen.
sl@0
   551
               */
sl@0
   552
              if (counter_word == rtti_count)
sl@0
   553
                phase2_call_unexpected_after_unwind = true; /* no pad, enter later */
sl@0
   554
              else { /* pad */
sl@0
   555
                landingpad_t *landingpadp;
sl@0
   556
                landingpad_t landingpad;
sl@0
   557
                uint32_t padaddress;
sl@0
   558
#ifdef PR_DIAGNOSTICS
sl@0
   559
                printf("PR Got fnspec barrier in phase 2 (immediate entry)\n");
sl@0
   560
#endif
sl@0
   561
                ehtp += (sizeof(((EHT_fnspec_tail *)ehtp)->rtti_count) +
sl@0
   562
                         sizeof(uint32_t) * rtti_count);  /* point at pad offset */
sl@0
   563
                landingpadp = (landingpad_t *)ehtp;
sl@0
   564
                landingpad = *(landingpad_t *)ehtp;
sl@0
   565
                padaddress = ehabiv2 ?
sl@0
   566
		  __ARM_resolve_prel31(landingpadp) :
sl@0
   567
		  ER_RO_OFFSET_TO_ADDR(landingpad, ucbp);
sl@0
   568
                core_set(context, 0, (uint32_t)ucbp);
sl@0
   569
                core_set(context, R_PC, padaddress);
sl@0
   570
                /* Even if this is a fnspec with a landing pad, in phase 1 we said we'd
sl@0
   571
                 * end up in __cxa_call_unexpected so show the same thing now
sl@0
   572
                 */
sl@0
   573
                DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_PADENTRY, &__cxa_call_unexpected);
sl@0
   574
                return _URC_INSTALL_CONTEXT;
sl@0
   575
              }
sl@0
   576
            } /* endif (barrier match) */
sl@0
   577
          } /* endif (which phase) */
sl@0
   578
          
sl@0
   579
          /* Advance to the next item, remembering to skip the landing pad if present */
sl@0
   580
          ehtp += (sizeof(((EHT_fnspec_tail *)ehtp)->rtti_count) +
sl@0
   581
                   sizeof(uint32_t) * rtti_count +
sl@0
   582
                   (counter_word == rtti_count ? 0 : sizeof(landingpad_t)));
sl@0
   583
          break;
sl@0
   584
        }
sl@0
   585
      case 3: /* unallocated */
sl@0
   586
        DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_TABLECORRUPT);
sl@0
   587
        return _URC_FAILURE;
sl@0
   588
      } /* switch */
sl@0
   589
sl@0
   590
    } /* while (1) */
sl@0
   591
    
sl@0
   592
#ifdef PR_DIAGNOSTICS
sl@0
   593
    printf("PR Reached end of EHT\n");
sl@0
   594
#endif
sl@0
   595
sl@0
   596
  } /* if out-of-line EHT */
sl@0
   597
sl@0
   598
sl@0
   599
  /* Do a virtual unwind of this frame - load the first unwind bytes then loop.
sl@0
   600
   * Loop exit is by executing opcode CODE_FINISH.
sl@0
   601
   */
sl@0
   602
sl@0
   603
  ud.unwind_word = *(uint32_t *)eht_startp;             /* first word */
sl@0
   604
  ud.unwind_word_pointer = (uint32_t *)eht_startp + 1;  /* ptr to extension words, if any */
sl@0
   605
  if (idx == 0) {                  /* short description */
sl@0
   606
    ud.unwind_words_remaining = 0; /* no further words */
sl@0
   607
    ud.unwind_word <<= 8;          /* 3 explicit unwind bytes in this word */
sl@0
   608
    ud.unwind_word_bytes_remaining = 3;
sl@0
   609
  } else {                         /* long description: extension word count in bits 16-23 */
sl@0
   610
    ud.unwind_words_remaining = ((ud.unwind_word) >> 16) & 0xff;
sl@0
   611
    ud.unwind_word <<= 16;         /* 2 explicit unwind bytes in this word */
sl@0
   612
    ud.unwind_word_bytes_remaining = 2;
sl@0
   613
  }
sl@0
   614
sl@0
   615
#ifdef PR_DIAGNOSTICS
sl@0
   616
  /*  debug_print_vrs(context); */
sl@0
   617
#endif
sl@0
   618
sl@0
   619
  while (1) {
sl@0
   620
    uint8_t ub = next_unwind_byte(&ud);
sl@0
   621
sl@0
   622
#ifdef PR_DIAGNOSTICS
sl@0
   623
    printf("PR Unwind byte 0x%x\n", ub);
sl@0
   624
#endif
sl@0
   625
sl@0
   626
    /* decode and execute the current byte ... */
sl@0
   627
sl@0
   628
    if (ub == CODE_FINISH) { /* finished unwinding */
sl@0
   629
      if (!wrote_pc) {
sl@0
   630
        uint32_t lr;
sl@0
   631
        if (!wrote_lr) {
sl@0
   632
          /* If neither pc nor lr was written, the saved return address was
sl@0
   633
           * not restored. This indicates broken unwind instructions.
sl@0
   634
           */
sl@0
   635
          DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_TABLECORRUPT);
sl@0
   636
          return _URC_FAILURE;
sl@0
   637
        }
sl@0
   638
        _Unwind_VRS_Get(context, _UVRSC_CORE, R_LR, _UVRSD_UINT32, &lr);
sl@0
   639
        core_set(context, R_PC, lr);
sl@0
   640
        wrote_pc_from_lr = true;
sl@0
   641
      }
sl@0
   642
#ifdef PR_DIAGNOSTICS
sl@0
   643
      {
sl@0
   644
        uint32_t nextpc;
sl@0
   645
        _Unwind_VRS_Get(context, _UVRSC_CORE, R_PC, _UVRSD_UINT32, &nextpc);
sl@0
   646
        printf("PR Next PC is  0x%x\n", nextpc);
sl@0
   647
      }
sl@0
   648
#endif
sl@0
   649
      break;
sl@0
   650
    }
sl@0
   651
    if (ub <= 0x3f) { /* 00nnnnnn: vsp += (nnnnnn << 2) + 4 */
sl@0
   652
      uint32_t increment = ((ub & 0x3f) << 2) + 4;
sl@0
   653
      core_set(context, R_SP, core_get(context, R_SP) + increment);
sl@0
   654
      continue;
sl@0
   655
    }
sl@0
   656
    if (ub <= 0x7f) { /* 01xxxxxx: vsp -= (xxxxxx << 2) + 4 */
sl@0
   657
      uint32_t decrement = ((ub & 0x3f) << 2) + 4;
sl@0
   658
      core_set(context, R_SP, core_get(context, R_SP) - decrement);
sl@0
   659
      continue;
sl@0
   660
    }
sl@0
   661
    if (ub <= 0x8f) { /* 100000000 00000000: refuse, 1000rrrr rrrrrrrr: pop integer regs */
sl@0
   662
      uint32_t mask = (ub & 0xf) << 12;
sl@0
   663
      ub = next_unwind_byte(&ud);
sl@0
   664
      mask |= ub << 4;
sl@0
   665
      if (mask == 0) { /* 10000000 00000000 refuse to unwind */
sl@0
   666
        DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_NOUNWIND);
sl@0
   667
        return _URC_FAILURE;
sl@0
   668
      }
sl@0
   669
      if (_Unwind_VRS_Pop(context, _UVRSC_CORE, mask, _UVRSD_UINT32) != _UVRSR_OK) {
sl@0
   670
        DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_VRSFAILED);
sl@0
   671
        return _URC_FAILURE;
sl@0
   672
      }
sl@0
   673
      if (mask & (1 << R_PC)) wrote_pc = true;
sl@0
   674
      if (mask & (1 << R_LR)) wrote_lr = true;
sl@0
   675
      continue;
sl@0
   676
    }
sl@0
   677
    if (ub <= 0x9f) { /* 1001nnnn: vsp = r[nnnn] if not 13,15 */
sl@0
   678
      uint8_t regno = ub & 0xf;
sl@0
   679
      if (regno == 13 || regno == R_PC) {  /* reserved */
sl@0
   680
        DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_CPP_BADOPCODE);
sl@0
   681
        return _URC_FAILURE;
sl@0
   682
      }
sl@0
   683
      core_set(context, R_SP, core_get(context, regno));
sl@0
   684
      continue;
sl@0
   685
    }
sl@0
   686
    if (ub <= 0xaf) { /* 1010xnnn: pop r4-r[4+nnn], +r14 if x */
sl@0
   687
      uint32_t mask = count_to_mask((ub & 0x7) + 1) << 4;
sl@0
   688
      if (ub & 0x8) {
sl@0
   689
        mask |= (1 << R_LR);
sl@0
   690
        wrote_lr = true;
sl@0
   691
      }
sl@0
   692
      if (_Unwind_VRS_Pop(context, _UVRSC_CORE, mask, _UVRSD_UINT32) != _UVRSR_OK) {
sl@0
   693
        DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_VRSFAILED);
sl@0
   694
        return _URC_FAILURE;
sl@0
   695
      }
sl@0
   696
      continue;
sl@0
   697
    }
sl@0
   698
    if (ub <= 0xb7) {
sl@0
   699
      /* if (ub == 0xb0) is CODE_FINISH, handled earlier */
sl@0
   700
      if (ub == 0xb1) { /* 10110001 0000iiii pop integer regs, others reserved */
sl@0
   701
        uint32_t mask = next_unwind_byte(&ud);
sl@0
   702
        if (mask == 0 || mask > 0xf) { /* reserved */
sl@0
   703
          DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_CPP_BADOPCODE);
sl@0
   704
          return _URC_FAILURE;
sl@0
   705
        }
sl@0
   706
        if (_Unwind_VRS_Pop(context, _UVRSC_CORE, mask, _UVRSD_UINT32) != _UVRSR_OK) {
sl@0
   707
          DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_VRSFAILED);
sl@0
   708
          return _URC_FAILURE;
sl@0
   709
        }
sl@0
   710
        continue;
sl@0
   711
      }
sl@0
   712
      if (ub == 0xb2) { /* 10110010 uleb128 : vsp += (uleb128 << 2) + 0x204 */
sl@0
   713
        uint32_t u = 0;
sl@0
   714
        uint32_t n = 0;
sl@0
   715
        /* decode */
sl@0
   716
        while (1) {
sl@0
   717
          ub = next_unwind_byte(&ud);
sl@0
   718
          u |= (ub & 0x7f) << n;
sl@0
   719
          if ((ub & 0x80) == 0) break;
sl@0
   720
          n += 7;
sl@0
   721
        }
sl@0
   722
        core_set(context, R_SP, core_get(context, R_SP) + (u << 2) + 0x204);
sl@0
   723
        continue;
sl@0
   724
      }
sl@0
   725
      if (ub == 0xb3) { /* 10110011: pop vfp from FSTMFDX */
sl@0
   726
        uint32_t discriminator = next_unwind_byte(&ud);
sl@0
   727
        discriminator = ((discriminator & 0xf0) << 12) | ((discriminator & 0x0f) + 1);
sl@0
   728
        if (_Unwind_VRS_Pop(context, _UVRSC_VFP, discriminator, _UVRSD_VFPX) != _UVRSR_OK) {
sl@0
   729
          DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_VRSFAILED);
sl@0
   730
          return _URC_FAILURE;
sl@0
   731
        }
sl@0
   732
        continue;
sl@0
   733
      }
sl@0
   734
      { /* 101101nn: was pop fpa, now spare */
sl@0
   735
        DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_CPP_BADOPCODE);
sl@0
   736
        return _URC_FAILURE;
sl@0
   737
      }
sl@0
   738
    } /* if (ub <= 0xb7) ... */
sl@0
   739
    if (ub <= 0xbf) { /* 10111nnn: pop vfp from FSTMFDX */
sl@0
   740
      uint32_t discriminator = 0x80000 | ((ub & 0x7) + 1);
sl@0
   741
      if (_Unwind_VRS_Pop(context, _UVRSC_VFP, discriminator, _UVRSD_VFPX) != _UVRSR_OK) {
sl@0
   742
        DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_VRSFAILED);
sl@0
   743
        return _URC_FAILURE;
sl@0
   744
      }
sl@0
   745
      continue;
sl@0
   746
    }
sl@0
   747
    if (ub <= 0xc7) {
sl@0
   748
      if (ub == 0xc7) { /* 11000111: WMMX C regs */
sl@0
   749
        uint32_t mask = next_unwind_byte(&ud);
sl@0
   750
        if (mask == 0 || mask > 0xf) { /* reserved */
sl@0
   751
          DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_CPP_BADOPCODE);
sl@0
   752
          return _URC_FAILURE;
sl@0
   753
        }
sl@0
   754
        if (_Unwind_VRS_Pop(context, _UVRSC_WMMXC, mask, _UVRSD_UINT32) != _UVRSR_OK) {
sl@0
   755
          DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_VRSFAILED);
sl@0
   756
          return _URC_FAILURE;
sl@0
   757
        }
sl@0
   758
        continue;
sl@0
   759
      } else if (ub == 0xc6) { /* 11000110: WMMX D regs */
sl@0
   760
        uint32_t discriminator = next_unwind_byte(&ud);
sl@0
   761
        discriminator = ((discriminator & 0xf0) << 12) | ((discriminator & 0x0f) + 1);
sl@0
   762
        if (_Unwind_VRS_Pop(context, _UVRSC_WMMXD, discriminator, _UVRSD_UINT64) != _UVRSR_OK) {
sl@0
   763
          DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_VRSFAILED);
sl@0
   764
          return _URC_FAILURE;
sl@0
   765
        }
sl@0
   766
        continue;
sl@0
   767
      } else {
sl@0
   768
        /* 11000nnn (nnn != 6, 7): WMMX D regs */
sl@0
   769
        uint32_t discriminator = 0xa0000 | ((ub & 0x7) + 1);
sl@0
   770
        if (_Unwind_VRS_Pop(context, _UVRSC_WMMXD, discriminator, _UVRSD_UINT64) != _UVRSR_OK) {
sl@0
   771
          DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_VRSFAILED);
sl@0
   772
          return _URC_FAILURE;
sl@0
   773
        }
sl@0
   774
        continue;
sl@0
   775
      }
sl@0
   776
    } /* if (ub <= 0xc7) ... */
sl@0
   777
    if (ub == 0xc8 || /* 11001000 sssscccc: pop VFP hi regs from FSTMFDD */
sl@0
   778
        ub == 0xc9) { /* 11001001 sssscccc: pop VFP from FSTMFDD */
sl@0
   779
      uint32_t discriminator = next_unwind_byte(&ud);
sl@0
   780
      discriminator = ((discriminator & 0xf0) << 12) | ((discriminator & 0x0f) + 1);
sl@0
   781
      if (ub == 0xc8) discriminator += 16 << 16;
sl@0
   782
      if (_Unwind_VRS_Pop(context, _UVRSC_VFP, discriminator, _UVRSD_DOUBLE) != _UVRSR_OK) {
sl@0
   783
        DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_VRSFAILED);
sl@0
   784
        return _URC_FAILURE;
sl@0
   785
      }
sl@0
   786
      continue;
sl@0
   787
    }
sl@0
   788
    if (ub <= 0xcf) { /* spare */
sl@0
   789
      DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_CPP_BADOPCODE);
sl@0
   790
      return _URC_FAILURE;
sl@0
   791
    }
sl@0
   792
    if (ub <= 0xd7) { /* 11010nnn: pop VFP from FSTMFDD */
sl@0
   793
      uint32_t discriminator = 0x80000 | ((ub & 0x7) + 1);
sl@0
   794
      if (_Unwind_VRS_Pop(context, _UVRSC_VFP, discriminator, _UVRSD_DOUBLE) != _UVRSR_OK) {
sl@0
   795
        DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_VRSFAILED);
sl@0
   796
        return _URC_FAILURE;
sl@0
   797
      }
sl@0
   798
      continue;
sl@0
   799
    }
sl@0
   800
    /* and in fact everything else is currently reserved or spare */
sl@0
   801
    DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_ENDING, _UAARG_ENDING_CPP_BADOPCODE);
sl@0
   802
    return _URC_FAILURE;
sl@0
   803
  }
sl@0
   804
 
sl@0
   805
#ifdef PR_DIAGNOSTICS
sl@0
   806
  /* debug_print_vrs(context); */
sl@0
   807
#endif
sl@0
   808
sl@0
   809
  /* The VRS has now been updated to reflect the virtual unwind.
sl@0
   810
   * If we are dealing with an unmatched fnspec, pop intervening frames 
sl@0
   811
   * and call unexpected(). Else return to our caller with an
sl@0
   812
   * indication to continue unwinding.
sl@0
   813
   */
sl@0
   814
sl@0
   815
  if (phase2_call_unexpected_after_unwind) {
sl@0
   816
    /* Set up the VRS to enter __cxa_call_unexpected,
sl@0
   817
     * and upload the VRS to the real machine.
sl@0
   818
     * The barrier_cache was initialised earlier.
sl@0
   819
     */
sl@0
   820
#ifdef PR_DIAGNOSTICS
sl@0
   821
    printf("PR Got fnspec barrier in phase 2 (unwinding completed)\n");
sl@0
   822
#endif
sl@0
   823
    core_set(context, 0, (uint32_t)ucbp);
sl@0
   824
    if (!wrote_pc_from_lr) {
sl@0
   825
      uint32_t pc;
sl@0
   826
      /* Move the return address to lr to simulate a call */
sl@0
   827
      _Unwind_VRS_Get(context, _UVRSC_CORE, R_PC, _UVRSD_UINT32, &pc);
sl@0
   828
      core_set(context, R_LR, pc);
sl@0
   829
    }
sl@0
   830
    core_set(context, R_PC, (uint32_t)&__cxa_call_unexpected);
sl@0
   831
    DEBUGGER_BOTTLENECK(ucbp, _UASUBSYS_CPP, _UAACT_PADENTRY, &__cxa_call_unexpected);
sl@0
   832
    return _URC_INSTALL_CONTEXT;
sl@0
   833
  }
sl@0
   834
  
sl@0
   835
  /* Else continue with next frame */
sl@0
   836
  return _URC_CONTINUE_UNWIND;
sl@0
   837
}
sl@0
   838
sl@0
   839
#endif
sl@0
   840
/* end ifdef prcommon_c */