1/* libunwind - a platform-independent unwind library
2   Copyright (C) 2001-2004 Hewlett-Packard Co
3	Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4
5This file is part of libunwind.
6
7Permission is hereby granted, free of charge, to any person obtaining
8a copy of this software and associated documentation files (the
9"Software"), to deal in the Software without restriction, including
10without limitation the rights to use, copy, modify, merge, publish,
11distribute, sublicense, and/or sell copies of the Software, and to
12permit persons to whom the Software is furnished to do so, subject to
13the following conditions:
14
15The above copyright notice and this permission notice shall be
16included in all copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
25
26#include "unwind_i.h"
27
28/* forward declaration: */
29static int create_state_record_for (struct cursor *c,
30				    struct ia64_state_record *sr,
31				    unw_word_t ip);
32
33typedef unsigned long unw_word;
34
35#define alloc_reg_state()	(mempool_alloc (&unw.reg_state_pool))
36#define free_reg_state(rs)	(mempool_free (&unw.reg_state_pool, rs))
37#define alloc_labeled_state()	(mempool_alloc (&unw.labeled_state_pool))
38#define free_labeled_state(s)	(mempool_free (&unw.labeled_state_pool, s))
39
40/* Routines to manipulate the state stack.  */
41
42static inline void
43push (struct ia64_state_record *sr)
44{
45  struct ia64_reg_state *rs;
46
47  rs = alloc_reg_state ();
48  if (!rs)
49    {
50      print_error ("libunwind: cannot stack reg state!\n");
51      return;
52    }
53  memcpy (rs, &sr->curr, sizeof (*rs));
54  sr->curr.next = rs;
55}
56
57static void
58pop (struct ia64_state_record *sr)
59{
60  struct ia64_reg_state *rs = sr->curr.next;
61
62  if (!rs)
63    {
64      print_error ("libunwind: stack underflow!\n");
65      return;
66    }
67  memcpy (&sr->curr, rs, sizeof (*rs));
68  free_reg_state (rs);
69}
70
71/* Make a copy of the state stack.  Non-recursive to avoid stack overflows.  */
72static struct ia64_reg_state *
73dup_state_stack (struct ia64_reg_state *rs)
74{
75  struct ia64_reg_state *copy, *prev = NULL, *first = NULL;
76
77  while (rs)
78    {
79      copy = alloc_reg_state ();
80      if (!copy)
81	{
82	  print_error ("unwind.dup_state_stack: out of memory\n");
83	  return NULL;
84	}
85      memcpy (copy, rs, sizeof (*copy));
86      if (first)
87	prev->next = copy;
88      else
89	first = copy;
90      rs = rs->next;
91      prev = copy;
92    }
93  return first;
94}
95
96/* Free all stacked register states (but not RS itself).  */
97static void
98free_state_stack (struct ia64_reg_state *rs)
99{
100  struct ia64_reg_state *p, *next;
101
102  for (p = rs->next; p != NULL; p = next)
103    {
104      next = p->next;
105      free_reg_state (p);
106    }
107  rs->next = NULL;
108}
109
110/* Unwind decoder routines */
111
112static enum ia64_pregnum CONST_ATTR
113decode_abreg (unsigned char abreg, int memory)
114{
115  switch (abreg)
116    {
117    case 0x04 ... 0x07:
118      return IA64_REG_R4 + (abreg - 0x04);
119    case 0x22 ... 0x25:
120      return IA64_REG_F2 + (abreg - 0x22);
121    case 0x30 ... 0x3f:
122      return IA64_REG_F16 + (abreg - 0x30);
123    case 0x41 ... 0x45:
124      return IA64_REG_B1 + (abreg - 0x41);
125    case 0x60:
126      return IA64_REG_PR;
127    case 0x61:
128      return IA64_REG_PSP;
129    case 0x62:
130      return memory ? IA64_REG_PRI_UNAT_MEM : IA64_REG_PRI_UNAT_GR;
131    case 0x63:
132      return IA64_REG_IP;
133    case 0x64:
134      return IA64_REG_BSP;
135    case 0x65:
136      return IA64_REG_BSPSTORE;
137    case 0x66:
138      return IA64_REG_RNAT;
139    case 0x67:
140      return IA64_REG_UNAT;
141    case 0x68:
142      return IA64_REG_FPSR;
143    case 0x69:
144      return IA64_REG_PFS;
145    case 0x6a:
146      return IA64_REG_LC;
147    default:
148      break;
149    }
150  Dprintf ("libunwind: bad abreg=0x%x\n", abreg);
151  return IA64_REG_LC;
152}
153
154static void
155set_reg (struct ia64_reg_info *reg, enum ia64_where where, int when,
156	 unsigned long val)
157{
158  reg->val = val;
159  reg->where = where;
160  if (reg->when == IA64_WHEN_NEVER)
161    reg->when = when;
162}
163
164static void
165alloc_spill_area (unsigned long *offp, unsigned long regsize,
166		  struct ia64_reg_info *lo, struct ia64_reg_info *hi)
167{
168  struct ia64_reg_info *reg;
169
170  for (reg = hi; reg >= lo; --reg)
171    {
172      if (reg->where == IA64_WHERE_SPILL_HOME)
173	{
174	  reg->where = IA64_WHERE_PSPREL;
175	  *offp -= regsize;
176	  reg->val = *offp;
177	}
178    }
179}
180
181static inline void
182spill_next_when (struct ia64_reg_info **regp, struct ia64_reg_info *lim,
183		 unw_word t)
184{
185  struct ia64_reg_info *reg;
186
187  for (reg = *regp; reg <= lim; ++reg)
188    {
189      if (reg->where == IA64_WHERE_SPILL_HOME)
190	{
191	  reg->when = t;
192	  *regp = reg + 1;
193	  return;
194	}
195    }
196  Dprintf ("libunwind: excess spill!\n");
197}
198
199static inline void
200finish_prologue (struct ia64_state_record *sr)
201{
202  struct ia64_reg_info *reg;
203  unsigned long off;
204  int i;
205
206  /* First, resolve implicit register save locations (see Section
207     "11.4.2.3 Rules for Using Unwind Descriptors", rule 3). */
208  for (i = 0; i < (int) ARRAY_SIZE (unw.save_order); ++i)
209    {
210      reg = sr->curr.reg + unw.save_order[i];
211      if (reg->where == IA64_WHERE_GR_SAVE)
212	{
213	  reg->where = IA64_WHERE_GR;
214	  reg->val = sr->gr_save_loc++;
215	}
216    }
217
218  /* Next, compute when the fp, general, and branch registers get
219     saved.  This must come before alloc_spill_area() because we need
220     to know which registers are spilled to their home locations.  */
221
222  if (sr->imask)
223    {
224      unsigned char kind, mask = 0, *cp = sr->imask;
225      unsigned long t;
226      static const unsigned char limit[3] =
227        {
228	  IA64_REG_F31, IA64_REG_R7, IA64_REG_B5
229	};
230      struct ia64_reg_info *(regs[3]);
231
232      regs[0] = sr->curr.reg + IA64_REG_F2;
233      regs[1] = sr->curr.reg + IA64_REG_R4;
234      regs[2] = sr->curr.reg + IA64_REG_B1;
235
236      for (t = 0; (int) t < sr->region_len; ++t)
237	{
238	  if ((t & 3) == 0)
239	    mask = *cp++;
240	  kind = (mask >> 2 * (3 - (t & 3))) & 3;
241	  if (kind > 0)
242	    spill_next_when (&regs[kind - 1], sr->curr.reg + limit[kind - 1],
243			     sr->region_start + t);
244	}
245    }
246
247  /* Next, lay out the memory stack spill area.  */
248
249  if (sr->any_spills)
250    {
251      off = sr->spill_offset;
252      alloc_spill_area (&off, 16, sr->curr.reg + IA64_REG_F2,
253			sr->curr.reg + IA64_REG_F31);
254      alloc_spill_area (&off, 8, sr->curr.reg + IA64_REG_B1,
255			sr->curr.reg + IA64_REG_B5);
256      alloc_spill_area (&off, 8, sr->curr.reg + IA64_REG_R4,
257			sr->curr.reg + IA64_REG_R7);
258    }
259}
260
261/* Region header descriptors.  */
262
263static void
264desc_prologue (int body, unw_word rlen, unsigned char mask,
265	       unsigned char grsave, struct ia64_state_record *sr)
266{
267  int i, region_start;
268
269  if (!(sr->in_body || sr->first_region))
270    finish_prologue (sr);
271  sr->first_region = 0;
272
273  /* check if we're done: */
274  if (sr->when_target < sr->region_start + sr->region_len)
275    {
276      sr->done = 1;
277      return;
278    }
279
280  region_start = sr->region_start + sr->region_len;
281
282  for (i = 0; i < sr->epilogue_count; ++i)
283    pop (sr);
284  sr->epilogue_count = 0;
285  sr->when_sp_restored = IA64_WHEN_NEVER;
286
287  sr->region_start = region_start;
288  sr->region_len = rlen;
289  sr->in_body = body;
290
291  if (!body)
292    {
293      push (sr);
294
295      if (mask)
296	for (i = 0; i < 4; ++i)
297	  {
298	    if (mask & 0x8)
299	      set_reg (sr->curr.reg + unw.save_order[i], IA64_WHERE_GR,
300		       sr->region_start + sr->region_len - 1, grsave++);
301	    mask <<= 1;
302	  }
303      sr->gr_save_loc = grsave;
304      sr->any_spills = 0;
305      sr->imask = 0;
306      sr->spill_offset = 0x10;	/* default to psp+16 */
307    }
308}
309
310/* Prologue descriptors.  */
311
312static inline void
313desc_abi (unsigned char abi, unsigned char context,
314	  struct ia64_state_record *sr)
315{
316  sr->abi_marker = (abi << 8) | context;
317}
318
319static inline void
320desc_br_gr (unsigned char brmask, unsigned char gr,
321	    struct ia64_state_record *sr)
322{
323  int i;
324
325  for (i = 0; i < 5; ++i)
326    {
327      if (brmask & 1)
328	set_reg (sr->curr.reg + IA64_REG_B1 + i, IA64_WHERE_GR,
329		 sr->region_start + sr->region_len - 1, gr++);
330      brmask >>= 1;
331    }
332}
333
334static inline void
335desc_br_mem (unsigned char brmask, struct ia64_state_record *sr)
336{
337  int i;
338
339  for (i = 0; i < 5; ++i)
340    {
341      if (brmask & 1)
342	{
343	  set_reg (sr->curr.reg + IA64_REG_B1 + i, IA64_WHERE_SPILL_HOME,
344		   sr->region_start + sr->region_len - 1, 0);
345	  sr->any_spills = 1;
346	}
347      brmask >>= 1;
348    }
349}
350
351static inline void
352desc_frgr_mem (unsigned char grmask, unw_word frmask,
353	       struct ia64_state_record *sr)
354{
355  int i;
356
357  for (i = 0; i < 4; ++i)
358    {
359      if ((grmask & 1) != 0)
360	{
361	  set_reg (sr->curr.reg + IA64_REG_R4 + i, IA64_WHERE_SPILL_HOME,
362		   sr->region_start + sr->region_len - 1, 0);
363	  sr->any_spills = 1;
364	}
365      grmask >>= 1;
366    }
367  for (i = 0; i < 20; ++i)
368    {
369      if ((frmask & 1) != 0)
370	{
371	  int base = (i < 4) ? IA64_REG_F2 : IA64_REG_F16 - 4;
372	  set_reg (sr->curr.reg + base + i, IA64_WHERE_SPILL_HOME,
373		   sr->region_start + sr->region_len - 1, 0);
374	  sr->any_spills = 1;
375	}
376      frmask >>= 1;
377    }
378}
379
380static inline void
381desc_fr_mem (unsigned char frmask, struct ia64_state_record *sr)
382{
383  int i;
384
385  for (i = 0; i < 4; ++i)
386    {
387      if ((frmask & 1) != 0)
388	{
389	  set_reg (sr->curr.reg + IA64_REG_F2 + i, IA64_WHERE_SPILL_HOME,
390		   sr->region_start + sr->region_len - 1, 0);
391	  sr->any_spills = 1;
392	}
393      frmask >>= 1;
394    }
395}
396
397static inline void
398desc_gr_gr (unsigned char grmask, unsigned char gr,
399	    struct ia64_state_record *sr)
400{
401  int i;
402
403  for (i = 0; i < 4; ++i)
404    {
405      if ((grmask & 1) != 0)
406	set_reg (sr->curr.reg + IA64_REG_R4 + i, IA64_WHERE_GR,
407		 sr->region_start + sr->region_len - 1, gr++);
408      grmask >>= 1;
409    }
410}
411
412static inline void
413desc_gr_mem (unsigned char grmask, struct ia64_state_record *sr)
414{
415  int i;
416
417  for (i = 0; i < 4; ++i)
418    {
419      if ((grmask & 1) != 0)
420	{
421	  set_reg (sr->curr.reg + IA64_REG_R4 + i, IA64_WHERE_SPILL_HOME,
422		   sr->region_start + sr->region_len - 1, 0);
423	  sr->any_spills = 1;
424	}
425      grmask >>= 1;
426    }
427}
428
429static inline void
430desc_mem_stack_f (unw_word t, unw_word size, struct ia64_state_record *sr)
431{
432  set_reg (sr->curr.reg + IA64_REG_PSP, IA64_WHERE_NONE,
433	   sr->region_start + MIN ((int) t, sr->region_len - 1), 16 * size);
434}
435
436static inline void
437desc_mem_stack_v (unw_word t, struct ia64_state_record *sr)
438{
439  sr->curr.reg[IA64_REG_PSP].when =
440    sr->region_start + MIN ((int) t, sr->region_len - 1);
441}
442
443static inline void
444desc_reg_gr (unsigned char reg, unsigned char dst,
445	     struct ia64_state_record *sr)
446{
447  set_reg (sr->curr.reg + reg, IA64_WHERE_GR,
448	   sr->region_start + sr->region_len - 1, dst);
449}
450
451static inline void
452desc_reg_psprel (unsigned char reg, unw_word pspoff,
453		 struct ia64_state_record *sr)
454{
455  set_reg (sr->curr.reg + reg, IA64_WHERE_PSPREL,
456	   sr->region_start + sr->region_len - 1, 0x10 - 4 * pspoff);
457}
458
459static inline void
460desc_reg_sprel (unsigned char reg, unw_word spoff,
461		struct ia64_state_record *sr)
462{
463  set_reg (sr->curr.reg + reg, IA64_WHERE_SPREL,
464	   sr->region_start + sr->region_len - 1, 4 * spoff);
465}
466
467static inline void
468desc_rp_br (unsigned char dst, struct ia64_state_record *sr)
469{
470  sr->return_link_reg = dst;
471}
472
473static inline void
474desc_reg_when (unsigned char regnum, unw_word t, struct ia64_state_record *sr)
475{
476  struct ia64_reg_info *reg = sr->curr.reg + regnum;
477
478  if (reg->where == IA64_WHERE_NONE)
479    reg->where = IA64_WHERE_GR_SAVE;
480  reg->when = sr->region_start + MIN ((int) t, sr->region_len - 1);
481}
482
483static inline void
484desc_spill_base (unw_word pspoff, struct ia64_state_record *sr)
485{
486  sr->spill_offset = 0x10 - 4 * pspoff;
487}
488
489static inline unsigned char *
490desc_spill_mask (unsigned char *imaskp, struct ia64_state_record *sr)
491{
492  sr->imask = imaskp;
493  return imaskp + (2 * sr->region_len + 7) / 8;
494}
495
496/* Body descriptors.  */
497
498static inline void
499desc_epilogue (unw_word t, unw_word ecount, struct ia64_state_record *sr)
500{
501  sr->when_sp_restored = sr->region_start + sr->region_len - 1 - t;
502  sr->epilogue_count = ecount + 1;
503}
504
505static inline void
506desc_copy_state (unw_word label, struct ia64_state_record *sr)
507{
508  struct ia64_labeled_state *ls;
509
510  for (ls = sr->labeled_states; ls; ls = ls->next)
511    {
512      if (ls->label == label)
513	{
514	  free_state_stack (&sr->curr);
515	  memcpy (&sr->curr, &ls->saved_state, sizeof (sr->curr));
516	  sr->curr.next = dup_state_stack (ls->saved_state.next);
517	  return;
518	}
519    }
520  print_error ("libunwind: failed to find labeled state\n");
521}
522
523static inline void
524desc_label_state (unw_word label, struct ia64_state_record *sr)
525{
526  struct ia64_labeled_state *ls;
527
528  ls = alloc_labeled_state ();
529  if (!ls)
530    {
531      print_error ("unwind.desc_label_state(): out of memory\n");
532      return;
533    }
534  ls->label = label;
535  memcpy (&ls->saved_state, &sr->curr, sizeof (ls->saved_state));
536  ls->saved_state.next = dup_state_stack (sr->curr.next);
537
538  /* insert into list of labeled states: */
539  ls->next = sr->labeled_states;
540  sr->labeled_states = ls;
541}
542
543/* General descriptors.  */
544
545static inline int
546desc_is_active (unsigned char qp, unw_word t, struct ia64_state_record *sr)
547{
548  if (sr->when_target <= sr->region_start + MIN ((int) t, sr->region_len - 1))
549    return 0;
550  if (qp > 0)
551    {
552      if ((sr->pr_val & ((unw_word_t) 1 << qp)) == 0)
553	return 0;
554      sr->pr_mask |= ((unw_word_t) 1 << qp);
555    }
556  return 1;
557}
558
559static inline void
560desc_restore_p (unsigned char qp, unw_word t, unsigned char abreg,
561		struct ia64_state_record *sr)
562{
563  struct ia64_reg_info *r;
564
565  if (!desc_is_active (qp, t, sr))
566    return;
567
568  r = sr->curr.reg + decode_abreg (abreg, 0);
569  r->where = IA64_WHERE_NONE;
570  r->when = IA64_WHEN_NEVER;
571  r->val = 0;
572}
573
574static inline void
575desc_spill_reg_p (unsigned char qp, unw_word t, unsigned char abreg,
576		  unsigned char x, unsigned char ytreg,
577		  struct ia64_state_record *sr)
578{
579  enum ia64_where where = IA64_WHERE_GR;
580  struct ia64_reg_info *r;
581
582  if (!desc_is_active (qp, t, sr))
583    return;
584
585  if (x)
586    where = IA64_WHERE_BR;
587  else if (ytreg & 0x80)
588    where = IA64_WHERE_FR;
589
590  r = sr->curr.reg + decode_abreg (abreg, 0);
591  r->where = where;
592  r->when = sr->region_start + MIN ((int) t, sr->region_len - 1);
593  r->val = (ytreg & 0x7f);
594}
595
596static inline void
597desc_spill_psprel_p (unsigned char qp, unw_word t, unsigned char abreg,
598		     unw_word pspoff, struct ia64_state_record *sr)
599{
600  struct ia64_reg_info *r;
601
602  if (!desc_is_active (qp, t, sr))
603    return;
604
605  r = sr->curr.reg + decode_abreg (abreg, 1);
606  r->where = IA64_WHERE_PSPREL;
607  r->when = sr->region_start + MIN ((int) t, sr->region_len - 1);
608  r->val = 0x10 - 4 * pspoff;
609}
610
611static inline void
612desc_spill_sprel_p (unsigned char qp, unw_word t, unsigned char abreg,
613		    unw_word spoff, struct ia64_state_record *sr)
614{
615  struct ia64_reg_info *r;
616
617  if (!desc_is_active (qp, t, sr))
618    return;
619
620  r = sr->curr.reg + decode_abreg (abreg, 1);
621  r->where = IA64_WHERE_SPREL;
622  r->when = sr->region_start + MIN ((int) t, sr->region_len - 1);
623  r->val = 4 * spoff;
624}
625
626#define UNW_DEC_BAD_CODE(code)						\
627	print_error ("libunwind: unknown code encountered\n")
628
629/* Register names.  */
630#define UNW_REG_BSP		IA64_REG_BSP
631#define UNW_REG_BSPSTORE	IA64_REG_BSPSTORE
632#define UNW_REG_FPSR		IA64_REG_FPSR
633#define UNW_REG_LC		IA64_REG_LC
634#define UNW_REG_PFS		IA64_REG_PFS
635#define UNW_REG_PR		IA64_REG_PR
636#define UNW_REG_RNAT		IA64_REG_RNAT
637#define UNW_REG_PSP		IA64_REG_PSP
638#define UNW_REG_RP		IA64_REG_IP
639#define UNW_REG_UNAT		IA64_REG_UNAT
640
641/* Region headers.  */
642#define UNW_DEC_PROLOGUE_GR(fmt,r,m,gr,arg)	desc_prologue(0,r,m,gr,arg)
643#define UNW_DEC_PROLOGUE(fmt,b,r,arg)		desc_prologue(b,r,0,32,arg)
644
645/* Prologue descriptors.  */
646#define UNW_DEC_ABI(fmt,a,c,arg)		desc_abi(a,c,arg)
647#define UNW_DEC_BR_GR(fmt,b,g,arg)		desc_br_gr(b,g,arg)
648#define UNW_DEC_BR_MEM(fmt,b,arg)		desc_br_mem(b,arg)
649#define UNW_DEC_FRGR_MEM(fmt,g,f,arg)		desc_frgr_mem(g,f,arg)
650#define UNW_DEC_FR_MEM(fmt,f,arg)		desc_fr_mem(f,arg)
651#define UNW_DEC_GR_GR(fmt,m,g,arg)		desc_gr_gr(m,g,arg)
652#define UNW_DEC_GR_MEM(fmt,m,arg)		desc_gr_mem(m,arg)
653#define UNW_DEC_MEM_STACK_F(fmt,t,s,arg)	desc_mem_stack_f(t,s,arg)
654#define UNW_DEC_MEM_STACK_V(fmt,t,arg)		desc_mem_stack_v(t,arg)
655#define UNW_DEC_REG_GR(fmt,r,d,arg)		desc_reg_gr(r,d,arg)
656#define UNW_DEC_REG_PSPREL(fmt,r,o,arg)		desc_reg_psprel(r,o,arg)
657#define UNW_DEC_REG_SPREL(fmt,r,o,arg)		desc_reg_sprel(r,o,arg)
658#define UNW_DEC_REG_WHEN(fmt,r,t,arg)		desc_reg_when(r,t,arg)
659#define UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg) \
660	desc_reg_when(IA64_REG_PRI_UNAT_GR,t,arg)
661#define UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg) \
662	desc_reg_when(IA64_REG_PRI_UNAT_MEM,t,arg)
663#define UNW_DEC_PRIUNAT_GR(fmt,r,arg) \
664	desc_reg_gr(IA64_REG_PRI_UNAT_GR,r,arg)
665#define UNW_DEC_PRIUNAT_PSPREL(fmt,o,arg) \
666	desc_reg_psprel(IA64_REG_PRI_UNAT_MEM,o,arg)
667#define UNW_DEC_PRIUNAT_SPREL(fmt,o,arg) \
668	desc_reg_sprel(IA64_REG_PRI_UNAT_MEM,o,arg)
669#define UNW_DEC_RP_BR(fmt,d,arg)		desc_rp_br(d,arg)
670#define UNW_DEC_SPILL_BASE(fmt,o,arg)		desc_spill_base(o,arg)
671#define UNW_DEC_SPILL_MASK(fmt,m,arg)		(m = desc_spill_mask(m,arg))
672
673/* Body descriptors.  */
674#define UNW_DEC_EPILOGUE(fmt,t,c,arg)		desc_epilogue(t,c,arg)
675#define UNW_DEC_COPY_STATE(fmt,l,arg)		desc_copy_state(l,arg)
676#define UNW_DEC_LABEL_STATE(fmt,l,arg)		desc_label_state(l,arg)
677
678/* General unwind descriptors.  */
679#define UNW_DEC_SPILL_REG_P(f,p,t,a,x,y,arg)	desc_spill_reg_p(p,t,a,x,y,arg)
680#define UNW_DEC_SPILL_REG(f,t,a,x,y,arg)	desc_spill_reg_p(0,t,a,x,y,arg)
681#define UNW_DEC_SPILL_PSPREL_P(f,p,t,a,o,arg) \
682	desc_spill_psprel_p(p,t,a,o,arg)
683#define UNW_DEC_SPILL_PSPREL(f,t,a,o,arg) \
684	desc_spill_psprel_p(0,t,a,o,arg)
685#define UNW_DEC_SPILL_SPREL_P(f,p,t,a,o,arg)	desc_spill_sprel_p(p,t,a,o,arg)
686#define UNW_DEC_SPILL_SPREL(f,t,a,o,arg)	desc_spill_sprel_p(0,t,a,o,arg)
687#define UNW_DEC_RESTORE_P(f,p,t,a,arg)		desc_restore_p(p,t,a,arg)
688#define UNW_DEC_RESTORE(f,t,a,arg)		desc_restore_p(0,t,a,arg)
689
690#include "unwind_decoder.h"
691
692#ifdef _U_dyn_op
693
694/* parse dynamic unwind info */
695
696static struct ia64_reg_info *
697lookup_preg (int regnum, int memory, struct ia64_state_record *sr)
698{
699  int preg;
700
701  switch (regnum)
702    {
703    case UNW_IA64_AR_BSP:		preg = IA64_REG_BSP; break;
704    case UNW_IA64_AR_BSPSTORE:		preg = IA64_REG_BSPSTORE; break;
705    case UNW_IA64_AR_FPSR:		preg = IA64_REG_FPSR; break;
706    case UNW_IA64_AR_LC:		preg = IA64_REG_LC; break;
707    case UNW_IA64_AR_PFS:		preg = IA64_REG_PFS; break;
708    case UNW_IA64_AR_RNAT:		preg = IA64_REG_RNAT; break;
709    case UNW_IA64_AR_UNAT:		preg = IA64_REG_UNAT; break;
710    case UNW_IA64_BR + 0:		preg = IA64_REG_IP; break;
711    case UNW_IA64_PR:			preg = IA64_REG_PR; break;
712    case UNW_IA64_SP:			preg = IA64_REG_PSP; break;
713
714    case UNW_IA64_NAT:
715      if (memory)
716	preg = IA64_REG_PRI_UNAT_MEM;
717      else
718	preg = IA64_REG_PRI_UNAT_GR;
719      break;
720
721    case UNW_IA64_GR + 4 ... UNW_IA64_GR + 7:
722      preg = IA64_REG_R4 + (regnum - (UNW_IA64_GR + 4));
723      break;
724
725    case UNW_IA64_BR + 1 ... UNW_IA64_BR + 5:
726      preg = IA64_REG_B1 + (regnum - UNW_IA64_BR);
727      break;
728
729    case UNW_IA64_FR + 2 ... UNW_IA64_FR + 5:
730      preg = IA64_REG_F2 + (regnum - (UNW_IA64_FR + 2));
731      break;
732
733    case UNW_IA64_FR + 16 ... UNW_IA64_FR + 31:
734      preg = IA64_REG_F16 + (regnum - (UNW_IA64_FR + 16));
735      break;
736
737    default:
738      Dprintf ("%s: invalid register number %d\n", __FUNCTION__, regnum);
739      return NULL;
740    }
741  return sr->curr.reg + preg;
742}
743
744/* An alias directive inside a region of length RLEN is interpreted to
745   mean that the region behaves exactly like the first RLEN
746   instructions at the aliased IP.  RLEN=0 implies that the current
747   state matches exactly that of before the instruction at the aliased
748   IP is executed.  */
749
750static int
751desc_alias (unw_dyn_op_t *op, struct cursor *c, struct ia64_state_record *sr)
752{
753  struct ia64_state_record orig_sr = *sr;
754  int i, ret, when, rlen = sr->region_len;
755  unw_word_t new_ip;
756
757  when = MIN (sr->when_target, rlen);
758  new_ip = op->val + ((when / 3) * 16 + (when % 3));
759
760  if ((ret = ia64_fetch_proc_info (c, new_ip, 1)) < 0)
761    return ret;
762
763  if ((ret = create_state_record_for (c, sr, new_ip)) < 0)
764    return ret;
765
766  sr->first_region = orig_sr.first_region;
767  sr->done = 0;
768  sr->any_spills |= orig_sr.any_spills;
769  sr->in_body = orig_sr.in_body;
770  sr->region_start = orig_sr.region_start;
771  sr->region_len = orig_sr.region_len;
772  if (sr->when_sp_restored != IA64_WHEN_NEVER)
773    sr->when_sp_restored = op->when + MIN (orig_sr.when_sp_restored, rlen);
774  sr->epilogue_count = orig_sr.epilogue_count;
775  sr->when_target = orig_sr.when_target;
776
777  for (i = 0; i < IA64_NUM_PREGS; ++i)
778    if (sr->curr.reg[i].when != IA64_WHEN_NEVER)
779      sr->curr.reg[i].when = op->when + MIN (sr->curr.reg[i].when, rlen);
780
781  ia64_free_state_record (sr);
782  sr->labeled_states = orig_sr.labeled_states;
783  sr->curr.next = orig_sr.curr.next;
784  return 0;
785}
786
787static inline int
788parse_dynamic (struct cursor *c, struct ia64_state_record *sr)
789{
790  unw_dyn_info_t *di = c->pi.unwind_info;
791  unw_dyn_proc_info_t *proc = &di->u.pi;
792  unw_dyn_region_info_t *r;
793  struct ia64_reg_info *ri;
794  enum ia64_where where;
795  int32_t when, len;
796  unw_dyn_op_t *op;
797  unw_word_t val;
798  int memory, ret;
799  int8_t qp;
800
801  for (r = proc->regions; r; r = r->next)
802    {
803      len = r->insn_count;
804      if (len < 0)
805	{
806	  if (r->next)
807	    {
808	      Debug (1, "negative region length allowed in last region only!");
809	      return -UNW_EINVAL;
810	    }
811	  len = -len;
812	  /* hack old region info to set the start where we need it: */
813	  sr->region_start = (di->end_ip - di->start_ip) / 0x10 * 3 - len;
814	  sr->region_len = 0;
815	}
816      /* all regions are treated as prologue regions: */
817      desc_prologue (0, len, 0, 0, sr);
818
819      if (sr->done)
820	return 0;
821
822      for (op = r->op; op < r->op + r->op_count; ++op)
823	{
824	  when = op->when;
825	  val = op->val;
826	  qp = op->qp;
827
828	  if (!desc_is_active (qp, when, sr))
829	    continue;
830
831	  when = sr->region_start + MIN ((int) when, sr->region_len - 1);
832
833	  switch (op->tag)
834	    {
835	    case UNW_DYN_SAVE_REG:
836	      memory = 0;
837	      if ((unsigned) (val - UNW_IA64_GR) < 128)
838		where = IA64_WHERE_GR;
839	      else if ((unsigned) (val - UNW_IA64_FR) < 128)
840		where = IA64_WHERE_FR;
841	      else if ((unsigned) (val - UNW_IA64_BR) < 8)
842		where = IA64_WHERE_BR;
843	      else
844		{
845		  Dprintf ("%s: can't save to register number %d\n",
846			   __FUNCTION__, (int) op->reg);
847		  return -UNW_EBADREG;
848		}
849	      /* fall through */
850	    update_reg_info:
851	      ri = lookup_preg (op->reg, memory, sr);
852	      if (!ri)
853		return -UNW_EBADREG;
854	      ri->where = where;
855	      ri->when = when;
856	      ri->val = val;
857	      break;
858
859	    case UNW_DYN_SPILL_FP_REL:
860	      memory = 1;
861	      where = IA64_WHERE_PSPREL;
862	      val = 0x10 - val;
863	      goto update_reg_info;
864
865	    case UNW_DYN_SPILL_SP_REL:
866	      memory = 1;
867	      where = IA64_WHERE_SPREL;
868	      goto update_reg_info;
869
870	    case UNW_DYN_ADD:
871	      if (op->reg == UNW_IA64_SP)
872		{
873		  if (val & 0xf)
874		    {
875		      Dprintf ("%s: frame-size %ld not an integer "
876			       "multiple of 16\n",
877			       __FUNCTION__, (long) op->val);
878		      return -UNW_EINVAL;
879		    }
880		  desc_mem_stack_f (when, -((int64_t) val / 16), sr);
881		}
882	      else
883		{
884		  Dprintf ("%s: can only ADD to stack-pointer\n",
885			   __FUNCTION__);
886		  return -UNW_EBADREG;
887		}
888	      break;
889
890	    case UNW_DYN_POP_FRAMES:
891	      sr->when_sp_restored = when;
892	      sr->epilogue_count = op->val;
893	      break;
894
895	    case UNW_DYN_LABEL_STATE:
896	      desc_label_state (op->val, sr);
897	      break;
898
899	    case UNW_DYN_COPY_STATE:
900	      desc_copy_state (op->val, sr);
901	      break;
902
903	    case UNW_DYN_ALIAS:
904	      if ((ret = desc_alias (op, c, sr)) < 0)
905		return ret;
906
907	    case UNW_DYN_STOP:
908	      goto end_of_ops;
909	    }
910	}
911    end_of_ops:
912      ;
913    }
914  return 0;
915}
916#else
917# define parse_dynamic(c,sr)	(-UNW_EINVAL)
918#endif /* _U_dyn_op */
919
920
921HIDDEN int
922ia64_fetch_proc_info (struct cursor *c, unw_word_t ip, int need_unwind_info)
923{
924  int ret, dynamic = 1;
925
926  if (c->pi_valid && !need_unwind_info)
927    return 0;
928
929  /* check dynamic info first --- it overrides everything else */
930  ret = unwi_find_dynamic_proc_info (c->as, ip, &c->pi, need_unwind_info,
931				     c->as_arg);
932  if (ret == -UNW_ENOINFO)
933    {
934      dynamic = 0;
935      ret = ia64_find_proc_info (c, ip, need_unwind_info);
936    }
937
938  c->pi_valid = 1;
939  c->pi_is_dynamic = dynamic;
940  return ret;
941}
942
943static inline void
944put_unwind_info (struct cursor *c, unw_proc_info_t *pi)
945{
946  if (!c->pi_valid)
947    return;
948
949  if (c->pi_is_dynamic)
950    unwi_put_dynamic_unwind_info (c->as, pi, c->as_arg);
951  else
952    ia64_put_unwind_info (c, pi);
953}
954
955static int
956create_state_record_for (struct cursor *c, struct ia64_state_record *sr,
957			 unw_word_t ip)
958{
959  unw_word_t predicates = c->pr;
960  struct ia64_reg_info *r;
961  uint8_t *dp, *desc_end;
962  int ret;
963
964  assert (c->pi_valid);
965
966  /* build state record */
967  memset (sr, 0, sizeof (*sr));
968  for (r = sr->curr.reg; r < sr->curr.reg + IA64_NUM_PREGS; ++r)
969    r->when = IA64_WHEN_NEVER;
970  sr->pr_val = predicates;
971  sr->first_region = 1;
972
973  if (!c->pi.unwind_info)
974    {
975      /* No info, return default unwinder (leaf proc, no mem stack, no
976         saved regs), rp in b0, pfs in ar.pfs.  */
977      Debug (1, "no unwind info for ip=0x%lx (gp=%lx)\n",
978	     (long) ip, (long) c->pi.gp);
979      sr->curr.reg[IA64_REG_IP].where = IA64_WHERE_BR;
980      sr->curr.reg[IA64_REG_IP].when = -1;
981      sr->curr.reg[IA64_REG_IP].val = 0;
982      goto out;
983    }
984
985  sr->when_target = (3 * ((ip & ~(unw_word_t) 0xf) - c->pi.start_ip) / 16
986		     + (ip & 0xf));
987
988  switch (c->pi.format)
989    {
990    case UNW_INFO_FORMAT_TABLE:
991    case UNW_INFO_FORMAT_REMOTE_TABLE:
992      dp = c->pi.unwind_info;
993      desc_end = dp + c->pi.unwind_info_size;
994      while (!sr->done && dp < desc_end)
995	dp = unw_decode (dp, sr->in_body, sr);
996      ret = 0;
997      break;
998
999    case UNW_INFO_FORMAT_DYNAMIC:
1000      ret = parse_dynamic (c, sr);
1001      break;
1002
1003    default:
1004      ret = -UNW_EINVAL;
1005    }
1006
1007  put_unwind_info (c, &c->pi);
1008
1009  if (ret < 0)
1010    return ret;
1011
1012  if (sr->when_target > sr->when_sp_restored)
1013    {
1014      /* sp has been restored and all values on the memory stack below
1015	 psp also have been restored.  */
1016      sr->curr.reg[IA64_REG_PSP].val = 0;
1017      sr->curr.reg[IA64_REG_PSP].where = IA64_WHERE_NONE;
1018      sr->curr.reg[IA64_REG_PSP].when = IA64_WHEN_NEVER;
1019      for (r = sr->curr.reg; r < sr->curr.reg + IA64_NUM_PREGS; ++r)
1020	if ((r->where == IA64_WHERE_PSPREL && r->val <= 0x10)
1021	    || r->where == IA64_WHERE_SPREL)
1022	  {
1023	    r->val = 0;
1024	    r->where = IA64_WHERE_NONE;
1025	    r->when = IA64_WHEN_NEVER;
1026	  }
1027    }
1028
1029  /* If RP did't get saved, generate entry for the return link
1030     register.  */
1031  if (sr->curr.reg[IA64_REG_IP].when >= sr->when_target)
1032    {
1033      sr->curr.reg[IA64_REG_IP].where = IA64_WHERE_BR;
1034      sr->curr.reg[IA64_REG_IP].when = -1;
1035      sr->curr.reg[IA64_REG_IP].val = sr->return_link_reg;
1036    }
1037
1038  if (sr->when_target > sr->curr.reg[IA64_REG_BSP].when
1039      && sr->when_target > sr->curr.reg[IA64_REG_BSPSTORE].when
1040      && sr->when_target > sr->curr.reg[IA64_REG_RNAT].when)
1041    {
1042      Debug (8, "func 0x%lx may switch the register-backing-store\n",
1043	     c->pi.start_ip);
1044      c->pi.flags |= UNW_PI_FLAG_IA64_RBS_SWITCH;
1045    }
1046 out:
1047#if UNW_DEBUG
1048  if (unwi_debug_level > 2)
1049    {
1050      Dprintf ("%s: state record for func 0x%lx, t=%u (flags=0x%lx):\n",
1051	       __FUNCTION__,
1052	       (long) c->pi.start_ip, sr->when_target, (long) c->pi.flags);
1053      for (r = sr->curr.reg; r < sr->curr.reg + IA64_NUM_PREGS; ++r)
1054	{
1055	  if (r->where != IA64_WHERE_NONE || r->when != IA64_WHEN_NEVER)
1056	    {
1057	      Dprintf ("  %s <- ", unw.preg_name[r - sr->curr.reg]);
1058	      switch (r->where)
1059		{
1060		case IA64_WHERE_GR:
1061		  Dprintf ("r%lu", (long) r->val);
1062		  break;
1063		case IA64_WHERE_FR:
1064		  Dprintf ("f%lu", (long) r->val);
1065		  break;
1066		case IA64_WHERE_BR:
1067		  Dprintf ("b%lu", (long) r->val);
1068		  break;
1069		case IA64_WHERE_SPREL:
1070		  Dprintf ("[sp+0x%lx]", (long) r->val);
1071		  break;
1072		case IA64_WHERE_PSPREL:
1073		  Dprintf ("[psp+0x%lx]", (long) r->val);
1074		  break;
1075		case IA64_WHERE_NONE:
1076		  Dprintf ("%s+0x%lx",
1077			   unw.preg_name[r - sr->curr.reg], (long) r->val);
1078		  break;
1079		default:
1080		  Dprintf ("BADWHERE(%d)", r->where);
1081		  break;
1082		}
1083	      Dprintf ("\t\t%d\n", r->when);
1084	    }
1085	}
1086    }
1087#endif
1088  return 0;
1089}
1090
1091/* The proc-info must be valid for IP before this routine can be
1092   called.  */
1093HIDDEN int
1094ia64_create_state_record (struct cursor *c, struct ia64_state_record *sr)
1095{
1096  return create_state_record_for (c, sr, c->ip);
1097}
1098
1099HIDDEN int
1100ia64_free_state_record (struct ia64_state_record *sr)
1101{
1102  struct ia64_labeled_state *ls, *next;
1103
1104  /* free labeled register states & stack: */
1105
1106  for (ls = sr->labeled_states; ls; ls = next)
1107    {
1108      next = ls->next;
1109      free_state_stack (&ls->saved_state);
1110      free_labeled_state (ls);
1111    }
1112  free_state_stack (&sr->curr);
1113
1114  return 0;
1115}
1116
1117HIDDEN int
1118ia64_make_proc_info (struct cursor *c)
1119{
1120  int ret, caching = c->as->caching_policy != UNW_CACHE_NONE;
1121
1122  if (!caching || ia64_get_cached_proc_info (c) < 0)
1123    {
1124      /* Lookup it up the slow way... */
1125      if ((ret = ia64_fetch_proc_info (c, c->ip, 0)) < 0)
1126	return ret;
1127      if (caching)
1128	ia64_cache_proc_info (c);
1129    }
1130  return 0;
1131}
1132