📄 unwind-ia64.c
字号:
{ if (reg->where == UNW_WHERE_SPILL_HOME) { reg->where = UNW_WHERE_PSPREL; *offp -= regsize; reg->val = *offp; } }}static inline voidspill_next_when (struct unw_reg_info **regp, struct unw_reg_info *lim, unw_word t){ struct unw_reg_info *reg; for (reg = *regp; reg <= lim; ++reg) { if (reg->where == UNW_WHERE_SPILL_HOME) { reg->when = t; *regp = reg + 1; return; } } /* Excess spill. */ abort ();}static voidfinish_prologue (struct unw_state_record *sr){ struct unw_reg_info *reg; unsigned long off; int i; /* First, resolve implicit register save locations (see Section "11.4.2.3 Rules for Using Unwind Descriptors", rule 3). */ for (i = 0; i < (int) sizeof (save_order); ++i) { reg = sr->curr.reg + save_order[i]; if (reg->where == UNW_WHERE_GR_SAVE) { reg->where = UNW_WHERE_GR; reg->val = sr->gr_save_loc++; } } /* Next, compute when the fp, general, and branch registers get saved. This must come before alloc_spill_area() because we need to know which registers are spilled to their home locations. */ if (sr->imask) { static unsigned char const limit[3] = { UNW_REG_F31, UNW_REG_R7, UNW_REG_B5 }; unsigned char kind, mask = 0, *cp = sr->imask; int t; struct unw_reg_info *(regs[3]); regs[0] = sr->curr.reg + UNW_REG_F2; regs[1] = sr->curr.reg + UNW_REG_R4; regs[2] = sr->curr.reg + UNW_REG_B1; for (t = 0; t < sr->region_len; ++t) { if ((t & 3) == 0) mask = *cp++; kind = (mask >> 2*(3-(t & 3))) & 3; if (kind > 0) spill_next_when (®s[kind - 1], sr->curr.reg + limit[kind - 1], sr->region_start + t); } } /* Next, lay out the memory stack spill area. */ if (sr->any_spills) { off = sr->spill_offset; alloc_spill_area (&off, 16, sr->curr.reg + UNW_REG_F2, sr->curr.reg + UNW_REG_F31); alloc_spill_area (&off, 8, sr->curr.reg + UNW_REG_B1, sr->curr.reg + UNW_REG_B5); alloc_spill_area (&off, 8, sr->curr.reg + UNW_REG_R4, sr->curr.reg + UNW_REG_R7); }}/* * Region header descriptors. */static voiddesc_prologue (int body, unw_word rlen, unsigned char mask, unsigned char grsave, struct unw_state_record *sr){ int i; if (!(sr->in_body || sr->first_region)) finish_prologue (sr); sr->first_region = 0; /* Check if we're done. */ if (sr->when_target < sr->region_start + sr->region_len) { sr->done = 1; return; } for (i = 0; i < sr->epilogue_count; ++i) pop (sr); sr->epilogue_count = 0; sr->epilogue_start = UNW_WHEN_NEVER; if (!body) push (sr); sr->region_start += sr->region_len; sr->region_len = rlen; sr->in_body = body; if (!body) { for (i = 0; i < 4; ++i) { if (mask & 0x8) set_reg (sr->curr.reg + save_order[i], UNW_WHERE_GR, sr->region_start + sr->region_len - 1, grsave++); mask <<= 1; } sr->gr_save_loc = grsave; sr->any_spills = 0; sr->imask = 0; sr->spill_offset = 0x10; /* default to psp+16 */ }}/* * Prologue descriptors. */static inline voiddesc_abi (unsigned char abi, unsigned char context, struct unw_state_record *sr){ sr->unwabi = (abi << 8) | context;}static inline voiddesc_br_gr (unsigned char brmask, unsigned char gr, struct unw_state_record *sr){ int i; for (i = 0; i < 5; ++i) { if (brmask & 1) set_reg (sr->curr.reg + UNW_REG_B1 + i, UNW_WHERE_GR, sr->region_start + sr->region_len - 1, gr++); brmask >>= 1; }}static inline voiddesc_br_mem (unsigned char brmask, struct unw_state_record *sr){ int i; for (i = 0; i < 5; ++i) { if (brmask & 1) { set_reg (sr->curr.reg + UNW_REG_B1 + i, UNW_WHERE_SPILL_HOME, sr->region_start + sr->region_len - 1, 0); sr->any_spills = 1; } brmask >>= 1; }}static inline voiddesc_frgr_mem (unsigned char grmask, unw_word frmask, struct unw_state_record *sr){ int i; for (i = 0; i < 4; ++i) { if ((grmask & 1) != 0) { set_reg (sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_SPILL_HOME, sr->region_start + sr->region_len - 1, 0); sr->any_spills = 1; } grmask >>= 1; } for (i = 0; i < 20; ++i) { if ((frmask & 1) != 0) { enum unw_register_index base = i < 4 ? UNW_REG_F2 : UNW_REG_F16 - 4; set_reg (sr->curr.reg + base + i, UNW_WHERE_SPILL_HOME, sr->region_start + sr->region_len - 1, 0); sr->any_spills = 1; } frmask >>= 1; }}static inline voiddesc_fr_mem (unsigned char frmask, struct unw_state_record *sr){ int i; for (i = 0; i < 4; ++i) { if ((frmask & 1) != 0) { set_reg (sr->curr.reg + UNW_REG_F2 + i, UNW_WHERE_SPILL_HOME, sr->region_start + sr->region_len - 1, 0); sr->any_spills = 1; } frmask >>= 1; }}static inline voiddesc_gr_gr (unsigned char grmask, unsigned char gr, struct unw_state_record *sr){ int i; for (i = 0; i < 4; ++i) { if ((grmask & 1) != 0) set_reg (sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_GR, sr->region_start + sr->region_len - 1, gr++); grmask >>= 1; }}static inline voiddesc_gr_mem (unsigned char grmask, struct unw_state_record *sr){ int i; for (i = 0; i < 4; ++i) { if ((grmask & 1) != 0) { set_reg (sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_SPILL_HOME, sr->region_start + sr->region_len - 1, 0); sr->any_spills = 1; } grmask >>= 1; }}static inline voiddesc_mem_stack_f (unw_word t, unw_word size, struct unw_state_record *sr){ set_reg (sr->curr.reg + UNW_REG_PSP, UNW_WHERE_NONE, sr->region_start + MIN ((int)t, sr->region_len - 1), 16*size);}static inline voiddesc_mem_stack_v (unw_word t, struct unw_state_record *sr){ sr->curr.reg[UNW_REG_PSP].when = sr->region_start + MIN ((int)t, sr->region_len - 1);}static inline voiddesc_reg_gr (unsigned char reg, unsigned char dst, struct unw_state_record *sr){ set_reg (sr->curr.reg + reg, UNW_WHERE_GR, sr->region_start + sr->region_len - 1, dst);}static inline voiddesc_reg_psprel (unsigned char reg, unw_word pspoff, struct unw_state_record *sr){ set_reg (sr->curr.reg + reg, UNW_WHERE_PSPREL, sr->region_start + sr->region_len - 1, 0x10 - 4*pspoff);}static inline voiddesc_reg_sprel (unsigned char reg, unw_word spoff, struct unw_state_record *sr){ set_reg (sr->curr.reg + reg, UNW_WHERE_SPREL, sr->region_start + sr->region_len - 1, 4*spoff);}static inline voiddesc_rp_br (unsigned char dst, struct unw_state_record *sr){ sr->return_link_reg = dst;}static inline voiddesc_reg_when (unsigned char regnum, unw_word t, struct unw_state_record *sr){ struct unw_reg_info *reg = sr->curr.reg + regnum; if (reg->where == UNW_WHERE_NONE) reg->where = UNW_WHERE_GR_SAVE; reg->when = sr->region_start + MIN ((int)t, sr->region_len - 1);}static inline voiddesc_spill_base (unw_word pspoff, struct unw_state_record *sr){ sr->spill_offset = 0x10 - 4*pspoff;}static inline unsigned char *desc_spill_mask (unsigned char *imaskp, struct unw_state_record *sr){ sr->imask = imaskp; return imaskp + (2*sr->region_len + 7)/8;}/* * Body descriptors. */static inline voiddesc_epilogue (unw_word t, unw_word ecount, struct unw_state_record *sr){ sr->epilogue_start = sr->region_start + sr->region_len - 1 - t; sr->epilogue_count = ecount + 1;}static inline voiddesc_copy_state (unw_word label, struct unw_state_record *sr){ struct unw_labeled_state *ls; for (ls = sr->labeled_states; ls; ls = ls->next) { if (ls->label == label) { free_state_stack (&sr->curr); memcpy (&sr->curr, &ls->saved_state, sizeof (sr->curr)); sr->curr.next = dup_state_stack (ls->saved_state.next); return; } } abort ();}static inline voiddesc_label_state (unw_word label, struct unw_state_record *sr){ struct unw_labeled_state *ls = alloc_label_state (); ls->label = label; memcpy (&ls->saved_state, &sr->curr, sizeof (ls->saved_state)); ls->saved_state.next = dup_state_stack (sr->curr.next); /* Insert into list of labeled states. */ ls->next = sr->labeled_states; sr->labeled_states = ls;}/* * General descriptors. */static inline intdesc_is_active (unsigned char qp, unw_word t, struct unw_state_record *sr){ if (sr->when_target <= sr->region_start + MIN ((int)t, sr->region_len - 1)) return 0; if (qp > 0) { if ((sr->pr_val & (1UL << qp)) == 0) return 0; sr->pr_mask |= (1UL << qp); } return 1;}static inline voiddesc_restore_p (unsigned char qp, unw_word t, unsigned char abreg, struct unw_state_record *sr){ struct unw_reg_info *r; if (! desc_is_active (qp, t, sr)) return; r = sr->curr.reg + decode_abreg (abreg, 0); r->where = UNW_WHERE_NONE; r->when = sr->region_start + MIN ((int)t, sr->region_len - 1); r->val = 0;}static inline voiddesc_spill_reg_p (unsigned char qp, unw_word t, unsigned char abreg, unsigned char x, unsigned char ytreg, struct unw_state_record *sr){ enum unw_where where = UNW_WHERE_GR; struct unw_reg_info *r; if (! desc_is_active (qp, t, sr)) return; if (x) where = UNW_WHERE_BR; else if (ytreg & 0x80) where = UNW_WHERE_FR; r = sr->curr.reg + decode_abreg (abreg, 0); r->where = where; r->when = sr->region_start + MIN ((int)t, sr->region_len - 1); r->val = ytreg & 0x7f;}static inline voiddesc_spill_psprel_p (unsigned char qp, unw_word t, unsigned char abreg, unw_word pspoff, struct unw_state_record *sr){ struct unw_reg_info *r; if (! desc_is_active (qp, t, sr)) return; r = sr->curr.reg + decode_abreg (abreg, 1); r->where = UNW_WHERE_PSPREL; r->when = sr->region_start + MIN((int)t, sr->region_len - 1); r->val = 0x10 - 4*pspoff;}static inline voiddesc_spill_sprel_p (unsigned char qp, unw_word t, unsigned char abreg, unw_word spoff, struct unw_state_record *sr){ struct unw_reg_info *r; if (! desc_is_active (qp, t, sr)) return; r = sr->curr.reg + decode_abreg (abreg, 1); r->where = UNW_WHERE_SPREL; r->when = sr->region_start + MIN ((int)t, sr->region_len - 1); r->val = 4*spoff;}#define UNW_DEC_BAD_CODE(code) abort ();/* Region headers. */#define UNW_DEC_PROLOGUE_GR(fmt,r,m,gr,arg) desc_prologue(0,r,m,gr,arg)#define UNW_DEC_PROLOGUE(fmt,b,r,arg) desc_prologue(b,r,0,32,arg)/* Prologue descriptors. */#define UNW_DEC_ABI(fmt,a,c,arg) desc_abi(a,c,arg)#define UNW_DEC_BR_GR(fmt,b,g,arg) desc_br_gr(b,g,arg)#define UNW_DEC_BR_MEM(fmt,b,arg) desc_br_mem(b,arg)#define UNW_DEC_FRGR_MEM(fmt,g,f,arg) desc_frgr_mem(g,f,arg)#define UNW_DEC_FR_MEM(fmt,f,arg) desc_fr_mem(f,arg)#define UNW_DEC_GR_GR(fmt,m,g,arg) desc_gr_gr(m,g,arg)#define UNW_DEC_GR_MEM(fmt,m,arg) desc_gr_mem(m,arg)#define UNW_DEC_MEM_STACK_F(fmt,t,s,arg) desc_mem_stack_f(t,s,arg)#define UNW_DEC_MEM_STACK_V(fmt,t,arg) desc_mem_stack_v(t,arg)#define UNW_DEC_REG_GR(fmt,r,d,arg) desc_reg_gr(r,d,arg)#define UNW_DEC_REG_PSPREL(fmt,r,o,arg) desc_reg_psprel(r,o,arg)#define UNW_DEC_REG_SPREL(fmt,r,o,arg) desc_reg_sprel(r,o,arg)#define UNW_DEC_REG_WHEN(fmt,r,t,arg) desc_reg_when(r,t,arg)#define UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg) desc_reg_when(UNW_REG_PRI_UNAT_GR,t,arg)#define UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg) desc_reg_when(UNW_REG_PRI_UNAT_MEM,t,arg)#define UNW_DEC_PRIUNAT_GR(fmt,r,arg) desc_reg_gr(UNW_REG_PRI_UNAT_GR,r,arg)#define UNW_DEC_PRIUNAT_PSPREL(fmt,o,arg) desc_reg_psprel(UNW_REG_PRI_UNAT_MEM,o,arg)#define UNW_DEC_PRIUNAT_SPREL(fmt,o,arg) desc_reg_sprel(UNW_REG_PRI_UNAT_MEM,o,arg)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -