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