Home | History | Annotate | Download | only in ia64
      1 /* libunwind - a platform-independent unwind library
      2    Copyright (C) 2001-2005 Hewlett-Packard Co
      3 	Contributed by David Mosberger-Tang <davidm (at) hpl.hp.com>
      4 
      5 This file is part of libunwind.
      6 
      7 Permission is hereby granted, free of charge, to any person obtaining
      8 a copy of this software and associated documentation files (the
      9 "Software"), to deal in the Software without restriction, including
     10 without limitation the rights to use, copy, modify, merge, publish,
     11 distribute, sublicense, and/or sell copies of the Software, and to
     12 permit persons to whom the Software is furnished to do so, subject to
     13 the following conditions:
     14 
     15 The above copyright notice and this permission notice shall be
     16 included in all copies or substantial portions of the Software.
     17 
     18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
     22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
     23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
     25 
     26 #ifndef unwind_i_h
     27 #define unwind_i_h
     28 
     29 #include <string.h>
     30 #include <inttypes.h>
     31 
     32 #include <libunwind-ia64.h>
     33 
     34 #include "rse.h"
     35 
     36 #include "libunwind_i.h"
     37 
     38 #define IA64_UNW_VER(x)		    ((x) >> 48)
     39 #define IA64_UNW_FLAG_MASK	    ((unw_word_t) 0x0000ffff00000000ULL)
     40 #define IA64_UNW_FLAG_OSMASK	    ((unw_word_t) 0x0000f00000000000ULL)
     41 #define IA64_UNW_FLAG_EHANDLER(x)   ((x) & (unw_word_t) 0x0000000100000000ULL)
     42 #define IA64_UNW_FLAG_UHANDLER(x)   ((x) & (unw_word_t) 0x0000000200000000ULL)
     43 #define IA64_UNW_LENGTH(x)	    ((x) & (unw_word_t) 0x00000000ffffffffULL)
     44 
     45 #ifdef MIN
     46 # undef MIN
     47 #endif
     48 #define MIN(a,b)	((a) < (b) ? (a) : (b))
     49 
     50 #if !defined(HAVE_SYS_UC_ACCESS_H) && !defined(UNW_REMOTE_ONLY)
     51 
     52 static ALWAYS_INLINE void *
     53 inlined_uc_addr (ucontext_t *uc, int reg, uint8_t *nat_bitnr)
     54 {
     55   unw_word_t reg_addr;
     56   void *addr;
     57 
     58   switch (reg)
     59     {
     60     case UNW_IA64_GR + 0:	addr = &unw.read_only.r0; break;
     61     case UNW_IA64_NAT + 0:	addr = &unw.read_only.r0; break;
     62     case UNW_IA64_FR + 0:	addr = &unw.read_only.f0; break;
     63     case UNW_IA64_FR + 1:
     64       if (__BYTE_ORDER == __BIG_ENDIAN)
     65 	addr = &unw.read_only.f1_be;
     66       else
     67 	addr = &unw.read_only.f1_le;
     68       break;
     69     case UNW_IA64_IP:		addr = &uc->uc_mcontext.sc_br[0]; break;
     70     case UNW_IA64_CFM:		addr = &uc->uc_mcontext.sc_ar_pfs; break;
     71     case UNW_IA64_AR_RNAT:	addr = &uc->uc_mcontext.sc_ar_rnat; break;
     72     case UNW_IA64_AR_UNAT:	addr = &uc->uc_mcontext.sc_ar_unat; break;
     73     case UNW_IA64_AR_LC:	addr = &uc->uc_mcontext.sc_ar_lc; break;
     74     case UNW_IA64_AR_FPSR:	addr = &uc->uc_mcontext.sc_ar_fpsr; break;
     75     case UNW_IA64_PR:		addr = &uc->uc_mcontext.sc_pr; break;
     76     case UNW_IA64_AR_BSPSTORE:	addr = &uc->uc_mcontext.sc_ar_bsp; break;
     77 
     78     case UNW_IA64_GR + 4 ... UNW_IA64_GR + 7:
     79     case UNW_IA64_GR + 12:
     80       addr = &uc->uc_mcontext.sc_gr[reg - UNW_IA64_GR];
     81       break;
     82 
     83     case UNW_IA64_NAT + 4 ... UNW_IA64_NAT + 7:
     84     case UNW_IA64_NAT + 12:
     85       addr = &uc->uc_mcontext.sc_nat;
     86       reg_addr = (unw_word_t) &uc->uc_mcontext.sc_gr[reg - UNW_IA64_NAT];
     87       *nat_bitnr = reg - UNW_IA64_NAT;
     88       break;
     89 
     90     case UNW_IA64_BR + 1 ... UNW_IA64_BR + 5:
     91       addr = &uc->uc_mcontext.sc_br[reg - UNW_IA64_BR];
     92       break;
     93 
     94     case UNW_IA64_FR+ 2 ... UNW_IA64_FR+ 5:
     95     case UNW_IA64_FR+16 ... UNW_IA64_FR+31:
     96       addr = &uc->uc_mcontext.sc_fr[reg - UNW_IA64_FR];
     97       break;
     98 
     99     default:
    100       addr = NULL;
    101     }
    102   return addr;
    103 }
    104 
    105 static inline void *
    106 uc_addr (ucontext_t *uc, int reg, uint8_t *nat_bitnr)
    107 {
    108   if (__builtin_constant_p (reg))
    109     return inlined_uc_addr (uc, reg, nat_bitnr);
    110   else
    111     return tdep_uc_addr (uc, reg, nat_bitnr);
    112 }
    113 
    114 /* Return TRUE if ADDR points inside unw.read_only_reg.  */
    115 
    116 static inline long
    117 ia64_read_only_reg (void *addr)
    118 {
    119   return ((unsigned long) ((char *) addr - (char *) &unw.read_only)
    120 	  < sizeof (unw.read_only));
    121 }
    122 
    123 #endif /* !defined(HAVE_SYS_UC_ACCESS_H) && !defined(UNW_REMOTE_ONLY) */
    124 
    125 /* Bits 0 and 1 of a location are used to encode its type:
    126 	bit 0: set if location uses floating-point format.
    127 	bit 1: set if location is a NaT bit on memory stack.  */
    128 
    129 #define IA64_LOC_TYPE_FP		(1 << 0)
    130 #define IA64_LOC_TYPE_MEMSTK_NAT	(1 << 1)
    131 
    132 #ifdef UNW_LOCAL_ONLY
    133 #define IA64_LOC_REG(r,t)	(((r) << 2) | (t))
    134 #define IA64_LOC_ADDR(a,t)	(((a) & ~0x3) | (t))
    135 #define IA64_LOC_UC_ADDR(a,t)	IA64_LOC_ADDR(a, t)
    136 #define IA64_NULL_LOC		(0)
    137 
    138 #define IA64_GET_REG(l)		((l) >> 2)
    139 #define IA64_GET_ADDR(l)	((l) & ~0x3)
    140 #define IA64_IS_NULL_LOC(l)	((l) == 0)
    141 #define IA64_IS_FP_LOC(l)	(((l) & IA64_LOC_TYPE_FP) != 0)
    142 #define IA64_IS_MEMSTK_NAT(l)	(((l) & IA64_LOC_TYPE_MEMSTK_NAT) != 0)
    143 #define IA64_IS_REG_LOC(l)	0
    144 #define IA64_IS_UC_LOC(l)	0
    145 
    146 #define IA64_REG_LOC(c,r)	((unw_word_t) uc_addr((c)->as_arg, r, NULL))
    147 #define IA64_REG_NAT_LOC(c,r,n)	((unw_word_t) uc_addr((c)->as_arg, r, n))
    148 #define IA64_FPREG_LOC(c,r)						 \
    149 	((unw_word_t) uc_addr((c)->as_arg, (r), NULL) | IA64_LOC_TYPE_FP)
    150 
    151 # define ia64_find_proc_info(c,ip,n)					\
    152 	tdep_find_proc_info(unw_local_addr_space, (ip), &(c)->pi, (n),	\
    153 			    (c)->as_arg)
    154 # define ia64_put_unwind_info(c, pi)	do { ; } while (0)
    155 
    156 /* Note: the register accessors (ia64_{get,set}{,fp}()) must check for
    157    NULL locations because uc_addr() returns NULL for unsaved
    158    registers.  */
    159 
    160 static inline int
    161 ia64_getfp (struct cursor *c, unw_word_t loc, unw_fpreg_t *val)
    162 {
    163   if (IA64_IS_NULL_LOC (loc))
    164     {
    165       Debug (16, "access to unsaved register\n");
    166       return -UNW_EBADREG;
    167     }
    168   *val = *(unw_fpreg_t *) IA64_GET_ADDR (loc);
    169   return 0;
    170 }
    171 
    172 static inline int
    173 ia64_putfp (struct cursor *c, unw_word_t loc, unw_fpreg_t val)
    174 {
    175   unw_fpreg_t *addr = (unw_fpreg_t *) IA64_GET_ADDR (loc);
    176 
    177   if (IA64_IS_NULL_LOC (loc))
    178     {
    179       Debug (16, "access to unsaved register\n");
    180       return -UNW_EBADREG;
    181     }
    182   else if (ia64_read_only_reg (addr))
    183     {
    184       Debug (16, "attempt to read-only register\n");
    185       return -UNW_EREADONLYREG;
    186     }
    187   *addr = val;
    188   return 0;
    189 }
    190 
    191 static inline int
    192 ia64_get (struct cursor *c, unw_word_t loc, unw_word_t *val)
    193 {
    194   if (IA64_IS_NULL_LOC (loc))
    195     {
    196       Debug (16, "access to unsaved register\n");
    197       return -UNW_EBADREG;
    198     }
    199   *val = *(unw_word_t *) IA64_GET_ADDR (loc);
    200   return 0;
    201 }
    202 
    203 static inline int
    204 ia64_put (struct cursor *c, unw_word_t loc, unw_word_t val)
    205 {
    206   unw_word_t *addr = (unw_word_t *) IA64_GET_ADDR (loc);
    207 
    208   if (IA64_IS_NULL_LOC (loc))
    209     {
    210       Debug (16, "access to unsaved register\n");
    211       return -UNW_EBADREG;
    212     }
    213   else if (ia64_read_only_reg (addr))
    214     {
    215       Debug (16, "attempt to read-only register\n");
    216       return -UNW_EREADONLYREG;
    217     }
    218   *addr = val;
    219   return 0;
    220 }
    221 
    222 #else /* !UNW_LOCAL_ONLY */
    223 
    224 /* Bits 0 and 1 of the second word (w1) of a location are used
    225    to further distinguish what location we're dealing with:
    226 
    227    	bit 0: set if the location is a register
    228 	bit 1: set of the location is accessed via uc_access(3)  */
    229 #define IA64_LOC_TYPE_REG	(1 << 0)
    230 #define IA64_LOC_TYPE_UC	(1 << 1)
    231 
    232 #define IA64_LOC_REG(r,t)	((ia64_loc_t) { ((r) << 2) | (t),	\
    233 						IA64_LOC_TYPE_REG })
    234 #define IA64_LOC_ADDR(a,t)	((ia64_loc_t) { ((a) & ~0x3) | (t), 0 })
    235 #define IA64_LOC_UC_ADDR(a,t)	((ia64_loc_t) { ((a) & ~0x3) | (t),	\
    236 						IA64_LOC_TYPE_UC })
    237 #define IA64_LOC_UC_REG(r,a)	((ia64_loc_t) { ((r) << 2),		 \
    238 						((a) | IA64_LOC_TYPE_REG \
    239 					         | IA64_LOC_TYPE_UC) })
    240 #define IA64_NULL_LOC		((ia64_loc_t) { 0, 0 })
    241 
    242 #define IA64_GET_REG(l)		((l).w0 >> 2)
    243 #define IA64_GET_ADDR(l)	((l).w0 & ~0x3)
    244 #define IA64_GET_AUX_ADDR(l)	((l).w1 & ~0x3)
    245 #define IA64_IS_NULL_LOC(l)	(((l).w0 | (l).w1) == 0)
    246 #define IA64_IS_FP_LOC(l)	(((l).w0 & IA64_LOC_TYPE_FP) != 0)
    247 #define IA64_IS_MEMSTK_NAT(l)	(((l).w0 & IA64_LOC_TYPE_MEMSTK_NAT) != 0)
    248 #define IA64_IS_REG_LOC(l)	(((l).w1 & IA64_LOC_TYPE_REG) != 0)
    249 #define IA64_IS_UC_LOC(l)	(((l).w1 & IA64_LOC_TYPE_UC) != 0)
    250 
    251 #define IA64_REG_LOC(c,r)	IA64_LOC_REG ((r), 0)
    252 #define IA64_REG_NAT_LOC(c,r,n)	IA64_LOC_REG ((r), 0)
    253 #define IA64_FPREG_LOC(c,r)	IA64_LOC_REG ((r), IA64_LOC_TYPE_FP)
    254 
    255 # define ia64_find_proc_info(c,ip,n)					\
    256 	(*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n),	\
    257 				       (c)->as_arg)
    258 # define ia64_put_unwind_info(c,pi)					\
    259 	(*(c)->as->acc.put_unwind_info)((c)->as, (pi), (c)->as_arg)
    260 
    261 #define ia64_uc_access_reg	UNW_OBJ(uc_access_reg)
    262 #define ia64_uc_access_fpreg	UNW_OBJ(uc_access_fpreg)
    263 
    264 extern int ia64_uc_access_reg (struct cursor *c, ia64_loc_t loc,
    265 			       unw_word_t *valp, int write);
    266 extern int ia64_uc_access_fpreg (struct cursor *c, ia64_loc_t loc,
    267 				 unw_fpreg_t *valp, int write);
    268 
    269 static inline int
    270 ia64_getfp (struct cursor *c, ia64_loc_t loc, unw_fpreg_t *val)
    271 {
    272   unw_word_t addr;
    273   int ret;
    274 
    275   if (IA64_IS_NULL_LOC (loc))
    276     {
    277       Debug (16, "access to unsaved register\n");
    278       return -UNW_EBADREG;
    279     }
    280 
    281   if (IA64_IS_UC_LOC (loc))
    282     return ia64_uc_access_fpreg (c, loc, val, 0);
    283 
    284   if (IA64_IS_REG_LOC (loc))
    285     return (*c->as->acc.access_fpreg) (c->as, IA64_GET_REG (loc),
    286 				       val, 0, c->as_arg);
    287 
    288   addr = IA64_GET_ADDR (loc);
    289   ret = (*c->as->acc.access_mem) (c->as, addr + 0, &val->raw.bits[0], 0,
    290 				  c->as_arg);
    291   if (ret < 0)
    292     return ret;
    293 
    294   return (*c->as->acc.access_mem) (c->as, addr + 8, &val->raw.bits[1], 0,
    295 				   c->as_arg);
    296 }
    297 
    298 static inline int
    299 ia64_putfp (struct cursor *c, ia64_loc_t loc, unw_fpreg_t val)
    300 {
    301   unw_word_t addr;
    302   int ret;
    303 
    304   if (IA64_IS_NULL_LOC (loc))
    305     {
    306       Debug (16, "access to unsaved register\n");
    307       return -UNW_EBADREG;
    308     }
    309 
    310   if (IA64_IS_UC_LOC (loc))
    311     return ia64_uc_access_fpreg (c, loc, &val, 1);
    312 
    313   if (IA64_IS_REG_LOC (loc))
    314     return (*c->as->acc.access_fpreg) (c->as, IA64_GET_REG (loc), &val, 1,
    315 				       c->as_arg);
    316 
    317   addr = IA64_GET_ADDR (loc);
    318   ret = (*c->as->acc.access_mem) (c->as, addr + 0, &val.raw.bits[0], 1,
    319 				  c->as_arg);
    320   if (ret < 0)
    321     return ret;
    322 
    323   return (*c->as->acc.access_mem) (c->as, addr + 8, &val.raw.bits[1], 1,
    324 				   c->as_arg);
    325 }
    326 
    327 /* Get the 64 data bits from location LOC.  If bit 0 is cleared, LOC
    328    is a memory address, otherwise it is a register number.  If the
    329    register is a floating-point register, the 64 bits are read from
    330    the significand bits.  */
    331 
    332 static inline int
    333 ia64_get (struct cursor *c, ia64_loc_t loc, unw_word_t *val)
    334 {
    335   if (IA64_IS_NULL_LOC (loc))
    336     {
    337       Debug (16, "access to unsaved register\n");
    338       return -UNW_EBADREG;
    339     }
    340 
    341   if (IA64_IS_FP_LOC (loc))
    342     {
    343       unw_fpreg_t tmp;
    344       int ret;
    345 
    346       ret = ia64_getfp (c, loc, &tmp);
    347       if (ret < 0)
    348 	return ret;
    349 
    350       if (c->as->big_endian)
    351 	*val = tmp.raw.bits[1];
    352       else
    353 	*val = tmp.raw.bits[0];
    354       return 0;
    355     }
    356 
    357   if (IA64_IS_UC_LOC (loc))
    358     return ia64_uc_access_reg (c, loc, val, 0);
    359 
    360   if (IA64_IS_REG_LOC (loc))
    361     return (*c->as->acc.access_reg)(c->as, IA64_GET_REG (loc), val, 0,
    362 				    c->as_arg);
    363   else
    364     return (*c->as->acc.access_mem)(c->as, IA64_GET_ADDR (loc), val, 0,
    365 				    c->as_arg);
    366 }
    367 
    368 static inline int
    369 ia64_put (struct cursor *c, ia64_loc_t loc, unw_word_t val)
    370 {
    371   if (IA64_IS_NULL_LOC (loc))
    372     {
    373       Debug (16, "access to unsaved register\n");
    374       return -UNW_EBADREG;
    375     }
    376 
    377   if (IA64_IS_FP_LOC (loc))
    378     {
    379       unw_fpreg_t tmp;
    380 
    381       memset (&tmp, 0, sizeof (tmp));
    382       if (c->as->big_endian)
    383 	tmp.raw.bits[1] = val;
    384       else
    385 	tmp.raw.bits[0] = val;
    386       return ia64_putfp (c, loc, tmp);
    387     }
    388 
    389   if (IA64_IS_UC_LOC (loc))
    390     return ia64_uc_access_reg (c, loc, &val, 1);
    391 
    392   if (IA64_IS_REG_LOC (loc))
    393     return (*c->as->acc.access_reg)(c->as, IA64_GET_REG (loc), &val, 1,
    394 				    c->as_arg);
    395   else
    396     return (*c->as->acc.access_mem)(c->as, IA64_GET_ADDR (loc), &val, 1,
    397 				    c->as_arg);
    398 }
    399 
    400 #endif /* !UNW_LOCAL_ONLY */
    401 
    402 struct ia64_unwind_block
    403   {
    404     unw_word_t header;
    405     unw_word_t desc[0];			/* unwind descriptors */
    406 
    407     /* Personality routine and language-specific data follow behind
    408        descriptors.  */
    409   };
    410 
    411 enum ia64_where
    412   {
    413     IA64_WHERE_NONE,	/* register isn't saved at all */
    414     IA64_WHERE_GR,	/* register is saved in a general register */
    415     IA64_WHERE_FR,	/* register is saved in a floating-point register */
    416     IA64_WHERE_BR,	/* register is saved in a branch register */
    417     IA64_WHERE_SPREL,	/* register is saved on memstack (sp-relative) */
    418     IA64_WHERE_PSPREL,	/* register is saved on memstack (psp-relative) */
    419 
    420     /* At the end of each prologue these locations get resolved to
    421        IA64_WHERE_PSPREL and IA64_WHERE_GR, respectively:  */
    422 
    423     IA64_WHERE_SPILL_HOME, /* register is saved in its spill home */
    424     IA64_WHERE_GR_SAVE	/* register is saved in next general register */
    425   };
    426 
    427 #define IA64_WHEN_NEVER	0x7fffffff
    428 
    429 struct ia64_reg_info
    430   {
    431     unw_word_t val;		/* save location: register number or offset */
    432     enum ia64_where where;	/* where the register gets saved */
    433     int when;			/* when the register gets saved */
    434   };
    435 
    436 struct ia64_labeled_state;	/* opaque structure */
    437 
    438 struct ia64_reg_state
    439   {
    440     struct ia64_reg_state *next;    /* next (outer) element on state stack */
    441     struct ia64_reg_info reg[IA64_NUM_PREGS];	/* register save locations */
    442   };
    443 
    444 struct ia64_state_record
    445   {
    446     unsigned int first_region : 1;	/* is this the first region? */
    447     unsigned int done : 1;		/* are we done scanning descriptors? */
    448     unsigned int any_spills : 1;	/* got any register spills? */
    449     unsigned int in_body : 1;		/* are we inside prologue or body? */
    450     uint8_t *imask;		/* imask of spill_mask record or NULL */
    451     uint16_t abi_marker;
    452 
    453     unw_word_t pr_val;		/* predicate values */
    454     unw_word_t pr_mask;		/* predicate mask */
    455 
    456     long spill_offset;		/* psp-relative offset for spill base */
    457     int region_start;
    458     int region_len;
    459     int when_sp_restored;
    460     int epilogue_count;
    461     int when_target;
    462 
    463     uint8_t gr_save_loc;	/* next save register */
    464     uint8_t return_link_reg;	/* branch register used as return pointer */
    465 
    466     struct ia64_labeled_state *labeled_states;
    467     struct ia64_reg_state curr;
    468   };
    469 
    470 struct ia64_labeled_state
    471   {
    472     struct ia64_labeled_state *next;	/* next label (or NULL) */
    473     unsigned long label;			/* label for this state */
    474     struct ia64_reg_state saved_state;
    475   };
    476 
    477 /* Convenience macros: */
    478 #define ia64_make_proc_info		UNW_OBJ(make_proc_info)
    479 #define ia64_fetch_proc_info		UNW_OBJ(fetch_proc_info)
    480 #define ia64_create_state_record	UNW_OBJ(create_state_record)
    481 #define ia64_free_state_record		UNW_OBJ(free_state_record)
    482 #define ia64_find_save_locs		UNW_OBJ(find_save_locs)
    483 #define ia64_validate_cache		UNW_OBJ(ia64_validate_cache)
    484 #define ia64_local_validate_cache	UNW_OBJ(ia64_local_validate_cache)
    485 #define ia64_per_thread_cache		UNW_OBJ(per_thread_cache)
    486 #define ia64_scratch_loc		UNW_OBJ(scratch_loc)
    487 #define ia64_local_resume		UNW_OBJ(local_resume)
    488 #define ia64_local_addr_space_init	UNW_OBJ(local_addr_space_init)
    489 #define ia64_strloc			UNW_OBJ(strloc)
    490 #define ia64_install_cursor		UNW_OBJ(install_cursor)
    491 #define rbs_switch			UNW_OBJ(rbs_switch)
    492 #define rbs_find_stacked		UNW_OBJ(rbs_find_stacked)
    493 
    494 extern int ia64_make_proc_info (struct cursor *c);
    495 extern int ia64_fetch_proc_info (struct cursor *c, unw_word_t ip,
    496 				 int need_unwind_info);
    497 /* The proc-info must be valid for IP before this routine can be
    498    called:  */
    499 extern int ia64_create_state_record (struct cursor *c,
    500 				     struct ia64_state_record *sr);
    501 extern int ia64_free_state_record (struct ia64_state_record *sr);
    502 extern int ia64_find_save_locs (struct cursor *c);
    503 extern void ia64_validate_cache (unw_addr_space_t as, void *arg);
    504 extern int ia64_local_validate_cache (unw_addr_space_t as, void *arg);
    505 extern void ia64_local_addr_space_init (void);
    506 extern ia64_loc_t ia64_scratch_loc (struct cursor *c, unw_regnum_t reg,
    507 				    uint8_t *nat_bitnr);
    508 
    509 extern NORETURN void ia64_install_cursor (struct cursor *c,
    510 					  unw_word_t pri_unat,
    511 					  unw_word_t *extra,
    512 					  unw_word_t bspstore,
    513 					  unw_word_t dirty_size,
    514 					  unw_word_t *dirty_partition,
    515 					  unw_word_t dirty_rnat);
    516 extern int ia64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor,
    517 			      void *arg);
    518 extern int rbs_switch (struct cursor *c,
    519 		       unw_word_t saved_bsp, unw_word_t saved_bspstore,
    520 		       ia64_loc_t saved_rnat_loc);
    521 extern int rbs_find_stacked (struct cursor *c, unw_word_t regs_to_skip,
    522 			     ia64_loc_t *locp, ia64_loc_t *rnat_locp);
    523 
    524 #ifndef UNW_REMOTE_ONLY
    525 # define NEED_RBS_COVER_AND_FLUSH
    526 # define rbs_cover_and_flush	UNW_OBJ(rbs_cover_and_flush)
    527   extern int rbs_cover_and_flush (struct cursor *c, unw_word_t nregs,
    528 				  unw_word_t *dirty_partition,
    529 				  unw_word_t *dirty_rnat,
    530 				  unw_word_t *bspstore);
    531 #endif
    532 
    533 /* Warning: ia64_strloc() is for debugging only and it is NOT re-entrant! */
    534 extern const char *ia64_strloc (ia64_loc_t loc);
    535 
    536 /* Return true if the register-backing store is inside a ucontext_t
    537    that needs to be accessed via uc_access(3).  */
    538 
    539 static inline int
    540 rbs_on_uc (struct rbs_area *rbs)
    541 {
    542   return IA64_IS_UC_LOC (rbs->rnat_loc) && !IA64_IS_REG_LOC (rbs->rnat_loc);
    543 }
    544 
    545 /* Return true if BSP points to a word that's stored on register
    546    backing-store RBS.  */
    547 static inline int
    548 rbs_contains (struct rbs_area *rbs, unw_word_t bsp)
    549 {
    550   int result;
    551 
    552   /* Caveat: this takes advantage of unsigned arithmetic.  The full
    553      test is (bsp >= rbs->end - rbs->size) && (bsp < rbs->end).  We
    554      take advantage of the fact that -n == ~n + 1.  */
    555   result = bsp - rbs->end > ~rbs->size;
    556   Debug (16, "0x%lx in [0x%lx-0x%lx) => %d\n",
    557 	 (long) bsp, (long) (rbs->end - rbs->size), (long) rbs->end, result);
    558   return result;
    559 }
    560 
    561 static inline ia64_loc_t
    562 rbs_get_rnat_loc (struct rbs_area *rbs, unw_word_t bsp)
    563 {
    564   unw_word_t rnat_addr = rse_rnat_addr (bsp);
    565   ia64_loc_t rnat_loc;
    566 
    567   if (rbs_contains (rbs, rnat_addr))
    568     {
    569       if (rbs_on_uc (rbs))
    570 	rnat_loc = IA64_LOC_UC_ADDR (rnat_addr, 0);
    571       else
    572 	rnat_loc = IA64_LOC_ADDR (rnat_addr, 0);
    573     }
    574   else
    575     rnat_loc = rbs->rnat_loc;
    576   return rnat_loc;
    577 }
    578 
    579 static inline ia64_loc_t
    580 rbs_loc (struct rbs_area *rbs, unw_word_t bsp)
    581 {
    582   if (rbs_on_uc (rbs))
    583     return IA64_LOC_UC_ADDR (bsp, 0);
    584   else
    585     return IA64_LOC_ADDR (bsp, 0);
    586 }
    587 
    588 static inline int
    589 ia64_get_stacked (struct cursor *c, unw_word_t reg,
    590 		  ia64_loc_t *locp, ia64_loc_t *rnat_locp)
    591 {
    592   struct rbs_area *rbs = c->rbs_area + c->rbs_curr;
    593   unw_word_t addr, regs_to_skip = reg - 32;
    594   int ret = 0;
    595 
    596   assert (reg >= 32 && reg < 128);
    597 
    598   addr = rse_skip_regs (c->bsp, regs_to_skip);
    599   if (locp)
    600     *locp = rbs_loc (rbs, addr);
    601   if (rnat_locp)
    602     *rnat_locp = rbs_get_rnat_loc (rbs, addr);
    603 
    604   if (!rbs_contains (rbs, addr))
    605     ret = rbs_find_stacked (c, regs_to_skip, locp, rnat_locp);
    606   return ret;
    607 }
    608 
    609 /* The UNaT slot # calculation is identical to the one for RNaT slots,
    610    but for readability/clarity, we don't want to use
    611    ia64_rnat_slot_num() directly.  */
    612 #define ia64_unat_slot_num(addr)	rse_slot_num(addr)
    613 
    614 /* The following are helper macros which makes it easier for libunwind
    615    to be used in the kernel.  They allow the kernel to optimize away
    616    any unused code without littering everything with #ifdefs.  */
    617 #define ia64_is_big_endian(c)	((c)->as->big_endian)
    618 #define ia64_get_abi(c)		((c)->as->abi)
    619 #define ia64_set_abi(c, v)	((c)->as->abi = (v))
    620 #define ia64_get_abi_marker(c)	((c)->last_abi_marker)
    621 
    622 /* XXX should be in glibc: */
    623 #ifndef IA64_SC_FLAG_ONSTACK
    624 # define IA64_SC_FLAG_ONSTACK_BIT    0 /* running on signal stack? */
    625 # define IA64_SC_FLAG_IN_SYSCALL_BIT 1 /* did signal interrupt a syscall? */
    626 # define IA64_SC_FLAG_FPH_VALID_BIT  2 /* is state in f[32]-f[127] valid? */
    627 
    628 # define IA64_SC_FLAG_ONSTACK		(1 << IA64_SC_FLAG_ONSTACK_BIT)
    629 # define IA64_SC_FLAG_IN_SYSCALL	(1 << IA64_SC_FLAG_IN_SYSCALL_BIT)
    630 # define IA64_SC_FLAG_FPH_VALID		(1 << IA64_SC_FLAG_FPH_VALID_BIT)
    631 #endif
    632 
    633 #endif /* unwind_i_h */
    634