00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "tconfig.h"
00035 #include "tsystem.h"
00036 #include "unwind.h"
00037 #include "unwind-ia64.h"
00038 #include "ia64intrin.h"
00039
00040
00041 #undef ENABLE_MALLOC_CHECKING
00042
00043 #ifndef __USING_SJLJ_EXCEPTIONS__
00044 #define UNW_VER(x) ((x) >> 48)
00045 #define UNW_FLAG_MASK 0x0000ffff00000000
00046 #define UNW_FLAG_OSMASK 0x0000f00000000000
00047 #define UNW_FLAG_EHANDLER(x) ((x) & 0x0000000100000000L)
00048 #define UNW_FLAG_UHANDLER(x) ((x) & 0x0000000200000000L)
00049 #define UNW_LENGTH(x) ((x) & 0x00000000ffffffffL)
00050
00051 enum unw_application_register
00052 {
00053 UNW_AR_BSP,
00054 UNW_AR_BSPSTORE,
00055 UNW_AR_PFS,
00056 UNW_AR_RNAT,
00057 UNW_AR_UNAT,
00058 UNW_AR_LC,
00059 UNW_AR_EC,
00060 UNW_AR_FPSR,
00061 UNW_AR_RSC,
00062 UNW_AR_CCV
00063 };
00064
00065 enum unw_register_index
00066 {
00067
00068 UNW_REG_PRI_UNAT_GR,
00069 UNW_REG_PRI_UNAT_MEM,
00070
00071
00072 UNW_REG_PSP,
00073
00074
00075 UNW_REG_BSP,
00076 UNW_REG_BSPSTORE,
00077 UNW_REG_PFS,
00078 UNW_REG_RNAT,
00079
00080 UNW_REG_RP,
00081
00082
00083 UNW_REG_UNAT, UNW_REG_PR, UNW_REG_LC, UNW_REG_FPSR,
00084
00085
00086 UNW_REG_R2,
00087 UNW_REG_R4 = UNW_REG_R2 + 2,
00088 UNW_REG_R7 = UNW_REG_R2 + 5,
00089 UNW_REG_R31 = UNW_REG_R2 + 29,
00090
00091
00092 UNW_REG_F2,
00093 UNW_REG_F5 = UNW_REG_F2 + 3,
00094 UNW_REG_F16 = UNW_REG_F2 + 14,
00095 UNW_REG_F31 = UNW_REG_F2 + 29,
00096
00097
00098 UNW_REG_B0, UNW_REG_B1,
00099 UNW_REG_B5 = UNW_REG_B1 + 4,
00100
00101 UNW_NUM_REGS
00102 };
00103
00104 enum unw_where
00105 {
00106 UNW_WHERE_NONE,
00107 UNW_WHERE_GR,
00108 UNW_WHERE_FR,
00109 UNW_WHERE_BR,
00110 UNW_WHERE_SPREL,
00111 UNW_WHERE_PSPREL,
00112
00113
00114
00115 UNW_WHERE_SPILL_HOME,
00116 UNW_WHERE_GR_SAVE
00117 };
00118
00119 #define UNW_WHEN_NEVER 0x7fffffff
00120
00121 struct unw_reg_info
00122 {
00123 unsigned long val;
00124 enum unw_where where;
00125 int when;
00126 };
00127
00128 struct unw_reg_state {
00129 struct unw_reg_state *next;
00130 struct unw_reg_info reg[UNW_NUM_REGS];
00131 };
00132
00133 struct unw_labeled_state {
00134 struct unw_labeled_state *next;
00135 unsigned long label;
00136 struct unw_reg_state saved_state;
00137 };
00138
00139 typedef struct unw_state_record
00140 {
00141 unsigned int first_region : 1;
00142 unsigned int done : 1;
00143 unsigned int any_spills : 1;
00144 unsigned int in_body : 1;
00145 unsigned int no_reg_stack_frame : 1;
00146 unsigned char *imask;
00147 unsigned long pr_val;
00148 unsigned long pr_mask;
00149 long spill_offset;
00150 int region_start;
00151 int region_len;
00152 int epilogue_start;
00153 int epilogue_count;
00154 int when_target;
00155
00156 unsigned char gr_save_loc;
00157 unsigned char return_link_reg;
00158
00159 struct unw_labeled_state *labeled_states;
00160 struct unw_reg_state curr;
00161
00162 _Unwind_Personality_Fn personality;
00163
00164 } _Unwind_FrameState;
00165
00166 enum unw_nat_type
00167 {
00168 UNW_NAT_NONE,
00169 UNW_NAT_VAL,
00170 UNW_NAT_MEMSTK,
00171 UNW_NAT_REGSTK
00172 };
00173
00174 struct unw_stack
00175 {
00176 unsigned long limit;
00177 unsigned long top;
00178 };
00179
00180 struct _Unwind_Context
00181 {
00182
00183 unsigned long rnat;
00184 unsigned long regstk_top;
00185
00186
00187 unsigned long bsp;
00188
00189 unsigned long sp;
00190 unsigned long psp;
00191 unsigned long rp;
00192 unsigned long pr;
00193
00194 unsigned long region_start;
00195 unsigned long gp;
00196 void *lsda;
00197
00198
00199 unsigned long *bsp_loc;
00200
00201 unsigned long *bspstore_loc;
00202 unsigned long *pfs_loc;
00203
00204
00205 unsigned long *pri_unat_loc;
00206 unsigned long *unat_loc;
00207 unsigned long *lc_loc;
00208 unsigned long *fpsr_loc;
00209
00210 unsigned long eh_data[4];
00211
00212 struct unw_ireg
00213 {
00214 unsigned long *loc;
00215 struct unw_ireg_nat
00216 {
00217 enum unw_nat_type type : 3;
00218 signed long off : 61;
00219 } nat;
00220 } ireg[32 - 2];
00221
00222 unsigned long *br_loc[7];
00223 void *fr_loc[32 - 2];
00224
00225
00226
00227 unsigned long initial_unat;
00228 };
00229
00230 typedef unsigned long unw_word;
00231
00232
00233
00234
00235 static unsigned char const save_order[] =
00236 {
00237 UNW_REG_RP, UNW_REG_PFS, UNW_REG_PSP, UNW_REG_PR,
00238 UNW_REG_UNAT, UNW_REG_LC, UNW_REG_FPSR, UNW_REG_PRI_UNAT_GR
00239 };
00240
00241
00242 #define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
00243
00244
00245
00246
00247
00248 static inline int
00249 atomic_alloc (unsigned int *mask)
00250 {
00251 unsigned int old = *mask, ret, new;
00252
00253 while (1)
00254 {
00255 if (old == 0)
00256 return -1;
00257 ret = old & -old;
00258 new = old & ~ret;
00259 new = __sync_val_compare_and_swap (mask, old, new);
00260 if (old == new)
00261 break;
00262 old = new;
00263 }
00264
00265 return __builtin_ffs (ret) - 1;
00266 }
00267
00268
00269
00270 static inline void
00271 atomic_free (unsigned int *mask, int bit)
00272 {
00273 __sync_xor_and_fetch (mask, 1 << bit);
00274 }
00275
00276
00277 #define SIZE(X) (sizeof(X) / sizeof(*(X)))
00278 #define MASK_FOR(X) ((2U << (SIZE (X) - 1)) - 1)
00279 #define PTR_IN(X, P) ((P) >= (X) && (P) < (X) + SIZE (X))
00280
00281 static struct unw_reg_state emergency_reg_state[32];
00282 static int emergency_reg_state_free = MASK_FOR (emergency_reg_state);
00283
00284 static struct unw_labeled_state emergency_labeled_state[8];
00285 static int emergency_labeled_state_free = MASK_FOR (emergency_labeled_state);
00286
00287 #ifdef ENABLE_MALLOC_CHECKING
00288 static int reg_state_alloced;
00289 static int labeled_state_alloced;
00290 #endif
00291
00292
00293
00294 static struct unw_reg_state *
00295 alloc_reg_state (void)
00296 {
00297 struct unw_reg_state *rs;
00298
00299 #ifdef ENABLE_MALLOC_CHECKING
00300 reg_state_alloced++;
00301 #endif
00302
00303 rs = malloc (sizeof (struct unw_reg_state));
00304 if (!rs)
00305 {
00306 int n = atomic_alloc (&emergency_reg_state_free);
00307 if (n >= 0)
00308 rs = &emergency_reg_state[n];
00309 }
00310
00311 return rs;
00312 }
00313
00314 static void
00315 free_reg_state (struct unw_reg_state *rs)
00316 {
00317 #ifdef ENABLE_MALLOC_CHECKING
00318 reg_state_alloced--;
00319 #endif
00320
00321 if (PTR_IN (emergency_reg_state, rs))
00322 atomic_free (&emergency_reg_state_free, rs - emergency_reg_state);
00323 else
00324 free (rs);
00325 }
00326
00327 static struct unw_labeled_state *
00328 alloc_label_state (void)
00329 {
00330 struct unw_labeled_state *ls;
00331
00332 #ifdef ENABLE_MALLOC_CHECKING
00333 labeled_state_alloced++;
00334 #endif
00335
00336 ls = malloc(sizeof(struct unw_labeled_state));
00337 if (!ls)
00338 {
00339 int n = atomic_alloc (&emergency_labeled_state_free);
00340 if (n >= 0)
00341 ls = &emergency_labeled_state[n];
00342 }
00343
00344 return ls;
00345 }
00346
00347 static void
00348 free_label_state (struct unw_labeled_state *ls)
00349 {
00350 #ifdef ENABLE_MALLOC_CHECKING
00351 labeled_state_alloced--;
00352 #endif
00353
00354 if (PTR_IN (emergency_labeled_state, ls))
00355 atomic_free (&emergency_labeled_state_free, emergency_labeled_state - ls);
00356 else
00357 free (ls);
00358 }
00359
00360
00361
00362 static void
00363 push (struct unw_state_record *sr)
00364 {
00365 struct unw_reg_state *rs = alloc_reg_state ();
00366 memcpy (rs, &sr->curr, sizeof (*rs));
00367 sr->curr.next = rs;
00368 }
00369
00370 static void
00371 pop (struct unw_state_record *sr)
00372 {
00373 struct unw_reg_state *rs = sr->curr.next;
00374
00375 if (!rs)
00376 abort ();
00377 memcpy (&sr->curr, rs, sizeof(*rs));
00378 free_reg_state (rs);
00379 }
00380
00381
00382
00383 static struct unw_reg_state *
00384 dup_state_stack (struct unw_reg_state *rs)
00385 {
00386 struct unw_reg_state *copy, *prev = NULL, *first = NULL;
00387
00388 while (rs)
00389 {
00390 copy = alloc_reg_state ();
00391 memcpy (copy, rs, sizeof(*copy));
00392 if (first)
00393 prev->next = copy;
00394 else
00395 first = copy;
00396 rs = rs->next;
00397 prev = copy;
00398 }
00399
00400 return first;
00401 }
00402
00403
00404 static void
00405 free_state_stack (struct unw_reg_state *rs)
00406 {
00407 struct unw_reg_state *p, *next;
00408
00409 for (p = rs->next; p != NULL; p = next)
00410 {
00411 next = p->next;
00412 free_reg_state (p);
00413 }
00414 rs->next = NULL;
00415 }
00416
00417
00418
00419 static void
00420 free_label_states (struct unw_labeled_state *ls)
00421 {
00422 struct unw_labeled_state *next;
00423
00424 for (; ls ; ls = next)
00425 {
00426 next = ls->next;
00427
00428 free_state_stack (&ls->saved_state);
00429 free_label_state (ls);
00430 }
00431 }
00432
00433
00434
00435 static enum unw_register_index __attribute__((const))
00436 decode_abreg (unsigned char abreg, int memory)
00437 {
00438 switch (abreg)
00439 {
00440 case 0x04 ... 0x07: return UNW_REG_R4 + (abreg - 0x04);
00441 case 0x22 ... 0x25: return UNW_REG_F2 + (abreg - 0x22);
00442 case 0x30 ... 0x3f: return UNW_REG_F16 + (abreg - 0x30);
00443 case 0x41 ... 0x45: return UNW_REG_B1 + (abreg - 0x41);
00444 case 0x60: return UNW_REG_PR;
00445 case 0x61: return UNW_REG_PSP;
00446 case 0x62: return memory ? UNW_REG_PRI_UNAT_MEM : UNW_REG_PRI_UNAT_GR;
00447 case 0x63: return UNW_REG_RP;
00448 case 0x64: return UNW_REG_BSP;
00449 case 0x65: return UNW_REG_BSPSTORE;
00450 case 0x66: return UNW_REG_RNAT;
00451 case 0x67: return UNW_REG_UNAT;
00452 case 0x68: return UNW_REG_FPSR;
00453 case 0x69: return UNW_REG_PFS;
00454 case 0x6a: return UNW_REG_LC;
00455 default:
00456 abort ();
00457 }
00458 }
00459
00460 static void
00461 set_reg (struct unw_reg_info *reg, enum unw_where where,
00462 int when, unsigned long val)
00463 {
00464 reg->val = val;
00465 reg->where = where;
00466 if (reg->when == UNW_WHEN_NEVER)
00467 reg->when = when;
00468 }
00469
00470 static void
00471 alloc_spill_area (unsigned long *offp, unsigned long regsize,
00472 struct unw_reg_info *lo, struct unw_reg_info *hi)
00473 {
00474 struct unw_reg_info *reg;
00475
00476 for (reg = hi; reg >= lo; --reg)
00477 {
00478 if (reg->where == UNW_WHERE_SPILL_HOME)
00479 {
00480 reg->where = UNW_WHERE_PSPREL;
00481 *offp -= regsize;
00482 reg->val = *offp;
00483 }
00484 }
00485 }
00486
00487 static inline void
00488 spill_next_when (struct unw_reg_info **regp, struct unw_reg_info *lim,
00489 unw_word t)
00490 {
00491 struct unw_reg_info *reg;
00492
00493 for (reg = *regp; reg <= lim; ++reg)
00494 {
00495 if (reg->where == UNW_WHERE_SPILL_HOME)
00496 {
00497 reg->when = t;
00498 *regp = reg + 1;
00499 return;
00500 }
00501 }
00502
00503 abort ();
00504 }
00505
00506 static void
00507 finish_prologue (struct unw_state_record *sr)
00508 {
00509 struct unw_reg_info *reg;
00510 unsigned long off;
00511 int i;
00512
00513
00514
00515
00516 for (i = 0; i < (int) sizeof (save_order); ++i)
00517 {
00518 reg = sr->curr.reg + save_order[i];
00519 if (reg->where == UNW_WHERE_GR_SAVE)
00520 {
00521 reg->where = UNW_WHERE_GR;
00522 reg->val = sr->gr_save_loc++;
00523 }
00524 }
00525
00526
00527
00528
00529 if (sr->imask)
00530 {
00531 static unsigned char const limit[3] = {
00532 UNW_REG_F31, UNW_REG_R7, UNW_REG_B5
00533 };
00534
00535 unsigned char kind, mask = 0, *cp = sr->imask;
00536 int t;
00537 struct unw_reg_info *(regs[3]);
00538
00539 regs[0] = sr->curr.reg + UNW_REG_F2;
00540 regs[1] = sr->curr.reg + UNW_REG_R4;
00541 regs[2] = sr->curr.reg + UNW_REG_B1;
00542
00543 for (t = 0; t < sr->region_len; ++t)
00544 {
00545 if ((t & 3) == 0)
00546 mask = *cp++;
00547 kind = (mask >> 2*(3-(t & 3))) & 3;
00548 if (kind > 0)
00549 spill_next_when (®s[kind - 1], sr->curr.reg + limit[kind - 1],
00550 sr->region_start + t);
00551 }
00552 }
00553
00554
00555 if (sr->any_spills)
00556 {
00557 off = sr->spill_offset;
00558 alloc_spill_area (&off, 16, sr->curr.reg + UNW_REG_F2,
00559 sr->curr.reg + UNW_REG_F31);
00560 alloc_spill_area (&off, 8, sr->curr.reg + UNW_REG_B1,
00561 sr->curr.reg + UNW_REG_B5);
00562 alloc_spill_area (&off, 8, sr->curr.reg + UNW_REG_R4,
00563 sr->curr.reg + UNW_REG_R7);
00564 }
00565 }
00566
00567
00568
00569
00570
00571 static void
00572 desc_prologue (int body, unw_word rlen, unsigned char mask,
00573 unsigned char grsave, struct unw_state_record *sr)
00574 {
00575 int i;
00576
00577 if (!(sr->in_body || sr->first_region))
00578 finish_prologue (sr);
00579 sr->first_region = 0;
00580
00581
00582 if (sr->when_target < sr->region_start + sr->region_len)
00583 {
00584 sr->done = 1;
00585 return;
00586 }
00587
00588 for (i = 0; i < sr->epilogue_count; ++i)
00589 pop (sr);
00590
00591 sr->epilogue_count = 0;
00592 sr->epilogue_start = UNW_WHEN_NEVER;
00593
00594 if (!body)
00595 push (sr);
00596
00597 sr->region_start += sr->region_len;
00598 sr->region_len = rlen;
00599 sr->in_body = body;
00600
00601 if (!body)
00602 {
00603 for (i = 0; i < 4; ++i)
00604 {
00605 if (mask & 0x8)
00606 set_reg (sr->curr.reg + save_order[i], UNW_WHERE_GR,
00607 sr->region_start + sr->region_len - 1, grsave++);
00608 mask <<= 1;
00609 }
00610 sr->gr_save_loc = grsave;
00611 sr->any_spills = 0;
00612 sr->imask = 0;
00613 sr->spill_offset = 0x10;
00614 }
00615 }
00616
00617
00618
00619
00620
00621 static inline void
00622 desc_abi (unsigned char abi __attribute__((unused)),
00623 unsigned char context __attribute__((unused)),
00624 struct unw_state_record *sr __attribute__((unused)))
00625 {
00626
00627 }
00628
00629 static inline void
00630 desc_br_gr (unsigned char brmask, unsigned char gr,
00631 struct unw_state_record *sr)
00632 {
00633 int i;
00634
00635 for (i = 0; i < 5; ++i)
00636 {
00637 if (brmask & 1)
00638 set_reg (sr->curr.reg + UNW_REG_B1 + i, UNW_WHERE_GR,
00639 sr->region_start + sr->region_len - 1, gr++);
00640 brmask >>= 1;
00641 }
00642 }
00643
00644 static inline void
00645 desc_br_mem (unsigned char brmask, struct unw_state_record *sr)
00646 {
00647 int i;
00648
00649 for (i = 0; i < 5; ++i)
00650 {
00651 if (brmask & 1)
00652 {
00653 set_reg (sr->curr.reg + UNW_REG_B1 + i, UNW_WHERE_SPILL_HOME,
00654 sr->region_start + sr->region_len - 1, 0);
00655 sr->any_spills = 1;
00656 }
00657 brmask >>= 1;
00658 }
00659 }
00660
00661 static inline void
00662 desc_frgr_mem (unsigned char grmask, unw_word frmask,
00663 struct unw_state_record *sr)
00664 {
00665 int i;
00666
00667 for (i = 0; i < 4; ++i)
00668 {
00669 if ((grmask & 1) != 0)
00670 {
00671 set_reg (sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_SPILL_HOME,
00672 sr->region_start + sr->region_len - 1, 0);
00673 sr->any_spills = 1;
00674 }
00675 grmask >>= 1;
00676 }
00677 for (i = 0; i < 20; ++i)
00678 {
00679 if ((frmask & 1) != 0)
00680 {
00681 enum unw_register_index base = i < 4 ? UNW_REG_F2 : UNW_REG_F16 - 4;
00682 set_reg (sr->curr.reg + base + i, UNW_WHERE_SPILL_HOME,
00683 sr->region_start + sr->region_len - 1, 0);
00684 sr->any_spills = 1;
00685 }
00686 frmask >>= 1;
00687 }
00688 }
00689
00690 static inline void
00691 desc_fr_mem (unsigned char frmask, struct unw_state_record *sr)
00692 {
00693 int i;
00694
00695 for (i = 0; i < 4; ++i)
00696 {
00697 if ((frmask & 1) != 0)
00698 {
00699 set_reg (sr->curr.reg + UNW_REG_F2 + i, UNW_WHERE_SPILL_HOME,
00700 sr->region_start + sr->region_len - 1, 0);
00701 sr->any_spills = 1;
00702 }
00703 frmask >>= 1;
00704 }
00705 }
00706
00707 static inline void
00708 desc_gr_gr (unsigned char grmask, unsigned char gr,
00709 struct unw_state_record *sr)
00710 {
00711 int i;
00712
00713 for (i = 0; i < 4; ++i)
00714 {
00715 if ((grmask & 1) != 0)
00716 set_reg (sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_GR,
00717 sr->region_start + sr->region_len - 1, gr++);
00718 grmask >>= 1;
00719 }
00720 }
00721
00722 static inline void
00723 desc_gr_mem (unsigned char grmask, struct unw_state_record *sr)
00724 {
00725 int i;
00726
00727 for (i = 0; i < 4; ++i)
00728 {
00729 if ((grmask & 1) != 0)
00730 {
00731 set_reg (sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_SPILL_HOME,
00732 sr->region_start + sr->region_len - 1, 0);
00733 sr->any_spills = 1;
00734 }
00735 grmask >>= 1;
00736 }
00737 }
00738
00739 static inline void
00740 desc_mem_stack_f (unw_word t, unw_word size, struct unw_state_record *sr)
00741 {
00742 set_reg (sr->curr.reg + UNW_REG_PSP, UNW_WHERE_NONE,
00743 sr->region_start + MIN ((int)t, sr->region_len - 1), 16*size);
00744 }
00745
00746 static inline void
00747 desc_mem_stack_v (unw_word t, struct unw_state_record *sr)
00748 {
00749 sr->curr.reg[UNW_REG_PSP].when
00750 = sr->region_start + MIN ((int)t, sr->region_len - 1);
00751 }
00752
00753 static inline void
00754 desc_reg_gr (unsigned char reg, unsigned char dst, struct unw_state_record *sr)
00755 {
00756 set_reg (sr->curr.reg + reg, UNW_WHERE_GR,
00757 sr->region_start + sr->region_len - 1, dst);
00758 }
00759
00760 static inline void
00761 desc_reg_psprel (unsigned char reg, unw_word pspoff,
00762 struct unw_state_record *sr)
00763 {
00764 set_reg (sr->curr.reg + reg, UNW_WHERE_PSPREL,
00765 sr->region_start + sr->region_len - 1,
00766 0x10 - 4*pspoff);
00767 }
00768
00769 static inline void
00770 desc_reg_sprel (unsigned char reg, unw_word spoff, struct unw_state_record *sr)
00771 {
00772 set_reg (sr->curr.reg + reg, UNW_WHERE_SPREL,
00773 sr->region_start + sr->region_len - 1,
00774 4*spoff);
00775 }
00776
00777 static inline void
00778 desc_rp_br (unsigned char dst, struct unw_state_record *sr)
00779 {
00780 sr->return_link_reg = dst;
00781 }
00782
00783 static inline void
00784 desc_reg_when (unsigned char regnum, unw_word t, struct unw_state_record *sr)
00785 {
00786 struct unw_reg_info *reg = sr->curr.reg + regnum;
00787
00788 if (reg->where == UNW_WHERE_NONE)
00789 reg->where = UNW_WHERE_GR_SAVE;
00790 reg->when = sr->region_start + MIN ((int)t, sr->region_len - 1);
00791 }
00792
00793 static inline void
00794 desc_spill_base (unw_word pspoff, struct unw_state_record *sr)
00795 {
00796 sr->spill_offset = 0x10 - 4*pspoff;
00797 }
00798
00799 static inline unsigned char *
00800 desc_spill_mask (unsigned char *imaskp, struct unw_state_record *sr)
00801 {
00802 sr->imask = imaskp;
00803 return imaskp + (2*sr->region_len + 7)/8;
00804 }
00805
00806
00807
00808
00809 static inline void
00810 desc_epilogue (unw_word t, unw_word ecount, struct unw_state_record *sr)
00811 {
00812 sr->epilogue_start = sr->region_start + sr->region_len - 1 - t;
00813 sr->epilogue_count = ecount + 1;
00814 }
00815
00816 static inline void
00817 desc_copy_state (unw_word label, struct unw_state_record *sr)
00818 {
00819 struct unw_labeled_state *ls;
00820
00821 for (ls = sr->labeled_states; ls; ls = ls->next)
00822 {
00823 if (ls->label == label)
00824 {
00825 free_state_stack (&sr->curr);
00826 memcpy (&sr->curr, &ls->saved_state, sizeof (sr->curr));
00827 sr->curr.next = dup_state_stack (ls->saved_state.next);
00828 return;
00829 }
00830 }
00831 abort ();
00832 }
00833
00834 static inline void
00835 desc_label_state (unw_word label, struct unw_state_record *sr)
00836 {
00837 struct unw_labeled_state *ls = alloc_label_state ();
00838
00839 ls->label = label;
00840 memcpy (&ls->saved_state, &sr->curr, sizeof (ls->saved_state));
00841 ls->saved_state.next = dup_state_stack (sr->curr.next);
00842
00843
00844 ls->next = sr->labeled_states;
00845 sr->labeled_states = ls;
00846 }
00847
00848
00849
00850
00851
00852 static inline int
00853 desc_is_active (unsigned char qp, unw_word t, struct unw_state_record *sr)
00854 {
00855 if (sr->when_target <= sr->region_start + MIN ((int)t, sr->region_len - 1))
00856 return 0;
00857 if (qp > 0)
00858 {
00859 if ((sr->pr_val & (1UL << qp)) == 0)
00860 return 0;
00861 sr->pr_mask |= (1UL << qp);
00862 }
00863 return 1;
00864 }
00865
00866 static inline void
00867 desc_restore_p (unsigned char qp, unw_word t, unsigned char abreg,
00868 struct unw_state_record *sr)
00869 {
00870 struct unw_reg_info *r;
00871
00872 if (! desc_is_active (qp, t, sr))
00873 return;
00874
00875 r = sr->curr.reg + decode_abreg (abreg, 0);
00876 r->where = UNW_WHERE_NONE;
00877 r->when = sr->region_start + MIN ((int)t, sr->region_len - 1);
00878 r->val = 0;
00879 }
00880
00881 static inline void
00882 desc_spill_reg_p (unsigned char qp, unw_word t, unsigned char abreg,
00883 unsigned char x, unsigned char ytreg,
00884 struct unw_state_record *sr)
00885 {
00886 enum unw_where where = UNW_WHERE_GR;
00887 struct unw_reg_info *r;
00888
00889 if (! desc_is_active (qp, t, sr))
00890 return;
00891
00892 if (x)
00893 where = UNW_WHERE_BR;
00894 else if (ytreg & 0x80)
00895 where = UNW_WHERE_FR;
00896
00897 r = sr->curr.reg + decode_abreg (abreg, 0);
00898 r->where = where;
00899 r->when = sr->region_start + MIN ((int)t, sr->region_len - 1);
00900 r->val = ytreg & 0x7f;
00901 }
00902
00903 static inline void
00904 desc_spill_psprel_p (unsigned char qp, unw_word t, unsigned char abreg,
00905 unw_word pspoff, struct unw_state_record *sr)
00906 {
00907 struct unw_reg_info *r;
00908
00909 if (! desc_is_active (qp, t, sr))
00910 return;
00911
00912 r = sr->curr.reg + decode_abreg (abreg, 1);
00913 r->where = UNW_WHERE_PSPREL;
00914 r->when = sr->region_start + MIN((int)t, sr->region_len - 1);
00915 r->val = 0x10 - 4*pspoff;
00916 }
00917
00918 static inline void
00919 desc_spill_sprel_p (unsigned char qp, unw_word t, unsigned char abreg,
00920 unw_word spoff, struct unw_state_record *sr)
00921 {
00922 struct unw_reg_info *r;
00923
00924 if (! desc_is_active (qp, t, sr))
00925 return;
00926
00927 r = sr->curr.reg + decode_abreg (abreg, 1);
00928 r->where = UNW_WHERE_SPREL;
00929 r->when = sr->region_start + MIN ((int)t, sr->region_len - 1);
00930 r->val = 4*spoff;
00931 }
00932
00933
00934 #define UNW_DEC_BAD_CODE(code) abort ();
00935
00936
00937 #define UNW_DEC_PROLOGUE_GR(fmt,r,m,gr,arg) desc_prologue(0,r,m,gr,arg)
00938 #define UNW_DEC_PROLOGUE(fmt,b,r,arg) desc_prologue(b,r,0,32,arg)
00939
00940
00941 #define UNW_DEC_ABI(fmt,a,c,arg) desc_abi(a,c,arg)
00942 #define UNW_DEC_BR_GR(fmt,b,g,arg) desc_br_gr(b,g,arg)
00943 #define UNW_DEC_BR_MEM(fmt,b,arg) desc_br_mem(b,arg)
00944 #define UNW_DEC_FRGR_MEM(fmt,g,f,arg) desc_frgr_mem(g,f,arg)
00945 #define UNW_DEC_FR_MEM(fmt,f,arg) desc_fr_mem(f,arg)
00946 #define UNW_DEC_GR_GR(fmt,m,g,arg) desc_gr_gr(m,g,arg)
00947 #define UNW_DEC_GR_MEM(fmt,m,arg) desc_gr_mem(m,arg)
00948 #define UNW_DEC_MEM_STACK_F(fmt,t,s,arg) desc_mem_stack_f(t,s,arg)
00949 #define UNW_DEC_MEM_STACK_V(fmt,t,arg) desc_mem_stack_v(t,arg)
00950 #define UNW_DEC_REG_GR(fmt,r,d,arg) desc_reg_gr(r,d,arg)
00951 #define UNW_DEC_REG_PSPREL(fmt,r,o,arg) desc_reg_psprel(r,o,arg)
00952 #define UNW_DEC_REG_SPREL(fmt,r,o,arg) desc_reg_sprel(r,o,arg)
00953 #define UNW_DEC_REG_WHEN(fmt,r,t,arg) desc_reg_when(r,t,arg)
00954 #define UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg) desc_reg_when(UNW_REG_PRI_UNAT_GR,t,arg)
00955 #define UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg) desc_reg_when(UNW_REG_PRI_UNAT_MEM,t,arg)
00956 #define UNW_DEC_PRIUNAT_GR(fmt,r,arg) desc_reg_gr(UNW_REG_PRI_UNAT_GR,r,arg)
00957 #define UNW_DEC_PRIUNAT_PSPREL(fmt,o,arg) desc_reg_psprel(UNW_REG_PRI_UNAT_MEM,o,arg)
00958 #define UNW_DEC_PRIUNAT_SPREL(fmt,o,arg) desc_reg_sprel(UNW_REG_PRI_UNAT_MEM,o,arg)
00959 #define UNW_DEC_RP_BR(fmt,d,arg) desc_rp_br(d,arg)
00960 #define UNW_DEC_SPILL_BASE(fmt,o,arg) desc_spill_base(o,arg)
00961 #define UNW_DEC_SPILL_MASK(fmt,m,arg) (m = desc_spill_mask(m,arg))
00962
00963
00964 #define UNW_DEC_EPILOGUE(fmt,t,c,arg) desc_epilogue(t,c,arg)
00965 #define UNW_DEC_COPY_STATE(fmt,l,arg) desc_copy_state(l,arg)
00966 #define UNW_DEC_LABEL_STATE(fmt,l,arg) desc_label_state(l,arg)
00967
00968
00969 #define UNW_DEC_SPILL_REG_P(f,p,t,a,x,y,arg) desc_spill_reg_p(p,t,a,x,y,arg)
00970 #define UNW_DEC_SPILL_REG(f,t,a,x,y,arg) desc_spill_reg_p(0,t,a,x,y,arg)
00971 #define UNW_DEC_SPILL_PSPREL_P(f,p,t,a,o,arg) desc_spill_psprel_p(p,t,a,o,arg)
00972 #define UNW_DEC_SPILL_PSPREL(f,t,a,o,arg) desc_spill_psprel_p(0,t,a,o,arg)
00973 #define UNW_DEC_SPILL_SPREL_P(f,p,t,a,o,arg) desc_spill_sprel_p(p,t,a,o,arg)
00974 #define UNW_DEC_SPILL_SPREL(f,t,a,o,arg) desc_spill_sprel_p(0,t,a,o,arg)
00975 #define UNW_DEC_RESTORE_P(f,p,t,a,arg) desc_restore_p(p,t,a,arg)
00976 #define UNW_DEC_RESTORE(f,t,a,arg) desc_restore_p(0,t,a,arg)
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040 static unw_word
01041 unw_decode_uleb128 (unsigned char **dpp)
01042 {
01043 unsigned shift = 0;
01044 unw_word byte, result = 0;
01045 unsigned char *bp = *dpp;
01046
01047 while (1)
01048 {
01049 byte = *bp++;
01050 result |= (byte & 0x7f) << shift;
01051 if ((byte & 0x80) == 0)
01052 break;
01053 shift += 7;
01054 }
01055 *dpp = bp;
01056 return result;
01057 }
01058
01059 static unsigned char *
01060 unw_decode_x1 (unsigned char *dp,
01061 unsigned char code __attribute__((unused)),
01062 void *arg)
01063 {
01064 unsigned char byte1, abreg;
01065 unw_word t, off;
01066
01067 byte1 = *dp++;
01068 t = unw_decode_uleb128 (&dp);
01069 off = unw_decode_uleb128 (&dp);
01070 abreg = (byte1 & 0x7f);
01071 if (byte1 & 0x80)
01072 UNW_DEC_SPILL_SPREL(X1, t, abreg, off, arg);
01073 else
01074 UNW_DEC_SPILL_PSPREL(X1, t, abreg, off, arg);
01075 return dp;
01076 }
01077
01078 static unsigned char *
01079 unw_decode_x2 (unsigned char *dp,
01080 unsigned char code __attribute__((unused)),
01081 void *arg)
01082 {
01083 unsigned char byte1, byte2, abreg, x, ytreg;
01084 unw_word t;
01085
01086 byte1 = *dp++; byte2 = *dp++;
01087 t = unw_decode_uleb128 (&dp);
01088 abreg = (byte1 & 0x7f);
01089 ytreg = byte2;
01090 x = (byte1 >> 7) & 1;
01091 if ((byte1 & 0x80) == 0 && ytreg == 0)
01092 UNW_DEC_RESTORE(X2, t, abreg, arg);
01093 else
01094 UNW_DEC_SPILL_REG(X2, t, abreg, x, ytreg, arg);
01095 return dp;
01096 }
01097
01098 static unsigned char *
01099 unw_decode_x3 (unsigned char *dp,
01100 unsigned char code __attribute__((unused)),
01101 void *arg)
01102 {
01103 unsigned char byte1, byte2, abreg, qp;
01104 unw_word t, off;
01105
01106 byte1 = *dp++; byte2 = *dp++;
01107 t = unw_decode_uleb128 (&dp);
01108 off = unw_decode_uleb128 (&dp);
01109
01110 qp = (byte1 & 0x3f);
01111 abreg = (byte2 & 0x7f);
01112
01113 if (byte1 & 0x80)
01114 UNW_DEC_SPILL_SPREL_P(X3, qp, t, abreg, off, arg);
01115 else
01116 UNW_DEC_SPILL_PSPREL_P(X3, qp, t, abreg, off, arg);
01117 return dp;
01118 }
01119
01120 static unsigned char *
01121 unw_decode_x4 (unsigned char *dp,
01122 unsigned char code __attribute__((unused)),
01123 void *arg)
01124 {
01125 unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg;
01126 unw_word t;
01127
01128 byte1 = *dp++; byte2 = *dp++; byte3 = *dp++;
01129 t = unw_decode_uleb128 (&dp);
01130
01131 qp = (byte1 & 0x3f);
01132 abreg = (byte2 & 0x7f);
01133 x = (byte2 >> 7) & 1;
01134 ytreg = byte3;
01135
01136 if ((byte2 & 0x80) == 0 && byte3 == 0)
01137 UNW_DEC_RESTORE_P(X4, qp, t, abreg, arg);
01138 else
01139 UNW_DEC_SPILL_REG_P(X4, qp, t, abreg, x, ytreg, arg);
01140 return dp;
01141 }
01142
01143 static unsigned char *
01144 unw_decode_r1 (unsigned char *dp, unsigned char code, void *arg)
01145 {
01146 int body = (code & 0x20) != 0;
01147 unw_word rlen;
01148
01149 rlen = (code & 0x1f);
01150 UNW_DEC_PROLOGUE(R1, body, rlen, arg);
01151 return dp;
01152 }
01153
01154 static unsigned char *
01155 unw_decode_r2 (unsigned char *dp, unsigned char code, void *arg)
01156 {
01157 unsigned char byte1, mask, grsave;
01158 unw_word rlen;
01159
01160 byte1 = *dp++;
01161
01162 mask = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
01163 grsave = (byte1 & 0x7f);
01164 rlen = unw_decode_uleb128 (&dp);
01165 UNW_DEC_PROLOGUE_GR(R2, rlen, mask, grsave, arg);
01166 return dp;
01167 }
01168
01169 static unsigned char *
01170 unw_decode_r3 (unsigned char *dp, unsigned char code, void *arg)
01171 {
01172 unw_word rlen;
01173
01174 rlen = unw_decode_uleb128 (&dp);
01175 UNW_DEC_PROLOGUE(R3, ((code & 0x3) == 1), rlen, arg);
01176 return dp;
01177 }
01178
01179 static unsigned char *
01180 unw_decode_p1 (unsigned char *dp, unsigned char code, void *arg)
01181 {
01182 unsigned char brmask = (code & 0x1f);
01183
01184 UNW_DEC_BR_MEM(P1, brmask, arg);
01185 return dp;
01186 }
01187
01188 static unsigned char *
01189 unw_decode_p2_p5 (unsigned char *dp, unsigned char code, void *arg)
01190 {
01191 if ((code & 0x10) == 0)
01192 {
01193 unsigned char byte1 = *dp++;
01194
01195 UNW_DEC_BR_GR(P2, ((code & 0xf) << 1) | ((byte1 >> 7) & 1),
01196 (byte1 & 0x7f), arg);
01197 }
01198 else if ((code & 0x08) == 0)
01199 {
01200 unsigned char byte1 = *dp++, r, dst;
01201
01202 r = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
01203 dst = (byte1 & 0x7f);
01204 switch (r)
01205 {
01206 case 0: UNW_DEC_REG_GR(P3, UNW_REG_PSP, dst, arg); break;
01207 case 1: UNW_DEC_REG_GR(P3, UNW_REG_RP, dst, arg); break;
01208 case 2: UNW_DEC_REG_GR(P3, UNW_REG_PFS, dst, arg); break;
01209 case 3: UNW_DEC_REG_GR(P3, UNW_REG_PR, dst, arg); break;
01210 case 4: UNW_DEC_REG_GR(P3, UNW_REG_UNAT, dst, arg); break;
01211 case 5: UNW_DEC_REG_GR(P3, UNW_REG_LC, dst, arg); break;
01212 case 6: UNW_DEC_RP_BR(P3, dst, arg); break;
01213 case 7: UNW_DEC_REG_GR(P3, UNW_REG_RNAT, dst, arg); break;
01214 case 8: UNW_DEC_REG_GR(P3, UNW_REG_BSP, dst, arg); break;
01215 case 9: UNW_DEC_REG_GR(P3, UNW_REG_BSPSTORE, dst, arg); break;
01216 case 10: UNW_DEC_REG_GR(P3, UNW_REG_FPSR, dst, arg); break;
01217 case 11: UNW_DEC_PRIUNAT_GR(P3, dst, arg); break;
01218 default: UNW_DEC_BAD_CODE(r); break;
01219 }
01220 }
01221 else if ((code & 0x7) == 0)
01222 UNW_DEC_SPILL_MASK(P4, dp, arg);
01223 else if ((code & 0x7) == 1)
01224 {
01225 unw_word grmask, frmask, byte1, byte2, byte3;
01226
01227 byte1 = *dp++; byte2 = *dp++; byte3 = *dp++;
01228 grmask = ((byte1 >> 4) & 0xf);
01229 frmask = ((byte1 & 0xf) << 16) | (byte2 << 8) | byte3;
01230 UNW_DEC_FRGR_MEM(P5, grmask, frmask, arg);
01231 }
01232 else
01233 UNW_DEC_BAD_CODE(code);
01234 return dp;
01235 }
01236
01237 static unsigned char *
01238 unw_decode_p6 (unsigned char *dp, unsigned char code, void *arg)
01239 {
01240 int gregs = (code & 0x10) != 0;
01241 unsigned char mask = (code & 0x0f);
01242
01243 if (gregs)
01244 UNW_DEC_GR_MEM(P6, mask, arg);
01245 else
01246 UNW_DEC_FR_MEM(P6, mask, arg);
01247 return dp;
01248 }
01249
01250 static unsigned char *
01251 unw_decode_p7_p10 (unsigned char *dp, unsigned char code, void *arg)
01252 {
01253 unsigned char r, byte1, byte2;
01254 unw_word t, size;
01255
01256 if ((code & 0x10) == 0)
01257 {
01258 r = (code & 0xf);
01259 t = unw_decode_uleb128 (&dp);
01260 switch (r)
01261 {
01262 case 0:
01263 size = unw_decode_uleb128 (&dp);
01264 UNW_DEC_MEM_STACK_F(P7, t, size, arg);
01265 break;
01266
01267 case 1: UNW_DEC_MEM_STACK_V(P7, t, arg); break;
01268 case 2: UNW_DEC_SPILL_BASE(P7, t, arg); break;
01269 case 3: UNW_DEC_REG_SPREL(P7, UNW_REG_PSP, t, arg); break;
01270 case 4: UNW_DEC_REG_WHEN(P7, UNW_REG_RP, t, arg); break;
01271 case 5: UNW_DEC_REG_PSPREL(P7, UNW_REG_RP, t, arg); break;
01272 case 6: UNW_DEC_REG_WHEN(P7, UNW_REG_PFS, t, arg); break;
01273 case 7: UNW_DEC_REG_PSPREL(P7, UNW_REG_PFS, t, arg); break;
01274 case 8: UNW_DEC_REG_WHEN(P7, UNW_REG_PR, t, arg); break;
01275 case 9: UNW_DEC_REG_PSPREL(P7, UNW_REG_PR, t, arg); break;
01276 case 10: UNW_DEC_REG_WHEN(P7, UNW_REG_LC, t, arg); break;
01277 case 11: UNW_DEC_REG_PSPREL(P7, UNW_REG_LC, t, arg); break;
01278 case 12: UNW_DEC_REG_WHEN(P7, UNW_REG_UNAT, t, arg); break;
01279 case 13: UNW_DEC_REG_PSPREL(P7, UNW_REG_UNAT, t, arg); break;
01280 case 14: UNW_DEC_REG_WHEN(P7, UNW_REG_FPSR, t, arg); break;
01281 case 15: UNW_DEC_REG_PSPREL(P7, UNW_REG_FPSR, t, arg); break;
01282 default: UNW_DEC_BAD_CODE(r); break;
01283 }
01284 }
01285 else
01286 {
01287 switch (code & 0xf)
01288 {
01289 case 0x0:
01290 {
01291 r = *dp++;
01292 t = unw_decode_uleb128 (&dp);
01293 switch (r)
01294 {
01295 case 1: UNW_DEC_REG_SPREL(P8, UNW_REG_RP, t, arg); break;
01296 case 2: UNW_DEC_REG_SPREL(P8, UNW_REG_PFS, t, arg); break;
01297 case 3: UNW_DEC_REG_SPREL(P8, UNW_REG_PR, t, arg); break;
01298 case 4: UNW_DEC_REG_SPREL(P8, UNW_REG_LC, t, arg); break;
01299 case 5: UNW_DEC_REG_SPREL(P8, UNW_REG_UNAT, t, arg); break;
01300 case 6: UNW_DEC_REG_SPREL(P8, UNW_REG_FPSR, t, arg); break;
01301 case 7: UNW_DEC_REG_WHEN(P8, UNW_REG_BSP, t, arg); break;
01302 case 8: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSP, t, arg); break;
01303 case 9: UNW_DEC_REG_SPREL(P8, UNW_REG_BSP, t, arg); break;
01304 case 10: UNW_DEC_REG_WHEN(P8, UNW_REG_BSPSTORE, t, arg); break;
01305 case 11: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSPSTORE, t, arg); break;
01306 case 12: UNW_DEC_REG_SPREL(P8, UNW_REG_BSPSTORE, t, arg); break;
01307 case 13: UNW_DEC_REG_WHEN(P8, UNW_REG_RNAT, t, arg); break;
01308 case 14: UNW_DEC_REG_PSPREL(P8, UNW_REG_RNAT, t, arg); break;
01309 case 15: UNW_DEC_REG_SPREL(P8, UNW_REG_RNAT, t, arg); break;
01310 case 16: UNW_DEC_PRIUNAT_WHEN_GR(P8, t, arg); break;
01311 case 17: UNW_DEC_PRIUNAT_PSPREL(P8, t, arg); break;
01312 case 18: UNW_DEC_PRIUNAT_SPREL(P8, t, arg); break;
01313 case 19: UNW_DEC_PRIUNAT_WHEN_MEM(P8, t, arg); break;
01314 default: UNW_DEC_BAD_CODE(r); break;
01315 }
01316 }
01317 break;
01318
01319 case 0x1:
01320 byte1 = *dp++; byte2 = *dp++;
01321 UNW_DEC_GR_GR(P9, (byte1 & 0xf), (byte2 & 0x7f), arg);
01322 break;
01323
01324 case 0xf:
01325 byte1 = *dp++; byte2 = *dp++;
01326 UNW_DEC_ABI(P10, byte1, byte2, arg);
01327 break;
01328
01329 case 0x9:
01330 return unw_decode_x1 (dp, code, arg);
01331
01332 case 0xa:
01333 return unw_decode_x2 (dp, code, arg);
01334
01335 case 0xb:
01336 return unw_decode_x3 (dp, code, arg);
01337
01338 case 0xc:
01339 return unw_decode_x4 (dp, code, arg);
01340
01341 default:
01342 UNW_DEC_BAD_CODE(code);
01343 break;
01344 }
01345 }
01346 return dp;
01347 }
01348
01349 static unsigned char *
01350 unw_decode_b1 (unsigned char *dp, unsigned char code, void *arg)
01351 {
01352 unw_word label = (code & 0x1f);
01353
01354 if ((code & 0x20) != 0)
01355 UNW_DEC_COPY_STATE(B1, label, arg);
01356 else
01357 UNW_DEC_LABEL_STATE(B1, label, arg);
01358 return dp;
01359 }
01360
01361 static unsigned char *
01362 unw_decode_b2 (unsigned char *dp, unsigned char code, void *arg)
01363 {
01364 unw_word t;
01365
01366 t = unw_decode_uleb128 (&dp);
01367 UNW_DEC_EPILOGUE(B2, t, (code & 0x1f), arg);
01368 return dp;
01369 }
01370
01371 static unsigned char *
01372 unw_decode_b3_x4 (unsigned char *dp, unsigned char code, void *arg)
01373 {
01374 unw_word t, ecount, label;
01375
01376 if ((code & 0x10) == 0)
01377 {
01378 t = unw_decode_uleb128 (&dp);
01379 ecount = unw_decode_uleb128 (&dp);
01380 UNW_DEC_EPILOGUE(B3, t, ecount, arg);
01381 }
01382 else if ((code & 0x07) == 0)
01383 {
01384 label = unw_decode_uleb128 (&dp);
01385 if ((code & 0x08) != 0)
01386 UNW_DEC_COPY_STATE(B4, label, arg);
01387 else
01388 UNW_DEC_LABEL_STATE(B4, label, arg);
01389 }
01390 else
01391 switch (code & 0x7)
01392 {
01393 case 1: return unw_decode_x1 (dp, code, arg);
01394 case 2: return unw_decode_x2 (dp, code, arg);
01395 case 3: return unw_decode_x3 (dp, code, arg);
01396 case 4: return unw_decode_x4 (dp, code, arg);
01397 default: UNW_DEC_BAD_CODE(code); break;
01398 }
01399 return dp;
01400 }
01401
01402 typedef unsigned char *(*unw_decoder) (unsigned char *, unsigned char, void *);
01403
01404 static const unw_decoder unw_decode_table[2][8] =
01405 {
01406
01407 {
01408 unw_decode_r1,
01409 unw_decode_r1,
01410 unw_decode_r2,
01411 unw_decode_r3,
01412 unw_decode_p1,
01413 unw_decode_p2_p5,
01414 unw_decode_p6,
01415 unw_decode_p7_p10
01416 },
01417 {
01418 unw_decode_r1,
01419 unw_decode_r1,
01420 unw_decode_r2,
01421 unw_decode_r3,
01422 unw_decode_b1,
01423 unw_decode_b1,
01424 unw_decode_b2,
01425 unw_decode_b3_x4
01426 }
01427 };
01428
01429
01430
01431
01432 static inline unsigned char *
01433 unw_decode (unsigned char *dp, int inside_body, void *arg)
01434 {
01435 unw_decoder decoder;
01436 unsigned char code;
01437
01438 code = *dp++;
01439 decoder = unw_decode_table[inside_body][code >> 5];
01440 dp = (*decoder) (dp, code, arg);
01441 return dp;
01442 }
01443
01444
01445
01446
01447 static inline unsigned long
01448 ia64_rse_slot_num (unsigned long *addr)
01449 {
01450 return (((unsigned long) addr) >> 3) & 0x3f;
01451 }
01452
01453
01454 static inline unsigned long
01455 ia64_rse_is_rnat_slot (unsigned long *addr)
01456 {
01457 return ia64_rse_slot_num (addr) == 0x3f;
01458 }
01459
01460
01461
01462 static inline unsigned long *
01463 ia64_rse_rnat_addr (unsigned long *slot_addr)
01464 {
01465 return (unsigned long *) ((unsigned long) slot_addr | (0x3f << 3));
01466 }
01467
01468
01469
01470
01471 static inline unsigned long
01472 ia64_rse_num_regs (unsigned long *bspstore, unsigned long *bsp)
01473 {
01474 unsigned long slots = (bsp - bspstore);
01475
01476 return slots - (ia64_rse_slot_num (bspstore) + slots)/0x40;
01477 }
01478
01479
01480
01481 static inline unsigned long *
01482 ia64_rse_skip_regs (unsigned long *addr, long num_regs)
01483 {
01484 long delta = ia64_rse_slot_num (addr) + num_regs;
01485
01486 if (num_regs < 0)
01487 delta -= 0x3e;
01488 return addr + num_regs + delta/0x3f;
01489 }
01490
01491
01492
01493
01494 static void
01495 unw_access_gr (struct _Unwind_Context *info, int regnum,
01496 unsigned long *val, char *nat, int write)
01497 {
01498 unsigned long *addr, *nat_addr = 0, nat_mask = 0, dummy_nat;
01499 struct unw_ireg *ireg;
01500
01501 if ((unsigned) regnum - 1 >= 127)
01502 abort ();
01503
01504 if (regnum < 1)
01505 {
01506 nat_addr = addr = &dummy_nat;
01507 dummy_nat = 0;
01508 }
01509 else if (regnum < 32)
01510 {
01511
01512 ireg = &info->ireg[regnum - 2];
01513 addr = ireg->loc;
01514 if (addr)
01515 {
01516 nat_addr = addr + ireg->nat.off;
01517 switch (ireg->nat.type)
01518 {
01519 case UNW_NAT_VAL:
01520
01521 if (write)
01522 {
01523 if (*nat)
01524 {
01525
01526 addr[0] = 0;
01527 addr[1] = 0x1fffe;
01528 return;
01529 }
01530 addr[1] = 0x1003e;
01531 }
01532 else if (addr[0] == 0 && addr[1] == 0x1ffe)
01533 {
01534
01535 *val = 0;
01536 *nat = 1;
01537 return;
01538 }
01539
01540
01541 case UNW_NAT_NONE:
01542 dummy_nat = 0;
01543 nat_addr = &dummy_nat;
01544 break;
01545
01546 case UNW_NAT_MEMSTK:
01547 nat_mask = 1UL << ((long) addr & 0x1f8)/8;
01548 break;
01549
01550 case UNW_NAT_REGSTK:
01551 nat_addr = ia64_rse_rnat_addr (addr);
01552 if ((unsigned long) nat_addr >= info->regstk_top)
01553 nat_addr = &info->rnat;
01554 nat_mask = 1UL << ia64_rse_slot_num (addr);
01555 break;
01556 }
01557 }
01558 }
01559 else
01560 {
01561
01562 addr = ia64_rse_skip_regs ((unsigned long *) info->bsp, regnum - 32);
01563 nat_addr = ia64_rse_rnat_addr (addr);
01564 if ((unsigned long) nat_addr >= info->regstk_top)
01565 nat_addr = &info->rnat;
01566 nat_mask = 1UL << ia64_rse_slot_num (addr);
01567 }
01568
01569 if (write)
01570 {
01571 *addr = *val;
01572 if (*nat)
01573 *nat_addr |= nat_mask;
01574 else
01575 *nat_addr &= ~nat_mask;
01576 }
01577 else
01578 {
01579 *val = *addr;
01580 *nat = (*nat_addr & nat_mask) != 0;
01581 }
01582 }
01583
01584
01585
01586 _Unwind_Word
01587 _Unwind_GetGR (struct _Unwind_Context *context, int index)
01588 {
01589 _Unwind_Word ret;
01590 char nat;
01591
01592 if (index == 1)
01593 return context->gp;
01594 else if (index >= 15 && index <= 18)
01595 return context->eh_data[index - 15];
01596 else
01597 unw_access_gr (context, index, &ret, &nat, 0);
01598
01599 return ret;
01600 }
01601
01602
01603
01604 void
01605 _Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
01606 {
01607 char nat = 0;
01608
01609 if (index == 1)
01610 context->gp = val;
01611 else if (index >= 15 && index <= 18)
01612 context->eh_data[index - 15] = val;
01613 else
01614 unw_access_gr (context, index, &val, &nat, 1);
01615 }
01616
01617
01618
01619 inline _Unwind_Ptr
01620 _Unwind_GetIP (struct _Unwind_Context *context)
01621 {
01622 return context->rp;
01623 }
01624
01625
01626
01627 inline void
01628 _Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
01629 {
01630 context->rp = val;
01631 }
01632
01633 void *
01634 _Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
01635 {
01636 return context->lsda;
01637 }
01638
01639 _Unwind_Ptr
01640 _Unwind_GetRegionStart (struct _Unwind_Context *context)
01641 {
01642 return context->region_start;
01643 }
01644
01645 void *
01646 _Unwind_FindEnclosingFunction (void *pc)
01647 {
01648 return NULL;
01649 }
01650
01651
01652 static _Unwind_Reason_Code
01653 uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
01654 {
01655 struct unw_table_entry *ent;
01656 unsigned long *unw, header, length;
01657 unsigned char *insn, *insn_end;
01658 unsigned long segment_base;
01659 struct unw_reg_info *r;
01660
01661 memset (fs, 0, sizeof (*fs));
01662 for (r = fs->curr.reg; r < fs->curr.reg + UNW_NUM_REGS; ++r)
01663 r->when = UNW_WHEN_NEVER;
01664 context->lsda = 0;
01665
01666 ent = _Unwind_FindTableEntry ((void *) context->rp,
01667 &segment_base, &context->gp);
01668 if (ent == NULL)
01669 {
01670
01671
01672
01673 #ifdef MD_FALLBACK_FRAME_STATE_FOR
01674 MD_FALLBACK_FRAME_STATE_FOR (context, fs, success);
01675
01676
01677
01678
01679
01680
01681
01682 if (context->br_loc[0] && *context->br_loc[0] != context->rp)
01683 {
01684 fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_BR;
01685 fs->curr.reg[UNW_REG_RP].when = -1;
01686 fs->curr.reg[UNW_REG_RP].val = 0;
01687 goto success;
01688 }
01689
01690 return _URC_END_OF_STACK;
01691 success:
01692 return _URC_NO_REASON;
01693 #else
01694 return _URC_END_OF_STACK;
01695 #endif
01696 }
01697
01698 context->region_start = ent->start_offset + segment_base;
01699 fs->when_target = (context->rp - context->region_start) / 16 * 3;
01700
01701 unw = (unsigned long *) (ent->info_offset + segment_base);
01702 header = *unw;
01703 length = UNW_LENGTH (header);
01704
01705
01706
01707 if (UNW_FLAG_EHANDLER (header) | UNW_FLAG_UHANDLER (header))
01708 {
01709 fs->personality =
01710 *(_Unwind_Personality_Fn *) (unw[length + 1] + context->gp);
01711 context->lsda = unw + length + 2;
01712 }
01713
01714 insn = (unsigned char *) (unw + 1);
01715 insn_end = (unsigned char *) (unw + 1 + length);
01716 while (!fs->done && insn < insn_end)
01717 insn = unw_decode (insn, fs->in_body, fs);
01718
01719 free_label_states (fs->labeled_states);
01720 free_state_stack (&fs->curr);
01721
01722 #ifdef ENABLE_MALLOC_CHECKING
01723 if (reg_state_alloced || labeled_state_alloced)
01724 abort ();
01725 #endif
01726
01727
01728
01729 if (fs->when_target > fs->epilogue_start)
01730 {
01731 struct unw_reg_info *r;
01732
01733 fs->curr.reg[UNW_REG_PSP].where = UNW_WHERE_NONE;
01734 fs->curr.reg[UNW_REG_PSP].val = 0;
01735 for (r = fs->curr.reg; r < fs->curr.reg + UNW_NUM_REGS; ++r)
01736 if ((r->where == UNW_WHERE_PSPREL && r->val <= 0x10)
01737 || r->where == UNW_WHERE_SPREL)
01738 r->where = UNW_WHERE_NONE;
01739 }
01740
01741
01742 if (fs->curr.reg[UNW_REG_RP].when >= fs->when_target)
01743 {
01744 fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_BR;
01745 fs->curr.reg[UNW_REG_RP].when = -1;
01746 fs->curr.reg[UNW_REG_RP].val = fs->return_link_reg;
01747 }
01748
01749 return _URC_NO_REASON;
01750 }
01751
01752 static void
01753 uw_update_reg_address (struct _Unwind_Context *context,
01754 _Unwind_FrameState *fs,
01755 enum unw_register_index regno)
01756 {
01757 struct unw_reg_info *r = fs->curr.reg + regno;
01758 void *addr;
01759 unsigned long rval;
01760
01761 if (r->where == UNW_WHERE_NONE || r->when >= fs->when_target)
01762 return;
01763
01764 rval = r->val;
01765 switch (r->where)
01766 {
01767 case UNW_WHERE_GR:
01768 if (rval >= 32)
01769 addr = ia64_rse_skip_regs ((unsigned long *) context->bsp, rval - 32);
01770 else if (rval >= 2)
01771 addr = context->ireg[rval - 2].loc;
01772 else
01773 abort ();
01774 break;
01775
01776 case UNW_WHERE_FR:
01777 if (rval >= 2 && rval < 32)
01778 addr = context->fr_loc[rval - 2];
01779 else
01780 abort ();
01781 break;
01782
01783 case UNW_WHERE_BR:
01784
01785
01786
01787 if (rval <= 5)
01788 addr = context->br_loc[rval];
01789 else
01790 abort ();
01791 break;
01792
01793 case UNW_WHERE_SPREL:
01794 addr = (void *)(context->sp + rval);
01795 break;
01796
01797 case UNW_WHERE_PSPREL:
01798 addr = (void *)(context->psp + rval);
01799 break;
01800
01801 default:
01802 abort ();
01803 }
01804
01805 switch (regno)
01806 {
01807 case UNW_REG_R2 ... UNW_REG_R31:
01808 context->ireg[regno - UNW_REG_R2].loc = addr;
01809 switch (r->where)
01810 {
01811 case UNW_WHERE_GR:
01812 if (rval >= 32)
01813 {
01814 context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_MEMSTK;
01815 context->ireg[regno - UNW_REG_R2].nat.off
01816 = context->pri_unat_loc - (unsigned long *) addr;
01817 }
01818 else if (rval >= 2)
01819 {
01820 context->ireg[regno - UNW_REG_R2].nat
01821 = context->ireg[rval - 2].nat;
01822 }
01823 else
01824 abort ();
01825 break;
01826
01827 case UNW_WHERE_FR:
01828 context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_VAL;
01829 context->ireg[regno - UNW_REG_R2].nat.off = 0;
01830 break;
01831
01832 case UNW_WHERE_BR:
01833 context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_NONE;
01834 context->ireg[regno - UNW_REG_R2].nat.off = 0;
01835 break;
01836
01837 case UNW_WHERE_PSPREL:
01838 case UNW_WHERE_SPREL:
01839 context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_MEMSTK;
01840 context->ireg[regno - UNW_REG_R2].nat.off
01841 = context->pri_unat_loc - (unsigned long *) addr;
01842 break;
01843
01844 default:
01845 abort ();
01846 }
01847 break;
01848
01849 case UNW_REG_F2 ... UNW_REG_F31:
01850 context->fr_loc[regno - UNW_REG_F2] = addr;
01851 break;
01852
01853 case UNW_REG_B1 ... UNW_REG_B5:
01854 context->br_loc[regno - UNW_REG_B0] = addr;
01855 break;
01856
01857 case UNW_REG_BSP:
01858 context->bsp_loc = addr;
01859 break;
01860 case UNW_REG_BSPSTORE:
01861 context->bspstore_loc = addr;
01862 break;
01863 case UNW_REG_PFS:
01864 context->pfs_loc = addr;
01865 break;
01866 case UNW_REG_RP:
01867 context->rp = *(unsigned long *)addr;
01868 break;
01869 case UNW_REG_UNAT:
01870 context->unat_loc = addr;
01871 break;
01872 case UNW_REG_PR:
01873 context->pr = *(unsigned long *) addr;
01874 break;
01875 case UNW_REG_LC:
01876 context->lc_loc = addr;
01877 break;
01878 case UNW_REG_FPSR:
01879 context->fpsr_loc = addr;
01880 break;
01881
01882 case UNW_REG_PSP:
01883 context->psp = *(unsigned long *)addr;
01884 break;
01885
01886 default:
01887 abort ();
01888 }
01889 }
01890
01891 static void
01892 uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
01893 {
01894 long i;
01895
01896 context->sp = context->psp;
01897
01898
01899 if (fs->when_target > fs->curr.reg[UNW_REG_PSP].when)
01900 {
01901 if (fs->curr.reg[UNW_REG_PSP].where == UNW_WHERE_NONE)
01902 context->psp = context->psp + fs->curr.reg[UNW_REG_PSP].val;
01903 else
01904 uw_update_reg_address (context, fs, UNW_REG_PSP);
01905 }
01906
01907
01908 {
01909 int i;
01910 if (fs->when_target < fs->curr.reg[UNW_REG_PRI_UNAT_GR].when)
01911 i = UNW_REG_PRI_UNAT_MEM;
01912 else if (fs->when_target < fs->curr.reg[UNW_REG_PRI_UNAT_MEM].when)
01913 i = UNW_REG_PRI_UNAT_GR;
01914 else if (fs->curr.reg[UNW_REG_PRI_UNAT_MEM].when
01915 > fs->curr.reg[UNW_REG_PRI_UNAT_GR].when)
01916 i = UNW_REG_PRI_UNAT_MEM;
01917 else
01918 i = UNW_REG_PRI_UNAT_GR;
01919 uw_update_reg_address (context, fs, i);
01920 }
01921
01922
01923 for (i = UNW_REG_BSP; i < UNW_NUM_REGS; ++i)
01924 uw_update_reg_address (context, fs, i);
01925
01926
01927
01928
01929
01930
01931 if (!(fs -> no_reg_stack_frame))
01932 {
01933 unsigned long pfs = *context->pfs_loc;
01934 unsigned long sol = (pfs >> 7) & 0x7f;
01935 context->bsp = (unsigned long)
01936 ia64_rse_skip_regs ((unsigned long *) context->bsp, -sol);
01937 }
01938 }
01939
01940
01941
01942
01943 #define uw_init_context(CONTEXT) \
01944 do { \
01945
01946
01947 \
01948 __builtin_unwind_init(); \
01949 uw_init_context_1 (CONTEXT, __builtin_ia64_bsp ()); \
01950 } while (0)
01951
01952 static void
01953 uw_init_context_1 (struct _Unwind_Context *context, void *bsp)
01954 {
01955 void *rp = __builtin_extract_return_addr (__builtin_return_address (0));
01956
01957 void *psp = __builtin_dwarf_cfa () - 16;
01958 _Unwind_FrameState fs;
01959
01960
01961 __builtin_ia64_flushrs ();
01962
01963 memset (context, 0, sizeof (struct _Unwind_Context));
01964 context->bsp = context->regstk_top = (unsigned long) bsp;
01965 context->psp = (unsigned long) psp;
01966 context->rp = (unsigned long) rp;
01967 asm ("mov %0 = sp" : "=r" (context->sp));
01968 asm ("mov %0 = pr" : "=r" (context->pr));
01969 context->pri_unat_loc = &context->initial_unat;
01970
01971
01972 if (uw_frame_state_for (context, &fs) != _URC_NO_REASON)
01973 abort ();
01974
01975 uw_update_context (context, &fs);
01976 }
01977
01978
01979
01980 static void __attribute__((noreturn))
01981 uw_install_context (struct _Unwind_Context *current __attribute__((unused)),
01982 struct _Unwind_Context *target)
01983 {
01984 unsigned long ireg_buf[4], ireg_nat = 0, ireg_pr = 0;
01985 long i;
01986
01987
01988
01989
01990 for (i = 4; i <= 7; ++i)
01991 {
01992 char nat;
01993 void *t = target->ireg[i - 2].loc;
01994 if (t)
01995 {
01996 unw_access_gr (target, i, &ireg_buf[i - 4], &nat, 0);
01997 ireg_nat |= (long)nat << (((size_t)&ireg_buf[i - 4] >> 3) & 0x3f);
01998
01999 ireg_pr |= 4L << i;
02000 }
02001 }
02002
02003
02004
02005
02006
02007 target->bsp = (unsigned long)
02008 ia64_rse_skip_regs ((unsigned long *)target->bsp,
02009 (*target->pfs_loc >> 7) & 0x7f);
02010
02011
02012 asm volatile ("uc_rnat = %0"
02013 : : "i"(offsetof (struct _Unwind_Context, rnat)));
02014 asm volatile ("uc_bsp = %0"
02015 : : "i"(offsetof (struct _Unwind_Context, bsp)));
02016 asm volatile ("uc_psp = %0"
02017 : : "i"(offsetof (struct _Unwind_Context, psp)));
02018 asm volatile ("uc_rp = %0"
02019 : : "i"(offsetof (struct _Unwind_Context, rp)));
02020 asm volatile ("uc_pr = %0"
02021 : : "i"(offsetof (struct _Unwind_Context, pr)));
02022 asm volatile ("uc_gp = %0"
02023 : : "i"(offsetof (struct _Unwind_Context, gp)));
02024 asm volatile ("uc_pfs_loc = %0"
02025 : : "i"(offsetof (struct _Unwind_Context, pfs_loc)));
02026 asm volatile ("uc_unat_loc = %0"
02027 : : "i"(offsetof (struct _Unwind_Context, unat_loc)));
02028 asm volatile ("uc_lc_loc = %0"
02029 : : "i"(offsetof (struct _Unwind_Context, lc_loc)));
02030 asm volatile ("uc_fpsr_loc = %0"
02031 : : "i"(offsetof (struct _Unwind_Context, fpsr_loc)));
02032 asm volatile ("uc_eh_data = %0"
02033 : : "i"(offsetof (struct _Unwind_Context, eh_data)));
02034 asm volatile ("uc_br_loc = %0"
02035 : : "i"(offsetof (struct _Unwind_Context, br_loc)));
02036 asm volatile ("uc_fr_loc = %0"
02037 : : "i"(offsetof (struct _Unwind_Context, fr_loc)));
02038
02039 asm volatile (
02040
02041 "add r20 = 8, %1 \n\t"
02042 "mov ar.unat = %2 \n\t"
02043 "mov pr = %3, 0x3c0 \n\t"
02044 ";; \n\t"
02045 "(p6) ld8.fill r4 = [%1] \n\t"
02046 "(p7) ld8.fill r5 = [r20] \n\t"
02047 "add r21 = uc_br_loc + 8, %0 \n\t"
02048 "adds %1 = 16, %1 \n\t"
02049 "adds r20 = 16, r20 \n\t"
02050 ";; \n\t"
02051 "(p8) ld8.fill r6 = [%1] \n\t"
02052 "(p9) ld8.fill r7 = [r20] \n\t"
02053 "add r20 = uc_br_loc, %0 \n\t"
02054 ";; \n\t"
02055
02056 "ld8 r22 = [r20], 16 \n\t"
02057 "ld8 r23 = [r21], 16 \n\t"
02058 ";; \n\t"
02059 "ld8 r24 = [r20], 16 \n\t"
02060 "ld8 r25 = [r21], uc_fr_loc - (uc_br_loc + 24)\n\t"
02061 ";; \n\t"
02062 "ld8 r26 = [r20], uc_fr_loc + 8 - (uc_br_loc + 32)\n\t"
02063 "ld8 r27 = [r21], 24 \n\t"
02064 "cmp.ne p6, p0 = r0, r22 \n\t"
02065 ";; \n\t"
02066 "ld8 r28 = [r20], 8 \n\t"
02067 "(p6) ld8 r22 = [r22] \n\t"
02068 "cmp.ne p7, p0 = r0, r23 \n\t"
02069 ";; \n\t"
02070 "(p7) ld8 r23 = [r23] \n\t"
02071 "cmp.ne p8, p0 = r0, r24 \n\t"
02072 ";; \n\t"
02073 "(p8) ld8 r24 = [r24] \n\t"
02074 "(p6) mov b1 = r22 \n\t"
02075 "cmp.ne p9, p0 = r0, r25 \n\t"
02076 ";; \n\t"
02077 "(p9) ld8 r25 = [r25] \n\t"
02078 "(p7) mov b2 = r23 \n\t"
02079 "cmp.ne p6, p0 = r0, r26 \n\t"
02080 ";; \n\t"
02081 "(p6) ld8 r26 = [r26] \n\t"
02082 "(p8) mov b3 = r24 \n\t"
02083 "cmp.ne p7, p0 = r0, r27 \n\t"
02084 ";; \n\t"
02085
02086 "(p7) ldf.fill f2 = [r27] \n\t"
02087 "(p9) mov b4 = r25 \n\t"
02088 "cmp.ne p8, p0 = r0, r28 \n\t"
02089 ";; \n\t"
02090 "(p8) ldf.fill f3 = [r28] \n\t"
02091 "(p6) mov b5 = r26 \n\t"
02092 ";; \n\t"
02093 "ld8 r29 = [r20], 16*8 - 4*8 \n\t"
02094 "ld8 r30 = [r21], 17*8 - 5*8 \n\t"
02095 ";; \n\t"
02096 "ld8 r22 = [r20], 16 \n\t"
02097 "ld8 r23 = [r21], 16 \n\t"
02098 ";; \n\t"
02099 "ld8 r24 = [r20], 16 \n\t"
02100 "ld8 r25 = [r21] \n\t"
02101 "cmp.ne p6, p0 = r0, r29 \n\t"
02102 ";; \n\t"
02103 "ld8 r26 = [r20], 8 \n\t"
02104 "(p6) ldf.fill f4 = [r29] \n\t"
02105 "cmp.ne p7, p0 = r0, r30 \n\t"
02106 ";; \n\t"
02107 "ld8 r27 = [r20], 8 \n\t"
02108 "(p7) ldf.fill f5 = [r30] \n\t"
02109 "cmp.ne p6, p0 = r0, r22 \n\t"
02110 ";; \n\t"
02111 "ld8 r28 = [r20], 8 \n\t"
02112 "(p6) ldf.fill f16 = [r22] \n\t"
02113 "cmp.ne p7, p0 = r0, r23 \n\t"
02114 ";; \n\t"
02115 "ld8 r29 = [r20], 8 \n\t"
02116 "(p7) ldf.fill f17 = [r23] \n\t"
02117 "cmp.ne p6, p0 = r0, r24 \n\t"
02118 ";; \n\t"
02119 "ld8 r22 = [r20], 8 \n\t"
02120 "(p6) ldf.fill f18 = [r24] \n\t"
02121 "cmp.ne p7, p0 = r0, r25 \n\t"
02122 ";; \n\t"
02123 "ld8 r23 = [r20], 8 \n\t"
02124 "(p7) ldf.fill f19 = [r25] \n\t"
02125 "cmp.ne p6, p0 = r0, r26 \n\t"
02126 ";; \n\t"
02127 "ld8 r24 = [r20], 8 \n\t"
02128 "(p6) ldf.fill f20 = [r26] \n\t"
02129 "cmp.ne p7, p0 = r0, r27 \n\t"
02130 ";; \n\t"
02131 "ld8 r25 = [r20], 8 \n\t"
02132 "(p7) ldf.fill f21 = [r27] \n\t"
02133 "cmp.ne p6, p0 = r0, r28 \n\t"
02134 ";; \n\t"
02135 "ld8 r26 = [r20], 8 \n\t"
02136 "(p6) ldf.fill f22 = [r28] \n\t"
02137 "cmp.ne p7, p0 = r0, r29 \n\t"
02138 ";; \n\t"
02139 "ld8 r28 = [r20], 8 \n\t"
02140 "(p7) ldf.fill f23 = [r29] \n\t"
02141 "cmp.ne p6, p0 = r0, r22 \n\t"
02142 ";; \n\t"
02143 "ld8 r29 = [r20], 8 \n\t"
02144 "(p6) ldf.fill f24 = [r22] \n\t"
02145 "cmp.ne p7, p0 = r0, r23 \n\t"
02146 ";; \n\t"
02147 "(p7) ldf.fill f25 = [r23] \n\t"
02148 "cmp.ne p6, p0 = r0, r24 \n\t"
02149 "cmp.ne p7, p0 = r0, r25 \n\t"
02150 ";; \n\t"
02151 "(p6) ldf.fill f26 = [r24] \n\t"
02152 "(p7) ldf.fill f27 = [r25] \n\t"
02153 "cmp.ne p6, p0 = r0, r26 \n\t"
02154 ";; \n\t"
02155 "(p6) ldf.fill f28 = [r26] \n\t"
02156 "cmp.ne p7, p0 = r0, r27 \n\t"
02157 "cmp.ne p6, p0 = r0, r28 \n\t"
02158 ";; \n\t"
02159 "(p7) ldf.fill f29 = [r27] \n\t"
02160 "(p6) ldf.fill f30 = [r28] \n\t"
02161 "cmp.ne p7, p0 = r0, r29 \n\t"
02162 ";; \n\t"
02163 "(p7) ldf.fill f31 = [r29] \n\t"
02164 "add r20 = uc_rnat, %0 \n\t"
02165 "add r21 = uc_bsp, %0 \n\t"
02166 ";; \n\t"
02167
02168 "ld8 r22 = [r20], uc_psp - uc_rnat \n\t"
02169 "ld8 r23 = [r21], uc_gp - uc_bsp \n\t"
02170 ";; \n\t"
02171 "ld8 r24 = [r20], uc_pfs_loc - uc_psp \n\t"
02172 "ld8 r1 = [r21], uc_rp - uc_gp \n\t"
02173 ";; \n\t"
02174 "ld8 r25 = [r20], uc_unat_loc - uc_pfs_loc\n\t"
02175 "ld8 r26 = [r21], uc_pr - uc_rp \n\t"
02176 ";; \n\t"
02177 "ld8 r27 = [r20], uc_lc_loc - uc_unat_loc\n\t"
02178 "ld8 r28 = [r21], uc_fpsr_loc - uc_pr \n\t"
02179 ";; \n\t"
02180 "ld8 r29 = [r20], uc_eh_data - uc_lc_loc\n\t"
02181 "ld8 r30 = [r21], uc_eh_data + 8 - uc_fpsr_loc\n\t"
02182 ";; \n\t"
02183
02184 "ld8 r15 = [r20], 16 \n\t"
02185 "ld8 r16 = [r21], 16 \n\t"
02186 ";; \n\t"
02187 "ld8 r17 = [r20] \n\t"
02188 "ld8 r18 = [r21] \n\t"
02189 ";; \n\t"
02190
02191 "cmp.ne p6, p0 = r0, r25 \n\t"
02192 "cmp.ne p7, p0 = r0, r27 \n\t"
02193 ";; \n\t"
02194 "(p6) ld8 r25 = [r25] \n\t"
02195 "(p7) ld8 r27 = [r27] \n\t"
02196 ";; \n\t"
02197 "(p7) mov.m ar.unat = r27 \n\t"
02198 "(p6) mov.i ar.pfs = r25 \n\t"
02199 "cmp.ne p9, p0 = r0, r29 \n\t"
02200 ";; \n\t"
02201 "(p9) ld8 r29 = [r29] \n\t"
02202 "cmp.ne p6, p0 = r0, r30 \n\t"
02203 ";; \n\t"
02204 "(p6) ld8 r30 = [r30] \n\t"
02205
02206 "mov pr = r28, ~0x3c0 \n\t"
02207 "(p9) mov.i ar.lc = r29 \n\t"
02208 ";; \n\t"
02209 "mov.m r25 = ar.rsc \n\t"
02210 "(p6) mov.i ar.fpsr = r30 \n\t"
02211 ";; \n\t"
02212 "and r25 = 0x1c, r25 \n\t"
02213 "mov b0 = r26 \n\t"
02214 ";; \n\t"
02215 "mov.m ar.rsc = r25 \n\t"
02216 ";; \n\t"
02217
02218
02219
02220
02221 "loadrs \n\t"
02222 "invala \n\t"
02223 ";; \n\t"
02224 "mov.m ar.bspstore = r23 \n\t"
02225 ";; \n\t"
02226 "or r25 = 0x3, r25 \n\t"
02227 "mov.m ar.rnat = r22 \n\t"
02228 ";; \n\t"
02229 "mov.m ar.rsc = r25 \n\t"
02230 "mov sp = r24 \n\t"
02231 "br.ret.sptk.few b0"
02232 : : "r"(target), "r"(ireg_buf), "r"(ireg_nat), "r"(ireg_pr)
02233 : "r15", "r16", "r17", "r18", "r20", "r21", "r22",
02234 "r23", "r24", "r25", "r26", "r27", "r28", "r29",
02235 "r30", "r31");
02236
02237 while (1);
02238 }
02239
02240 static inline _Unwind_Ptr
02241 uw_identify_context (struct _Unwind_Context *context)
02242 {
02243 return _Unwind_GetIP (context);
02244 }
02245
02246 #include "unwind.inc"
02247 #endif