162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2000 Hewlett-Packard Co 462306a36Sopenharmony_ci * Copyright (C) 2000 David Mosberger-Tang <davidm@hpl.hp.com> 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Generic IA-64 unwind info decoder. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * This file is used both by the Linux kernel and objdump. Please keep 962306a36Sopenharmony_ci * the two copies of this file in sync. 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * You need to customize the decoder by defining the following 1262306a36Sopenharmony_ci * macros/constants before including this file: 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * Types: 1562306a36Sopenharmony_ci * unw_word Unsigned integer type with at least 64 bits 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci * Register names: 1862306a36Sopenharmony_ci * UNW_REG_BSP 1962306a36Sopenharmony_ci * UNW_REG_BSPSTORE 2062306a36Sopenharmony_ci * UNW_REG_FPSR 2162306a36Sopenharmony_ci * UNW_REG_LC 2262306a36Sopenharmony_ci * UNW_REG_PFS 2362306a36Sopenharmony_ci * UNW_REG_PR 2462306a36Sopenharmony_ci * UNW_REG_RNAT 2562306a36Sopenharmony_ci * UNW_REG_PSP 2662306a36Sopenharmony_ci * UNW_REG_RP 2762306a36Sopenharmony_ci * UNW_REG_UNAT 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci * Decoder action macros: 3062306a36Sopenharmony_ci * UNW_DEC_BAD_CODE(code) 3162306a36Sopenharmony_ci * UNW_DEC_ABI(fmt,abi,context,arg) 3262306a36Sopenharmony_ci * UNW_DEC_BR_GR(fmt,brmask,gr,arg) 3362306a36Sopenharmony_ci * UNW_DEC_BR_MEM(fmt,brmask,arg) 3462306a36Sopenharmony_ci * UNW_DEC_COPY_STATE(fmt,label,arg) 3562306a36Sopenharmony_ci * UNW_DEC_EPILOGUE(fmt,t,ecount,arg) 3662306a36Sopenharmony_ci * UNW_DEC_FRGR_MEM(fmt,grmask,frmask,arg) 3762306a36Sopenharmony_ci * UNW_DEC_FR_MEM(fmt,frmask,arg) 3862306a36Sopenharmony_ci * UNW_DEC_GR_GR(fmt,grmask,gr,arg) 3962306a36Sopenharmony_ci * UNW_DEC_GR_MEM(fmt,grmask,arg) 4062306a36Sopenharmony_ci * UNW_DEC_LABEL_STATE(fmt,label,arg) 4162306a36Sopenharmony_ci * UNW_DEC_MEM_STACK_F(fmt,t,size,arg) 4262306a36Sopenharmony_ci * UNW_DEC_MEM_STACK_V(fmt,t,arg) 4362306a36Sopenharmony_ci * UNW_DEC_PRIUNAT_GR(fmt,r,arg) 4462306a36Sopenharmony_ci * UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg) 4562306a36Sopenharmony_ci * UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg) 4662306a36Sopenharmony_ci * UNW_DEC_PRIUNAT_WHEN_PSPREL(fmt,pspoff,arg) 4762306a36Sopenharmony_ci * UNW_DEC_PRIUNAT_WHEN_SPREL(fmt,spoff,arg) 4862306a36Sopenharmony_ci * UNW_DEC_PROLOGUE(fmt,body,rlen,arg) 4962306a36Sopenharmony_ci * UNW_DEC_PROLOGUE_GR(fmt,rlen,mask,grsave,arg) 5062306a36Sopenharmony_ci * UNW_DEC_REG_PSPREL(fmt,reg,pspoff,arg) 5162306a36Sopenharmony_ci * UNW_DEC_REG_REG(fmt,src,dst,arg) 5262306a36Sopenharmony_ci * UNW_DEC_REG_SPREL(fmt,reg,spoff,arg) 5362306a36Sopenharmony_ci * UNW_DEC_REG_WHEN(fmt,reg,t,arg) 5462306a36Sopenharmony_ci * UNW_DEC_RESTORE(fmt,t,abreg,arg) 5562306a36Sopenharmony_ci * UNW_DEC_RESTORE_P(fmt,qp,t,abreg,arg) 5662306a36Sopenharmony_ci * UNW_DEC_SPILL_BASE(fmt,pspoff,arg) 5762306a36Sopenharmony_ci * UNW_DEC_SPILL_MASK(fmt,imaskp,arg) 5862306a36Sopenharmony_ci * UNW_DEC_SPILL_PSPREL(fmt,t,abreg,pspoff,arg) 5962306a36Sopenharmony_ci * UNW_DEC_SPILL_PSPREL_P(fmt,qp,t,abreg,pspoff,arg) 6062306a36Sopenharmony_ci * UNW_DEC_SPILL_REG(fmt,t,abreg,x,ytreg,arg) 6162306a36Sopenharmony_ci * UNW_DEC_SPILL_REG_P(fmt,qp,t,abreg,x,ytreg,arg) 6262306a36Sopenharmony_ci * UNW_DEC_SPILL_SPREL(fmt,t,abreg,spoff,arg) 6362306a36Sopenharmony_ci * UNW_DEC_SPILL_SPREL_P(fmt,qp,t,abreg,pspoff,arg) 6462306a36Sopenharmony_ci */ 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_cistatic unw_word 6762306a36Sopenharmony_ciunw_decode_uleb128 (unsigned char **dpp) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci unsigned shift = 0; 7062306a36Sopenharmony_ci unw_word byte, result = 0; 7162306a36Sopenharmony_ci unsigned char *bp = *dpp; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci while (1) 7462306a36Sopenharmony_ci { 7562306a36Sopenharmony_ci byte = *bp++; 7662306a36Sopenharmony_ci result |= (byte & 0x7f) << shift; 7762306a36Sopenharmony_ci if ((byte & 0x80) == 0) 7862306a36Sopenharmony_ci break; 7962306a36Sopenharmony_ci shift += 7; 8062306a36Sopenharmony_ci } 8162306a36Sopenharmony_ci *dpp = bp; 8262306a36Sopenharmony_ci return result; 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistatic unsigned char * 8662306a36Sopenharmony_ciunw_decode_x1 (unsigned char *dp, unsigned char code, void *arg) 8762306a36Sopenharmony_ci{ 8862306a36Sopenharmony_ci unsigned char byte1, abreg; 8962306a36Sopenharmony_ci unw_word t, off; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci byte1 = *dp++; 9262306a36Sopenharmony_ci t = unw_decode_uleb128 (&dp); 9362306a36Sopenharmony_ci off = unw_decode_uleb128 (&dp); 9462306a36Sopenharmony_ci abreg = (byte1 & 0x7f); 9562306a36Sopenharmony_ci if (byte1 & 0x80) 9662306a36Sopenharmony_ci UNW_DEC_SPILL_SPREL(X1, t, abreg, off, arg); 9762306a36Sopenharmony_ci else 9862306a36Sopenharmony_ci UNW_DEC_SPILL_PSPREL(X1, t, abreg, off, arg); 9962306a36Sopenharmony_ci return dp; 10062306a36Sopenharmony_ci} 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cistatic unsigned char * 10362306a36Sopenharmony_ciunw_decode_x2 (unsigned char *dp, unsigned char code, void *arg) 10462306a36Sopenharmony_ci{ 10562306a36Sopenharmony_ci unsigned char byte1, byte2, abreg, x, ytreg; 10662306a36Sopenharmony_ci unw_word t; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci byte1 = *dp++; byte2 = *dp++; 10962306a36Sopenharmony_ci t = unw_decode_uleb128 (&dp); 11062306a36Sopenharmony_ci abreg = (byte1 & 0x7f); 11162306a36Sopenharmony_ci ytreg = byte2; 11262306a36Sopenharmony_ci x = (byte1 >> 7) & 1; 11362306a36Sopenharmony_ci if ((byte1 & 0x80) == 0 && ytreg == 0) 11462306a36Sopenharmony_ci UNW_DEC_RESTORE(X2, t, abreg, arg); 11562306a36Sopenharmony_ci else 11662306a36Sopenharmony_ci UNW_DEC_SPILL_REG(X2, t, abreg, x, ytreg, arg); 11762306a36Sopenharmony_ci return dp; 11862306a36Sopenharmony_ci} 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistatic unsigned char * 12162306a36Sopenharmony_ciunw_decode_x3 (unsigned char *dp, unsigned char code, void *arg) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci unsigned char byte1, byte2, abreg, qp; 12462306a36Sopenharmony_ci unw_word t, off; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci byte1 = *dp++; byte2 = *dp++; 12762306a36Sopenharmony_ci t = unw_decode_uleb128 (&dp); 12862306a36Sopenharmony_ci off = unw_decode_uleb128 (&dp); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci qp = (byte1 & 0x3f); 13162306a36Sopenharmony_ci abreg = (byte2 & 0x7f); 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci if (byte1 & 0x80) 13462306a36Sopenharmony_ci UNW_DEC_SPILL_SPREL_P(X3, qp, t, abreg, off, arg); 13562306a36Sopenharmony_ci else 13662306a36Sopenharmony_ci UNW_DEC_SPILL_PSPREL_P(X3, qp, t, abreg, off, arg); 13762306a36Sopenharmony_ci return dp; 13862306a36Sopenharmony_ci} 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_cistatic unsigned char * 14162306a36Sopenharmony_ciunw_decode_x4 (unsigned char *dp, unsigned char code, void *arg) 14262306a36Sopenharmony_ci{ 14362306a36Sopenharmony_ci unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg; 14462306a36Sopenharmony_ci unw_word t; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci byte1 = *dp++; byte2 = *dp++; byte3 = *dp++; 14762306a36Sopenharmony_ci t = unw_decode_uleb128 (&dp); 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci qp = (byte1 & 0x3f); 15062306a36Sopenharmony_ci abreg = (byte2 & 0x7f); 15162306a36Sopenharmony_ci x = (byte2 >> 7) & 1; 15262306a36Sopenharmony_ci ytreg = byte3; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci if ((byte2 & 0x80) == 0 && byte3 == 0) 15562306a36Sopenharmony_ci UNW_DEC_RESTORE_P(X4, qp, t, abreg, arg); 15662306a36Sopenharmony_ci else 15762306a36Sopenharmony_ci UNW_DEC_SPILL_REG_P(X4, qp, t, abreg, x, ytreg, arg); 15862306a36Sopenharmony_ci return dp; 15962306a36Sopenharmony_ci} 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_cistatic unsigned char * 16262306a36Sopenharmony_ciunw_decode_r1 (unsigned char *dp, unsigned char code, void *arg) 16362306a36Sopenharmony_ci{ 16462306a36Sopenharmony_ci int body = (code & 0x20) != 0; 16562306a36Sopenharmony_ci unw_word rlen; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci rlen = (code & 0x1f); 16862306a36Sopenharmony_ci UNW_DEC_PROLOGUE(R1, body, rlen, arg); 16962306a36Sopenharmony_ci return dp; 17062306a36Sopenharmony_ci} 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_cistatic unsigned char * 17362306a36Sopenharmony_ciunw_decode_r2 (unsigned char *dp, unsigned char code, void *arg) 17462306a36Sopenharmony_ci{ 17562306a36Sopenharmony_ci unsigned char byte1, mask, grsave; 17662306a36Sopenharmony_ci unw_word rlen; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci byte1 = *dp++; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci mask = ((code & 0x7) << 1) | ((byte1 >> 7) & 1); 18162306a36Sopenharmony_ci grsave = (byte1 & 0x7f); 18262306a36Sopenharmony_ci rlen = unw_decode_uleb128 (&dp); 18362306a36Sopenharmony_ci UNW_DEC_PROLOGUE_GR(R2, rlen, mask, grsave, arg); 18462306a36Sopenharmony_ci return dp; 18562306a36Sopenharmony_ci} 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_cistatic unsigned char * 18862306a36Sopenharmony_ciunw_decode_r3 (unsigned char *dp, unsigned char code, void *arg) 18962306a36Sopenharmony_ci{ 19062306a36Sopenharmony_ci unw_word rlen; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci rlen = unw_decode_uleb128 (&dp); 19362306a36Sopenharmony_ci UNW_DEC_PROLOGUE(R3, ((code & 0x3) == 1), rlen, arg); 19462306a36Sopenharmony_ci return dp; 19562306a36Sopenharmony_ci} 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_cistatic unsigned char * 19862306a36Sopenharmony_ciunw_decode_p1 (unsigned char *dp, unsigned char code, void *arg) 19962306a36Sopenharmony_ci{ 20062306a36Sopenharmony_ci unsigned char brmask = (code & 0x1f); 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci UNW_DEC_BR_MEM(P1, brmask, arg); 20362306a36Sopenharmony_ci return dp; 20462306a36Sopenharmony_ci} 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_cistatic unsigned char * 20762306a36Sopenharmony_ciunw_decode_p2_p5 (unsigned char *dp, unsigned char code, void *arg) 20862306a36Sopenharmony_ci{ 20962306a36Sopenharmony_ci if ((code & 0x10) == 0) 21062306a36Sopenharmony_ci { 21162306a36Sopenharmony_ci unsigned char byte1 = *dp++; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci UNW_DEC_BR_GR(P2, ((code & 0xf) << 1) | ((byte1 >> 7) & 1), 21462306a36Sopenharmony_ci (byte1 & 0x7f), arg); 21562306a36Sopenharmony_ci } 21662306a36Sopenharmony_ci else if ((code & 0x08) == 0) 21762306a36Sopenharmony_ci { 21862306a36Sopenharmony_ci unsigned char byte1 = *dp++, r, dst; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci r = ((code & 0x7) << 1) | ((byte1 >> 7) & 1); 22162306a36Sopenharmony_ci dst = (byte1 & 0x7f); 22262306a36Sopenharmony_ci switch (r) 22362306a36Sopenharmony_ci { 22462306a36Sopenharmony_ci case 0: UNW_DEC_REG_GR(P3, UNW_REG_PSP, dst, arg); break; 22562306a36Sopenharmony_ci case 1: UNW_DEC_REG_GR(P3, UNW_REG_RP, dst, arg); break; 22662306a36Sopenharmony_ci case 2: UNW_DEC_REG_GR(P3, UNW_REG_PFS, dst, arg); break; 22762306a36Sopenharmony_ci case 3: UNW_DEC_REG_GR(P3, UNW_REG_PR, dst, arg); break; 22862306a36Sopenharmony_ci case 4: UNW_DEC_REG_GR(P3, UNW_REG_UNAT, dst, arg); break; 22962306a36Sopenharmony_ci case 5: UNW_DEC_REG_GR(P3, UNW_REG_LC, dst, arg); break; 23062306a36Sopenharmony_ci case 6: UNW_DEC_RP_BR(P3, dst, arg); break; 23162306a36Sopenharmony_ci case 7: UNW_DEC_REG_GR(P3, UNW_REG_RNAT, dst, arg); break; 23262306a36Sopenharmony_ci case 8: UNW_DEC_REG_GR(P3, UNW_REG_BSP, dst, arg); break; 23362306a36Sopenharmony_ci case 9: UNW_DEC_REG_GR(P3, UNW_REG_BSPSTORE, dst, arg); break; 23462306a36Sopenharmony_ci case 10: UNW_DEC_REG_GR(P3, UNW_REG_FPSR, dst, arg); break; 23562306a36Sopenharmony_ci case 11: UNW_DEC_PRIUNAT_GR(P3, dst, arg); break; 23662306a36Sopenharmony_ci default: UNW_DEC_BAD_CODE(r); break; 23762306a36Sopenharmony_ci } 23862306a36Sopenharmony_ci } 23962306a36Sopenharmony_ci else if ((code & 0x7) == 0) 24062306a36Sopenharmony_ci UNW_DEC_SPILL_MASK(P4, dp, arg); 24162306a36Sopenharmony_ci else if ((code & 0x7) == 1) 24262306a36Sopenharmony_ci { 24362306a36Sopenharmony_ci unw_word grmask, frmask, byte1, byte2, byte3; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci byte1 = *dp++; byte2 = *dp++; byte3 = *dp++; 24662306a36Sopenharmony_ci grmask = ((byte1 >> 4) & 0xf); 24762306a36Sopenharmony_ci frmask = ((byte1 & 0xf) << 16) | (byte2 << 8) | byte3; 24862306a36Sopenharmony_ci UNW_DEC_FRGR_MEM(P5, grmask, frmask, arg); 24962306a36Sopenharmony_ci } 25062306a36Sopenharmony_ci else 25162306a36Sopenharmony_ci UNW_DEC_BAD_CODE(code); 25262306a36Sopenharmony_ci return dp; 25362306a36Sopenharmony_ci} 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_cistatic unsigned char * 25662306a36Sopenharmony_ciunw_decode_p6 (unsigned char *dp, unsigned char code, void *arg) 25762306a36Sopenharmony_ci{ 25862306a36Sopenharmony_ci int gregs = (code & 0x10) != 0; 25962306a36Sopenharmony_ci unsigned char mask = (code & 0x0f); 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci if (gregs) 26262306a36Sopenharmony_ci UNW_DEC_GR_MEM(P6, mask, arg); 26362306a36Sopenharmony_ci else 26462306a36Sopenharmony_ci UNW_DEC_FR_MEM(P6, mask, arg); 26562306a36Sopenharmony_ci return dp; 26662306a36Sopenharmony_ci} 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_cistatic unsigned char * 26962306a36Sopenharmony_ciunw_decode_p7_p10 (unsigned char *dp, unsigned char code, void *arg) 27062306a36Sopenharmony_ci{ 27162306a36Sopenharmony_ci unsigned char r, byte1, byte2; 27262306a36Sopenharmony_ci unw_word t, size; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci if ((code & 0x10) == 0) 27562306a36Sopenharmony_ci { 27662306a36Sopenharmony_ci r = (code & 0xf); 27762306a36Sopenharmony_ci t = unw_decode_uleb128 (&dp); 27862306a36Sopenharmony_ci switch (r) 27962306a36Sopenharmony_ci { 28062306a36Sopenharmony_ci case 0: 28162306a36Sopenharmony_ci size = unw_decode_uleb128 (&dp); 28262306a36Sopenharmony_ci UNW_DEC_MEM_STACK_F(P7, t, size, arg); 28362306a36Sopenharmony_ci break; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci case 1: UNW_DEC_MEM_STACK_V(P7, t, arg); break; 28662306a36Sopenharmony_ci case 2: UNW_DEC_SPILL_BASE(P7, t, arg); break; 28762306a36Sopenharmony_ci case 3: UNW_DEC_REG_SPREL(P7, UNW_REG_PSP, t, arg); break; 28862306a36Sopenharmony_ci case 4: UNW_DEC_REG_WHEN(P7, UNW_REG_RP, t, arg); break; 28962306a36Sopenharmony_ci case 5: UNW_DEC_REG_PSPREL(P7, UNW_REG_RP, t, arg); break; 29062306a36Sopenharmony_ci case 6: UNW_DEC_REG_WHEN(P7, UNW_REG_PFS, t, arg); break; 29162306a36Sopenharmony_ci case 7: UNW_DEC_REG_PSPREL(P7, UNW_REG_PFS, t, arg); break; 29262306a36Sopenharmony_ci case 8: UNW_DEC_REG_WHEN(P7, UNW_REG_PR, t, arg); break; 29362306a36Sopenharmony_ci case 9: UNW_DEC_REG_PSPREL(P7, UNW_REG_PR, t, arg); break; 29462306a36Sopenharmony_ci case 10: UNW_DEC_REG_WHEN(P7, UNW_REG_LC, t, arg); break; 29562306a36Sopenharmony_ci case 11: UNW_DEC_REG_PSPREL(P7, UNW_REG_LC, t, arg); break; 29662306a36Sopenharmony_ci case 12: UNW_DEC_REG_WHEN(P7, UNW_REG_UNAT, t, arg); break; 29762306a36Sopenharmony_ci case 13: UNW_DEC_REG_PSPREL(P7, UNW_REG_UNAT, t, arg); break; 29862306a36Sopenharmony_ci case 14: UNW_DEC_REG_WHEN(P7, UNW_REG_FPSR, t, arg); break; 29962306a36Sopenharmony_ci case 15: UNW_DEC_REG_PSPREL(P7, UNW_REG_FPSR, t, arg); break; 30062306a36Sopenharmony_ci default: UNW_DEC_BAD_CODE(r); break; 30162306a36Sopenharmony_ci } 30262306a36Sopenharmony_ci } 30362306a36Sopenharmony_ci else 30462306a36Sopenharmony_ci { 30562306a36Sopenharmony_ci switch (code & 0xf) 30662306a36Sopenharmony_ci { 30762306a36Sopenharmony_ci case 0x0: /* p8 */ 30862306a36Sopenharmony_ci { 30962306a36Sopenharmony_ci r = *dp++; 31062306a36Sopenharmony_ci t = unw_decode_uleb128 (&dp); 31162306a36Sopenharmony_ci switch (r) 31262306a36Sopenharmony_ci { 31362306a36Sopenharmony_ci case 1: UNW_DEC_REG_SPREL(P8, UNW_REG_RP, t, arg); break; 31462306a36Sopenharmony_ci case 2: UNW_DEC_REG_SPREL(P8, UNW_REG_PFS, t, arg); break; 31562306a36Sopenharmony_ci case 3: UNW_DEC_REG_SPREL(P8, UNW_REG_PR, t, arg); break; 31662306a36Sopenharmony_ci case 4: UNW_DEC_REG_SPREL(P8, UNW_REG_LC, t, arg); break; 31762306a36Sopenharmony_ci case 5: UNW_DEC_REG_SPREL(P8, UNW_REG_UNAT, t, arg); break; 31862306a36Sopenharmony_ci case 6: UNW_DEC_REG_SPREL(P8, UNW_REG_FPSR, t, arg); break; 31962306a36Sopenharmony_ci case 7: UNW_DEC_REG_WHEN(P8, UNW_REG_BSP, t, arg); break; 32062306a36Sopenharmony_ci case 8: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSP, t, arg); break; 32162306a36Sopenharmony_ci case 9: UNW_DEC_REG_SPREL(P8, UNW_REG_BSP, t, arg); break; 32262306a36Sopenharmony_ci case 10: UNW_DEC_REG_WHEN(P8, UNW_REG_BSPSTORE, t, arg); break; 32362306a36Sopenharmony_ci case 11: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSPSTORE, t, arg); break; 32462306a36Sopenharmony_ci case 12: UNW_DEC_REG_SPREL(P8, UNW_REG_BSPSTORE, t, arg); break; 32562306a36Sopenharmony_ci case 13: UNW_DEC_REG_WHEN(P8, UNW_REG_RNAT, t, arg); break; 32662306a36Sopenharmony_ci case 14: UNW_DEC_REG_PSPREL(P8, UNW_REG_RNAT, t, arg); break; 32762306a36Sopenharmony_ci case 15: UNW_DEC_REG_SPREL(P8, UNW_REG_RNAT, t, arg); break; 32862306a36Sopenharmony_ci case 16: UNW_DEC_PRIUNAT_WHEN_GR(P8, t, arg); break; 32962306a36Sopenharmony_ci case 17: UNW_DEC_PRIUNAT_PSPREL(P8, t, arg); break; 33062306a36Sopenharmony_ci case 18: UNW_DEC_PRIUNAT_SPREL(P8, t, arg); break; 33162306a36Sopenharmony_ci case 19: UNW_DEC_PRIUNAT_WHEN_MEM(P8, t, arg); break; 33262306a36Sopenharmony_ci default: UNW_DEC_BAD_CODE(r); break; 33362306a36Sopenharmony_ci } 33462306a36Sopenharmony_ci } 33562306a36Sopenharmony_ci break; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci case 0x1: 33862306a36Sopenharmony_ci byte1 = *dp++; byte2 = *dp++; 33962306a36Sopenharmony_ci UNW_DEC_GR_GR(P9, (byte1 & 0xf), (byte2 & 0x7f), arg); 34062306a36Sopenharmony_ci break; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci case 0xf: /* p10 */ 34362306a36Sopenharmony_ci byte1 = *dp++; byte2 = *dp++; 34462306a36Sopenharmony_ci UNW_DEC_ABI(P10, byte1, byte2, arg); 34562306a36Sopenharmony_ci break; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci case 0x9: 34862306a36Sopenharmony_ci return unw_decode_x1 (dp, code, arg); 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci case 0xa: 35162306a36Sopenharmony_ci return unw_decode_x2 (dp, code, arg); 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci case 0xb: 35462306a36Sopenharmony_ci return unw_decode_x3 (dp, code, arg); 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci case 0xc: 35762306a36Sopenharmony_ci return unw_decode_x4 (dp, code, arg); 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci default: 36062306a36Sopenharmony_ci UNW_DEC_BAD_CODE(code); 36162306a36Sopenharmony_ci break; 36262306a36Sopenharmony_ci } 36362306a36Sopenharmony_ci } 36462306a36Sopenharmony_ci return dp; 36562306a36Sopenharmony_ci} 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_cistatic unsigned char * 36862306a36Sopenharmony_ciunw_decode_b1 (unsigned char *dp, unsigned char code, void *arg) 36962306a36Sopenharmony_ci{ 37062306a36Sopenharmony_ci unw_word label = (code & 0x1f); 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci if ((code & 0x20) != 0) 37362306a36Sopenharmony_ci UNW_DEC_COPY_STATE(B1, label, arg); 37462306a36Sopenharmony_ci else 37562306a36Sopenharmony_ci UNW_DEC_LABEL_STATE(B1, label, arg); 37662306a36Sopenharmony_ci return dp; 37762306a36Sopenharmony_ci} 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_cistatic unsigned char * 38062306a36Sopenharmony_ciunw_decode_b2 (unsigned char *dp, unsigned char code, void *arg) 38162306a36Sopenharmony_ci{ 38262306a36Sopenharmony_ci unw_word t; 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci t = unw_decode_uleb128 (&dp); 38562306a36Sopenharmony_ci UNW_DEC_EPILOGUE(B2, t, (code & 0x1f), arg); 38662306a36Sopenharmony_ci return dp; 38762306a36Sopenharmony_ci} 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_cistatic unsigned char * 39062306a36Sopenharmony_ciunw_decode_b3_x4 (unsigned char *dp, unsigned char code, void *arg) 39162306a36Sopenharmony_ci{ 39262306a36Sopenharmony_ci unw_word t, ecount, label; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci if ((code & 0x10) == 0) 39562306a36Sopenharmony_ci { 39662306a36Sopenharmony_ci t = unw_decode_uleb128 (&dp); 39762306a36Sopenharmony_ci ecount = unw_decode_uleb128 (&dp); 39862306a36Sopenharmony_ci UNW_DEC_EPILOGUE(B3, t, ecount, arg); 39962306a36Sopenharmony_ci } 40062306a36Sopenharmony_ci else if ((code & 0x07) == 0) 40162306a36Sopenharmony_ci { 40262306a36Sopenharmony_ci label = unw_decode_uleb128 (&dp); 40362306a36Sopenharmony_ci if ((code & 0x08) != 0) 40462306a36Sopenharmony_ci UNW_DEC_COPY_STATE(B4, label, arg); 40562306a36Sopenharmony_ci else 40662306a36Sopenharmony_ci UNW_DEC_LABEL_STATE(B4, label, arg); 40762306a36Sopenharmony_ci } 40862306a36Sopenharmony_ci else 40962306a36Sopenharmony_ci switch (code & 0x7) 41062306a36Sopenharmony_ci { 41162306a36Sopenharmony_ci case 1: return unw_decode_x1 (dp, code, arg); 41262306a36Sopenharmony_ci case 2: return unw_decode_x2 (dp, code, arg); 41362306a36Sopenharmony_ci case 3: return unw_decode_x3 (dp, code, arg); 41462306a36Sopenharmony_ci case 4: return unw_decode_x4 (dp, code, arg); 41562306a36Sopenharmony_ci default: UNW_DEC_BAD_CODE(code); break; 41662306a36Sopenharmony_ci } 41762306a36Sopenharmony_ci return dp; 41862306a36Sopenharmony_ci} 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_citypedef unsigned char *(*unw_decoder) (unsigned char *, unsigned char, void *); 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_cistatic unw_decoder unw_decode_table[2][8] = 42362306a36Sopenharmony_ci{ 42462306a36Sopenharmony_ci /* prologue table: */ 42562306a36Sopenharmony_ci { 42662306a36Sopenharmony_ci unw_decode_r1, /* 0 */ 42762306a36Sopenharmony_ci unw_decode_r1, 42862306a36Sopenharmony_ci unw_decode_r2, 42962306a36Sopenharmony_ci unw_decode_r3, 43062306a36Sopenharmony_ci unw_decode_p1, /* 4 */ 43162306a36Sopenharmony_ci unw_decode_p2_p5, 43262306a36Sopenharmony_ci unw_decode_p6, 43362306a36Sopenharmony_ci unw_decode_p7_p10 43462306a36Sopenharmony_ci }, 43562306a36Sopenharmony_ci { 43662306a36Sopenharmony_ci unw_decode_r1, /* 0 */ 43762306a36Sopenharmony_ci unw_decode_r1, 43862306a36Sopenharmony_ci unw_decode_r2, 43962306a36Sopenharmony_ci unw_decode_r3, 44062306a36Sopenharmony_ci unw_decode_b1, /* 4 */ 44162306a36Sopenharmony_ci unw_decode_b1, 44262306a36Sopenharmony_ci unw_decode_b2, 44362306a36Sopenharmony_ci unw_decode_b3_x4 44462306a36Sopenharmony_ci } 44562306a36Sopenharmony_ci}; 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci/* 44862306a36Sopenharmony_ci * Decode one descriptor and return address of next descriptor. 44962306a36Sopenharmony_ci */ 45062306a36Sopenharmony_cistatic inline unsigned char * 45162306a36Sopenharmony_ciunw_decode (unsigned char *dp, int inside_body, void *arg) 45262306a36Sopenharmony_ci{ 45362306a36Sopenharmony_ci unw_decoder decoder; 45462306a36Sopenharmony_ci unsigned char code; 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci code = *dp++; 45762306a36Sopenharmony_ci decoder = unw_decode_table[inside_body][code >> 5]; 45862306a36Sopenharmony_ci dp = (*decoder) (dp, code, arg); 45962306a36Sopenharmony_ci return dp; 46062306a36Sopenharmony_ci} 461