diff options
Diffstat (limited to 'sys/contrib/ia64/libuwx/src/uwx_uinfo.c')
-rw-r--r-- | sys/contrib/ia64/libuwx/src/uwx_uinfo.c | 1119 |
1 files changed, 0 insertions, 1119 deletions
diff --git a/sys/contrib/ia64/libuwx/src/uwx_uinfo.c b/sys/contrib/ia64/libuwx/src/uwx_uinfo.c deleted file mode 100644 index 5f63b7e..0000000 --- a/sys/contrib/ia64/libuwx/src/uwx_uinfo.c +++ /dev/null @@ -1,1119 +0,0 @@ -/* -Copyright (c) 2003-2006 Hewlett-Packard Development Company, L.P. -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "uwx_env.h" -#include "uwx_uinfo.h" -#include "uwx_utable.h" -#include "uwx_scoreboard.h" -#include "uwx_bstream.h" -#include "uwx_trace.h" -#include "uwx_swap.h" - -int uwx_count_ones(unsigned int mask); - -/* - * uwx_uinfo.c - * - * This file contains the routines for reading and decoding - * the unwind information block. - * - * The main entry point, uwx_decode_uinfo(), is given a pointer - * to an unwind table entry and a pointer (passed by reference) - * to be filled in with a pointer to an update vector. It will - * read and decode the unwind descriptors contained in the - * unwind information block, then build the register state array, - * which describes the actions necessary to step from the current - * frame to the previous one. - */ - -#define COPYIN_UINFO_4(dest, src) \ - (env->remote? \ - (*env->copyin)(UWX_COPYIN_UINFO, (dest), (src), \ - WORDSZ, env->cb_token) : \ - (*(uint32_t *)(intptr_t)(dest) = *(uint32_t *)(intptr_t)(src), WORDSZ) ) - -#define COPYIN_UINFO_8(dest, src) \ - (env->remote? \ - (*env->copyin)(UWX_COPYIN_UINFO, (dest), (src), \ - DWORDSZ, env->cb_token) : \ - (*(uint64_t *)(intptr_t)(dest) = *(uint64_t *)(intptr_t)(src), DWORDSZ) ) - - -/* uwx_default_rstate: Returns the default register state for a leaf routine */ - -int uwx_default_rstate(struct uwx_env *env, uint64_t **rstatep) -{ - struct uwx_scoreboard *sb; - - sb = uwx_init_scoreboards(env); - *rstatep = sb->rstate; - return UWX_OK; -} - - -/* uwx_decode_uinfo: Decodes unwind info region */ - -int uwx_decode_uinfo( - struct uwx_env *env, - struct uwx_utable_entry *uentry, - uint64_t **rstatep) -{ - uint64_t uinfohdr; - unsigned int ulen; - int len; - struct uwx_bstream bstream; - struct uwx_scoreboard *scoreboard; - int ip_slot; - int cur_slot; - int status; - struct uwx_rhdr rhdr; - - /* Remember the offset from the start of the function */ - /* to the current IP. This helps the client find */ - /* the symbolic information. */ - - env->function_offset = env->remapped_ip - uentry->code_start; - - /* Read the unwind info header using the copyin callback. */ - /* (If we're reading a 32-bit unwind table, we need to */ - /* read the header as two 32-bit pieces to preserve the */ - /* guarantee that we always call copyin for aligned */ - /* 4-byte or 8-byte chunks.) */ - /* Then compute the length of the unwind descriptor */ - /* region and initialize a byte stream to read it. */ - - if (uentry->unwind_flags & UNWIND_TBL_32BIT) { - len = COPYIN_UINFO_4((char *)&uinfohdr, uentry->unwind_info); - len += COPYIN_UINFO_4((char *)&uinfohdr + WORDSZ, - uentry->unwind_info + WORDSZ); - } - else - len = COPYIN_UINFO_8((char *)&uinfohdr, uentry->unwind_info); - if (len != DWORDSZ) - return UWX_ERR_COPYIN_UINFO; - if (env->byte_swap) - uwx_swap8(&uinfohdr); - if (uentry->unwind_flags & UNWIND_TBL_32BIT) - ulen = UNW_LENGTH(uinfohdr) * WORDSZ; - else - ulen = UNW_LENGTH(uinfohdr) * DWORDSZ; - uwx_init_bstream(&bstream, env, - uentry->unwind_info + DWORDSZ, ulen, UWX_COPYIN_UINFO); - - /* Save the header and a pointer to the personality routine ptr */ - /* for later use in exception handling. */ - - env->uinfo_hdr = uinfohdr; - env->uinfo_end = uentry->unwind_info + DWORDSZ + ulen; - - TRACE_R_UIB(uentry, ulen) - - /* Create an initial scoreboard for tracking the unwind state. */ - - scoreboard = uwx_init_scoreboards(env); - - /* Prepare to read and decode the unwind regions described */ - /* by the unwind info block. Find the target "ip" slot */ - /* relative to the beginning of the region. The lower 4 bits */ - /* of the actual IP encode the slot number within a bundle. */ - - cur_slot = 0; - ip_slot = (int) ((env->context.special[UWX_REG_IP] & ~0x0fLL) - - uentry->code_start) - / BUNDLESZ * SLOTSPERBUNDLE - + (unsigned int) (env->context.special[UWX_REG_IP] & 0x0f); - - /* Loop over the regions in the unwind info block. */ - - for (;;) { - - /* Decode the next region header. */ - /* We have an error if we reach the end of the info block, */ - /* since we should have found our target ip slot by then. */ - /* We also have an error if the next byte isn't a region */ - /* header record. */ - - status = uwx_decode_rhdr(env, &bstream, &rhdr); - if (status != UWX_OK) - return status; - - /* If a prologue region, get a new scoreboard, pushing */ - /* the previous one onto the prologue stack. Then read */ - /* and decode the prologue region records. */ - - if (rhdr.is_prologue) { - scoreboard = uwx_new_scoreboard(env, scoreboard); - if (scoreboard == 0) - return UWX_ERR_NOMEM; - status = uwx_decode_prologue(env, &bstream, - scoreboard, &rhdr, ip_slot); - } - - /* If a body region, read and decode the body region */ - /* records. If the body has an epilogue count, */ - /* uwx_decode_body will note that in the region header */ - /* record for use at the bottom of the loop. */ - - else { - status = uwx_decode_body(env, &bstream, scoreboard, &rhdr, ip_slot); - } - - if (status != UWX_OK) - return status; - - TRACE_R_DUMP_SB(scoreboard, rhdr, cur_slot, ip_slot) - - /* If the target ip slot is within this region, we're done. */ - /* Return the scoreboard's register state array. */ - - if (ip_slot < rhdr.rlen) { - *rstatep = scoreboard->rstate; - return UWX_OK; - } - - /* Otherwise, update the current ip slot, pop the */ - /* scoreboard stack based on the epilogue count, */ - /* and loop back around for the next region. */ - - cur_slot += rhdr.rlen; - ip_slot -= rhdr.rlen; - if (rhdr.ecount > 0) { - scoreboard = uwx_pop_scoreboards(env, scoreboard, rhdr.ecount); - if (scoreboard == 0) - return UWX_ERR_PROLOG_UF; - } - } - /*NOTREACHED*/ -} - - -/* uwx_decode_rhdr: Decodes a region header record */ - -int uwx_decode_rhdr( - struct uwx_env *env, - struct uwx_bstream *bstream, - struct uwx_rhdr *rhdr) -{ - int b0; - int b1; - uint64_t val; - int status; - - /* Get the first byte of the next descriptor record. */ - b0 = uwx_get_byte(bstream); - if (b0 < 0) - return UWX_ERR_NOUDESC; - - /* Initialize region header record. */ - - rhdr->is_prologue = 0; - rhdr->rlen = 0; - rhdr->mask = 0; - rhdr->grsave = 0; - rhdr->ecount = 0; - - /* Format R1 */ - - if (b0 < 0x40) { - if ((b0 & 0x20) == 0) { - TRACE_I_DECODE_RHDR_1("(R1) prologue", b0) - rhdr->is_prologue = 1; - } - else { - TRACE_I_DECODE_RHDR_1("(R1) body", b0) - } - rhdr->rlen = b0 & 0x1f; - } - - /* Format R2 */ - - else if (b0 < 0x60) { - b1 = uwx_get_byte(bstream); - if (b1 < 0) - return UWX_ERR_BADUDESC; - status = uwx_get_uleb128(bstream, &val); - if (status != 0) - return UWX_ERR_BADUDESC; - TRACE_I_DECODE_RHDR_2L("(R2) prologue_gr", b0, b1, val) - rhdr->is_prologue = 1; - rhdr->rlen = (unsigned int) val; - rhdr->mask = ((b0 & 0x07) << 1) | (b1 >> 7); - rhdr->grsave = b1 & 0x7f; - } - - /* Format R3 */ - - else if (b0 < 0x80) { - status = uwx_get_uleb128(bstream, &val); - if (status != 0) - return UWX_ERR_BADUDESC; - if ((b0 & 0x03) == 0) { - TRACE_I_DECODE_RHDR_1L("(R3) prologue", b0, val) - rhdr->is_prologue = 1; - } - else { - TRACE_I_DECODE_RHDR_1L("(R3) body", b0, val) - } - rhdr->rlen = (unsigned int) val; - } - - /* Otherwise, not a region header record. */ - - else { - TRACE_I_DECODE_RHDR_1("(?)", b0) - return UWX_ERR_BADUDESC; - } - - return UWX_OK; -} - - -/* uwx_decode_prologue: Decodes a prologue region */ - -int uwx_decode_prologue( - struct uwx_env *env, - struct uwx_bstream *bstream, - struct uwx_scoreboard *scoreboard, - struct uwx_rhdr *rhdr, - int ip_slot) -{ - int status; - int reg; - int mask; - int b0; - int b1; - int b2; - int b3; - int r; - int t; - int i; - uint64_t parm1; - uint64_t parm2; - uint64_t newrstate[NSBREG]; - int tspill[NSBREG]; - int priunat_mem_rstate; - int t_priunat_mem; - unsigned int gr_mem_mask; - unsigned int br_mem_mask; - unsigned int fr_mem_mask; - unsigned int gr_gr_mask; - unsigned int br_gr_mask; - int ngr; - int nbr; - int nfr; - unsigned int spill_base; - unsigned int gr_base; - unsigned int br_base; - unsigned int fr_base; - - /* Initialize an array of register states from the current */ - /* scoreboard, along with a parallel array of spill times. */ - /* We use this as a temporary scoreboard, then update the */ - /* real scoreboard at the end of the procedure. */ - /* We initialize the spill time to (rhdr.rlen - 1) so that */ - /* spills without a "when" descriptor will take effect */ - /* at the end of the prologue region. */ - /* (Boundary condition: all actions in a zero-length prologue */ - /* will appear to have happened in the instruction slot */ - /* immediately preceding the prologue.) */ - - for (i = 0; i < env->nsbreg; i++) { - newrstate[i] = scoreboard->rstate[i]; - tspill[i] = rhdr->rlen - 1; - } - priunat_mem_rstate = UWX_DISP_NONE; - t_priunat_mem = rhdr->rlen - 1; - - fr_mem_mask = 0; - gr_mem_mask = 0; - br_mem_mask = 0; - gr_gr_mask = 0; - br_gr_mask = 0; - nfr = 127; - ngr = 127; - nbr = 127; - spill_base = 0; - - /* If prologue_gr header record supplied mask and grsave, */ - /* record these in the scoreboard. */ - - reg = rhdr->grsave; - mask = rhdr->mask; - if (mask & 0x8) { - newrstate[SBREG_RP] = UWX_DISP_REG(UWX_REG_GR(reg)); - reg++; - } - if (mask & 0x4) { - newrstate[SBREG_PFS] = UWX_DISP_REG(UWX_REG_GR(reg)); - reg++; - } - if (mask & 0x2) { - newrstate[SBREG_PSP] = UWX_DISP_REG(UWX_REG_GR(reg)); - reg++; - } - if (mask & 0x1) { - newrstate[SBREG_PREDS] = UWX_DISP_REG(UWX_REG_GR(reg)); - reg++; - } - - /* Read prologue descriptor records until */ - /* we hit another region header. */ - - for (;;) { - - b0 = uwx_get_byte(bstream); - - if (b0 < 0x80) { - /* Return the last byte read to the byte stream, since it's */ - /* really the first byte of the next region header record. */ - if (b0 >= 0) - (void) uwx_unget_byte(bstream, b0); - break; - } - - switch ((b0 & 0x70) >> 4) { - - case 0: /* 1000 xxxx */ - case 1: /* 1001 xxxx */ - /* Format P1 (br_mem) */ - TRACE_I_DECODE_PROLOGUE_1("(P1) br_mem", b0) - br_mem_mask = b0 & 0x1f; - break; - - case 2: /* 1010 xxxx */ - /* Format P2 (br_gr) */ - b1 = uwx_get_byte(bstream); - if (b1 < 0) - return UWX_ERR_BADUDESC; - TRACE_I_DECODE_PROLOGUE_2("(P2) br_gr", b0, b1) - mask = ((b0 & 0x0f) << 1) | (b1 >> 7); - reg = b1 & 0x7f; - br_gr_mask = mask; - for (i = 0; i < NSB_BR && mask != 0; i++) { - if (mask & 0x01) { - newrstate[SBREG_BR + i] = UWX_DISP_REG(UWX_REG_GR(reg)); - reg++; - } - mask = mask >> 1; - } - break; - - case 3: /* 1011 xxxx */ - /* Format P3 */ - if (b0 < 0xb8) { - b1 = uwx_get_byte(bstream); - if (b1 < 0) - return UWX_ERR_BADUDESC; - r = ((b0 & 0x7) << 1) | (b1 >> 7); - reg = b1 & 0x7f; - switch (r) { - case 0: /* psp_gr */ - TRACE_I_DECODE_PROLOGUE_2("(P3) psp_gr", b0, b1) - newrstate[SBREG_PSP] = UWX_DISP_REG(UWX_REG_GR(reg)); - break; - case 1: /* rp_gr */ - TRACE_I_DECODE_PROLOGUE_2("(P3) rp_gr", b0, b1) - newrstate[SBREG_RP] = UWX_DISP_REG(UWX_REG_GR(reg)); - break; - case 2: /* pfs_gr */ - TRACE_I_DECODE_PROLOGUE_2("(P3) pfs_gr", b0, b1) - newrstate[SBREG_PFS] = UWX_DISP_REG(UWX_REG_GR(reg)); - break; - case 3: /* preds_gr */ - TRACE_I_DECODE_PROLOGUE_2("(P3) preds_gr", b0, b1) - newrstate[SBREG_PREDS] = - UWX_DISP_REG(UWX_REG_GR(reg)); - break; - case 4: /* unat_gr */ - TRACE_I_DECODE_PROLOGUE_2("(P3) unat_gr", b0, b1) - newrstate[SBREG_UNAT] = - UWX_DISP_REG(UWX_REG_GR(reg)); - break; - case 5: /* lc_gr */ - TRACE_I_DECODE_PROLOGUE_2("(P3) lc_gr", b0, b1) - newrstate[SBREG_LC] = - UWX_DISP_REG(UWX_REG_GR(reg)); - break; - case 6: /* rp_br */ - TRACE_I_DECODE_PROLOGUE_2("(P3) rp_br", b0, b1) - scoreboard->rstate[SBREG_RP] = - UWX_DISP_REG(UWX_REG_BR(reg)); - if (newrstate[SBREG_RP] == - UWX_DISP_REG(UWX_REG_BR(0))) - newrstate[SBREG_RP] = - UWX_DISP_REG(UWX_REG_BR(reg)); - break; - case 7: /* rnat_gr */ - TRACE_I_DECODE_PROLOGUE_2("(P3) rnat_gr", b0, b1) - newrstate[SBREG_RNAT] = - UWX_DISP_REG(UWX_REG_GR(reg)); - break; - case 8: /* bsp_gr */ - TRACE_I_DECODE_PROLOGUE_2("(P3) bsp_gr", b0, b1) - /* Don't track BSP yet */ - return UWX_ERR_CANTUNWIND; - /* break; */ - case 9: /* bspstore_gr */ - TRACE_I_DECODE_PROLOGUE_2("(P3) bspstore_gr", b0, b1) - /* Don't track BSPSTORE yet */ - return UWX_ERR_CANTUNWIND; - /* break; */ - case 10: /* fpsr_gr */ - TRACE_I_DECODE_PROLOGUE_2("(P3) fpsr_gr", b0, b1) - newrstate[SBREG_FPSR] = - UWX_DISP_REG(UWX_REG_GR(reg)); - break; - case 11: /* priunat_gr */ - TRACE_I_DECODE_PROLOGUE_2("(P3) priunat_gr", b0, b1) - newrstate[SBREG_PRIUNAT] = - UWX_DISP_REG(UWX_REG_GR(reg)); - break; - default: - TRACE_I_DECODE_PROLOGUE_2("(P3) ??", b0, b1) - return UWX_ERR_BADUDESC; - } - } - - /* Format P4 (spill_mask) */ - else if (b0 == 0xb8) { - TRACE_I_DECODE_PROLOGUE_1("(P4) spill_mask", b0) - /* The spill_mask descriptor is followed by */ - /* an imask field whose length is determined */ - /* by the region length: there are two mask */ - /* bits per instruction slot in the region. */ - /* We decode these bits two at a time, counting */ - /* the number of FRs, GRs, and BRs that are */ - /* saved up to the slot of interest. Other */ - /* descriptors describe which sets of these */ - /* registers are spilled, and we put those */ - /* two pieces of information together at the */ - /* end of the main loop. */ - t = 0; - nfr = 0; - ngr = 0; - nbr = 0; - while (t < rhdr->rlen) { - b1 = uwx_get_byte(bstream); - if (b1 < 0) - return UWX_ERR_BADUDESC; - for (i = 0; i < 4 && (t + i) < ip_slot; i++) { - switch (b1 & 0xc0) { - case 0x00: break; - case 0x40: nfr++; break; - case 0x80: ngr++; break; - case 0xc0: nbr++; break; - } - b1 = b1 << 2; - } - t += 4; - } - } - - /* Format P5 (frgr_mem) */ - else if (b0 == 0xb9) { - b1 = uwx_get_byte(bstream); - if (b1 < 0) - return UWX_ERR_BADUDESC; - b2 = uwx_get_byte(bstream); - if (b2 < 0) - return UWX_ERR_BADUDESC; - b3 = uwx_get_byte(bstream); - if (b3 < 0) - return UWX_ERR_BADUDESC; - TRACE_I_DECODE_PROLOGUE_4("(P5) frgr_mem", b0, b1, b2, b3) - gr_mem_mask = b1 >> 4; - fr_mem_mask = ((b1 & 0x0f) << 16) | (b2 << 8) | b3; - } - - /* Invalid descriptor record */ - else { - TRACE_I_DECODE_PROLOGUE_1("(?)", b0) - return UWX_ERR_BADUDESC; - } - - break; - - case 4: /* 1100 xxxx */ - /* Format P6 (fr_mem) */ - TRACE_I_DECODE_PROLOGUE_1("(P6) fr_mem", b0) - fr_mem_mask = b0 & 0x0f; - break; - - case 5: /* 1101 xxxx */ - /* Format P6 (gr_mem) */ - TRACE_I_DECODE_PROLOGUE_1("(P6) gr_mem", b0) - gr_mem_mask = b0 & 0x0f; - break; - - case 6: /* 1110 xxxx */ - /* Format P7 */ - r = b0 & 0xf; - status = uwx_get_uleb128(bstream, &parm1); - if (status != 0) - return UWX_ERR_BADUDESC; - switch (r) { - case 0: /* mem_stack_f */ - status = uwx_get_uleb128(bstream, &parm2); - if (status != 0) - return UWX_ERR_BADUDESC; - TRACE_I_DECODE_PROLOGUE_1LL("(P7) mem_stack_f", b0, parm1, parm2) - newrstate[SBREG_PSP] = UWX_DISP_SPPLUS(parm2 * 16); - tspill[SBREG_PSP] = (int) parm1; - break; - case 1: /* mem_stack_v */ - TRACE_I_DECODE_PROLOGUE_1L("(P7) mem_stack_v", b0, parm1) - tspill[SBREG_PSP] = (int) parm1; - break; - case 2: /* spill_base */ - TRACE_I_DECODE_PROLOGUE_1L("(P7) spill_base", b0, parm1) - spill_base = 4 * (unsigned int) parm1; - break; - case 3: /* psp_sprel */ - TRACE_I_DECODE_PROLOGUE_1L("(P7) psp_sprel", b0, parm1) - newrstate[SBREG_PSP] = UWX_DISP_SPREL(parm1 * 4); - break; - case 4: /* rp_when */ - TRACE_I_DECODE_PROLOGUE_1L("(P7) rp_when", b0, parm1) - tspill[SBREG_RP] = (int) parm1; - break; - case 5: /* rp_psprel */ - TRACE_I_DECODE_PROLOGUE_1L("(P7) rp_psprel", b0, parm1) - newrstate[SBREG_RP] = UWX_DISP_PSPREL(parm1 * 4); - break; - case 6: /* pfs_when */ - TRACE_I_DECODE_PROLOGUE_1L("(P7) pfs_when", b0, parm1) - tspill[SBREG_PFS] = (int) parm1; - break; - case 7: /* pfs_psprel */ - TRACE_I_DECODE_PROLOGUE_1L("(P7) pfs_psprel", b0, parm1) - newrstate[SBREG_PFS] = UWX_DISP_PSPREL(parm1 * 4); - break; - case 8: /* preds_when */ - TRACE_I_DECODE_PROLOGUE_1L("(P7) preds_when", b0, parm1) - tspill[SBREG_PREDS] = (int) parm1; - break; - case 9: /* preds_psprel */ - TRACE_I_DECODE_PROLOGUE_1L("(P7) preds_psprel", b0, parm1) - newrstate[SBREG_PREDS] = UWX_DISP_PSPREL(parm1 * 4); - break; - case 10: /* lc_when */ - TRACE_I_DECODE_PROLOGUE_1L("(P7) lc_when", b0, parm1) - tspill[SBREG_LC] = (int) parm1; - break; - case 11: /* lc_psprel */ - TRACE_I_DECODE_PROLOGUE_1L("(P7) lc_psprel", b0, parm1) - newrstate[SBREG_LC] = UWX_DISP_PSPREL(parm1 * 4); - break; - case 12: /* unat_when */ - TRACE_I_DECODE_PROLOGUE_1L("(P7) unat_when", b0, parm1) - tspill[SBREG_UNAT] = (int) parm1; - break; - case 13: /* unat_psprel */ - TRACE_I_DECODE_PROLOGUE_1L("(P7) unat_psprel", b0, parm1) - newrstate[SBREG_UNAT] = UWX_DISP_PSPREL(parm1 * 4); - break; - case 14: /* fpsr_when */ - TRACE_I_DECODE_PROLOGUE_1L("(P7) fpsr_when", b0, parm1) - tspill[SBREG_FPSR] = (int) parm1; - break; - case 15: /* fpsr_psprel */ - TRACE_I_DECODE_PROLOGUE_1L("(P7) fpsr_psprel", b0, parm1) - newrstate[SBREG_FPSR] = UWX_DISP_PSPREL(parm1 * 4); - break; - } - break; - - case 7: /* 1111 xxxx */ - /* Format P8 */ - if (b0 == 0xf0) { - b1 = uwx_get_byte(bstream); - if (b1 < 0) - return UWX_ERR_BADUDESC; - status = uwx_get_uleb128(bstream, &parm1); - if (status != 0) - return UWX_ERR_BADUDESC; - switch (b1) { - case 1: /* rp_sprel */ - TRACE_I_DECODE_PROLOGUE_2L("(P8) rp_sprel", b0, b1, parm1) - newrstate[SBREG_RP] = UWX_DISP_SPREL(parm1 * 4); - break; - case 2: /* pfs_sprel */ - TRACE_I_DECODE_PROLOGUE_2L("(P8) pfs_sprel", b0, b1, parm1) - newrstate[SBREG_PFS] = UWX_DISP_SPREL(parm1 * 4); - break; - case 3: /* preds_sprel */ - TRACE_I_DECODE_PROLOGUE_2L("(P8) preds_sprel", b0, b1, parm1) - newrstate[SBREG_PREDS] = UWX_DISP_SPREL(parm1 * 4); - break; - case 4: /* lc_sprel */ - TRACE_I_DECODE_PROLOGUE_2L("(P8) lc_sprel", b0, b1, parm1) - newrstate[SBREG_LC] = UWX_DISP_SPREL(parm1 * 4); - break; - case 5: /* unat_sprel */ - TRACE_I_DECODE_PROLOGUE_2L("(P8) unat_sprel", b0, b1, parm1) - newrstate[SBREG_UNAT] = UWX_DISP_SPREL(parm1 * 4); - break; - case 6: /* fpsr_sprel */ - TRACE_I_DECODE_PROLOGUE_2L("(P8) fpsr_sprel", b0, b1, parm1) - newrstate[SBREG_FPSR] = UWX_DISP_SPREL(parm1 * 4); - break; - case 7: /* bsp_when */ - TRACE_I_DECODE_PROLOGUE_2L("(P8) bsp_when", b0, b1, parm1) - /* Don't track BSP yet */ - return UWX_ERR_CANTUNWIND; - /* break; */ - case 8: /* bsp_psprel */ - TRACE_I_DECODE_PROLOGUE_2L("(P8) bsp_psprel", b0, b1, parm1) - /* Don't track BSP yet */ - return UWX_ERR_CANTUNWIND; - /* break; */ - case 9: /* bsp_sprel */ - TRACE_I_DECODE_PROLOGUE_2L("(P8) bsp_sprel", b0, b1, parm1) - /* Don't track BSP yet */ - return UWX_ERR_CANTUNWIND; - /* break; */ - case 10: /* bspstore_when */ - TRACE_I_DECODE_PROLOGUE_2L("(P8) bspstore_when", b0, b1, parm1) - /* Don't track BSP yet */ - return UWX_ERR_CANTUNWIND; - /* break; */ - case 11: /* bspstore_psprel */ - TRACE_I_DECODE_PROLOGUE_2L("(P8) bspstore_psprel", b0, b1, parm1) - /* Don't track BSP yet */ - return UWX_ERR_CANTUNWIND; - /* break; */ - case 12: /* bspstore_sprel */ - TRACE_I_DECODE_PROLOGUE_2L("(P8) bspstore_sprel", b0, b1, parm1) - /* Don't track BSP yet */ - return UWX_ERR_CANTUNWIND; - /* break; */ - case 13: /* rnat_when */ - TRACE_I_DECODE_PROLOGUE_2L("(P8) rnat_when", b0, b1, parm1) - tspill[SBREG_RNAT] = (int) parm1; - break; - case 14: /* rnat_psprel */ - TRACE_I_DECODE_PROLOGUE_2L("(P8) rnat_psprel", b0, b1, parm1) - newrstate[SBREG_RNAT] = UWX_DISP_PSPREL(parm1 * 4); - break; - case 15: /* rnat_sprel */ - TRACE_I_DECODE_PROLOGUE_2L("(P8) rnat_sprel", b0, b1, parm1) - newrstate[SBREG_RNAT] = UWX_DISP_SPREL(parm1 * 4); - break; - case 16: /* priunat_when_gr */ - TRACE_I_DECODE_PROLOGUE_2L("(P8) priunat_when_gr", b0, b1, parm1) - tspill[SBREG_PRIUNAT] = (int) parm1; - break; - case 17: /* priunat_psprel */ - TRACE_I_DECODE_PROLOGUE_2L("(P8) priunat_psprel", b0, b1, parm1) - priunat_mem_rstate = UWX_DISP_PSPREL(parm1 * 4); - break; - case 18: /* priunat_sprel */ - TRACE_I_DECODE_PROLOGUE_2L("(P8) priunat_sprel", b0, b1, parm1) - priunat_mem_rstate = UWX_DISP_SPREL(parm1 * 4); - break; - case 19: /* priunat_when_mem */ - TRACE_I_DECODE_PROLOGUE_2L("(P8) priunat_when_mem", b0, b1, parm1) - t_priunat_mem = (int) parm1; - break; - default: - TRACE_I_DECODE_PROLOGUE_2L("(P8) ??", b0, b1, parm1) - return UWX_ERR_BADUDESC; - } - } - - /* Format P9 (gr_gr) */ - else if (b0 == 0xf1) { - b1 = uwx_get_byte(bstream); - if (b1 < 0) - return UWX_ERR_BADUDESC; - b2 = uwx_get_byte(bstream); - if (b2 < 0) - return UWX_ERR_BADUDESC; - TRACE_I_DECODE_PROLOGUE_3("(P9) gr_gr", b0, b1, b2) - mask = b1 & 0x0f; - reg = b2 & 0x7f; - gr_gr_mask = mask; - for (i = 0; i < NSB_GR && mask != 0; i++) { - if (mask & 0x01) { - newrstate[SBREG_GR + i] = - UWX_DISP_REG(UWX_REG_GR(reg)); - reg++; - } - mask = mask >> 1; - } - } - - /* Format X1 */ - else if (b0 == 0xf9) { - TRACE_I_DECODE_PROLOGUE_1("(X1)", b0) - b1 = uwx_get_byte(bstream); - if (b1 < 0) - return UWX_ERR_BADUDESC; - /* Don't support X-format descriptors yet */ - return UWX_ERR_CANTUNWIND; - } - - /* Format X2 */ - else if (b0 == 0xfa) { - TRACE_I_DECODE_PROLOGUE_1("(X2)", b0) - b1 = uwx_get_byte(bstream); - if (b1 < 0) - return UWX_ERR_BADUDESC; - b2 = uwx_get_byte(bstream); - if (b2 < 0) - return UWX_ERR_BADUDESC; - /* Don't support X-format descriptors yet */ - return UWX_ERR_CANTUNWIND; - } - - /* Format X3 */ - else if (b0 == 0xfb) { - TRACE_I_DECODE_PROLOGUE_1("(X3)", b0) - b1 = uwx_get_byte(bstream); - if (b1 < 0) - return UWX_ERR_BADUDESC; - b2 = uwx_get_byte(bstream); - if (b2 < 0) - return UWX_ERR_BADUDESC; - /* Don't support X-format descriptors yet */ - return UWX_ERR_CANTUNWIND; - } - - /* Format X4 */ - else if (b0 == 0xfc) { - TRACE_I_DECODE_PROLOGUE_1("(X4)", b0) - b1 = uwx_get_byte(bstream); - if (b1 < 0) - return UWX_ERR_BADUDESC; - b2 = uwx_get_byte(bstream); - if (b2 < 0) - return UWX_ERR_BADUDESC; - b3 = uwx_get_byte(bstream); - if (b3 < 0) - return UWX_ERR_BADUDESC; - /* Don't support X-format descriptors yet */ - return UWX_ERR_CANTUNWIND; - } - - /* Format P10 */ - else if (b0 == 0xff) { - b1 = uwx_get_byte(bstream); - if (b1 < 0) - return UWX_ERR_BADUDESC; - b2 = uwx_get_byte(bstream); - if (b2 < 0) - return UWX_ERR_BADUDESC; - TRACE_I_DECODE_PROLOGUE_3("(P10) abi", b0, b1, b2) - env->abi_context = (b1 << 8) | b2; - return UWX_ABI_FRAME; - } - - /* Invalid descriptor record */ - else { - TRACE_I_DECODE_PROLOGUE_1("(?)", b0) - return UWX_ERR_BADUDESC; - } - break; - } - } - - /* Process the masks of spilled GRs, FRs, and BRs to */ - /* determine when and where each register was saved. */ - - fr_base = spill_base + 16 * uwx_count_ones(fr_mem_mask); - br_base = fr_base + 8 * uwx_count_ones(br_mem_mask); - gr_base = br_base + 8 * uwx_count_ones(gr_mem_mask); - TRACE_I_DECODE_PROLOGUE_SPILL_BASE(spill_base) - TRACE_I_DECODE_PROLOGUE_MASKS(gr_mem_mask, gr_gr_mask) - TRACE_I_DECODE_PROLOGUE_NSPILL(ngr) - for (i = 0; ngr > 0 && i <= NSB_GR; i++) { - if (gr_mem_mask & 1) { - newrstate[SBREG_GR + i] = UWX_DISP_PSPREL(gr_base); - tspill[SBREG_GR + i] = 0; - gr_base -= 8; - ngr--; - } - else if (gr_gr_mask & 1) { - tspill[SBREG_GR + i] = 0; - ngr--; - } - gr_gr_mask = gr_gr_mask >> 1; - gr_mem_mask = gr_mem_mask >> 1; - } - for (i = 0; nbr > 0 && i <= NSB_BR; i++) { - if (br_mem_mask & 1) { - newrstate[SBREG_BR + i] = UWX_DISP_PSPREL(br_base); - tspill[SBREG_BR + i] = 0; - br_base -= 8; - nbr--; - } - else if (br_gr_mask & 1) { - tspill[SBREG_BR + i] = 0; - nbr--; - } - br_gr_mask = br_gr_mask >> 1; - br_mem_mask = br_mem_mask >> 1; - } - for (i = 0; nfr > 0 && i <= NSB_FR; i++) { - if (fr_mem_mask & 1) { - newrstate[SBREG_FR + i] = UWX_DISP_PSPREL(fr_base); - tspill[SBREG_FR + i] = 0; - fr_base -= 16; - nfr--; - } - fr_mem_mask = fr_mem_mask >> 1; - } - - /* Update the scoreboard. */ - - for (i = 0; i < env->nsbreg; i++) { - if (ip_slot >= rhdr->rlen || ip_slot > tspill[i]) - scoreboard->rstate[i] = newrstate[i]; - } - if (priunat_mem_rstate != UWX_DISP_NONE && ip_slot > t_priunat_mem) - scoreboard->rstate[SBREG_PRIUNAT] = priunat_mem_rstate; - - return UWX_OK; -} - -int uwx_count_ones(unsigned int mask) -{ - mask = (mask & 0x55555555) + ((mask & 0xaaaaaaaa) >> 1); - mask = (mask & 0x33333333) + ((mask & 0xcccccccc) >> 2); - mask = (mask & 0x0f0f0f0f) + ((mask & 0xf0f0f0f0) >> 4); - mask = (mask & 0x00ff00ff) + ((mask & 0xff00ff00) >> 8); - return (mask & 0x0000ffff) + ((mask & 0xffff0000) >> 16); -} - -/* uwx_decode_body: Decodes a body region */ - -int uwx_decode_body( - struct uwx_env *env, - struct uwx_bstream *bstream, - struct uwx_scoreboard *scoreboard, - struct uwx_rhdr *rhdr, - int ip_slot) -{ - int status; - int b0; - int b1; - int b2; - int b3; - int label; - int ecount; - int i; - uint64_t parm1; - uint64_t parm2; - uint64_t newrstate[NSBREG]; - int tspill[NSBREG]; - int t_sp_restore; - - /* Initialize an array of register states from the current */ - /* scoreboard, along with a parallel array of spill times. */ - /* We use this as a temporary scoreboard, then update the */ - /* real scoreboard at the end of the procedure. */ - /* We initialize the spill time to (rhdr.rlen - 1) so that */ - /* spills without a "when" descriptor will take effect */ - /* at the end of the prologue region. */ - /* (Boundary condition: all actions in a zero-length prologue */ - /* will appear to have happened in the instruction slot */ - /* immediately preceding the prologue.) */ - - for (i = 0; i < env->nsbreg; i++) { - newrstate[i] = scoreboard->rstate[i]; - tspill[i] = rhdr->rlen - 1; - } - t_sp_restore = rhdr->rlen - 1; - - /* Read body descriptor records until */ - /* we hit another region header. */ - - for (;;) { - - b0 = uwx_get_byte(bstream); - - if (b0 < 0x80) { - /* Return the last byte read to the byte stream, since it's */ - /* really the first byte of the next region header record. */ - if (b0 >= 0) - (void) uwx_unget_byte(bstream, b0); - break; - } - - /* Format B1 (label_state) */ - if (b0 < 0xa0) { - TRACE_I_DECODE_BODY_1("(B1) label_state", b0) - label = b0 & 0x1f; - status = uwx_label_scoreboard(env, scoreboard, label); - if (status != UWX_OK) - return (status); - } - - /* Format B1 (copy_state) */ - else if (b0 < 0xc0) { - TRACE_I_DECODE_BODY_1("(B1) copy_state", b0) - label = b0 & 0x1f; - status = uwx_copy_scoreboard(env, scoreboard, label); - if (status != UWX_OK) - return (status); - for (i = 0; i < env->nsbreg; i++) { - newrstate[i] = scoreboard->rstate[i]; - tspill[i] = rhdr->rlen; - } - } - - /* Format B2 (epilogue) */ - else if (b0 < 0xe0) { - ecount = b0 & 0x1f; - status = uwx_get_uleb128(bstream, &parm1); - if (status != 0) - return UWX_ERR_BADUDESC; - TRACE_I_DECODE_BODY_1L("(B2) epilogue", b0, parm1) - rhdr->ecount = ecount + 1; - t_sp_restore = rhdr->rlen - (unsigned int) parm1; - } - - /* Format B3 (epilogue) */ - else if (b0 == 0xe0) { - status = uwx_get_uleb128(bstream, &parm1); - if (status != 0) - return UWX_ERR_BADUDESC; - status = uwx_get_uleb128(bstream, &parm2); - if (status != 0) - return UWX_ERR_BADUDESC; - TRACE_I_DECODE_BODY_1LL("(B3) epilogue", b0, parm1, parm2) - t_sp_restore = rhdr->rlen - (unsigned int) parm1; - rhdr->ecount = (unsigned int) parm2 + 1; - } - - /* Format B4 (label_state) */ - else if (b0 == 0xf0) { - status = uwx_get_uleb128(bstream, &parm1); - if (status != 0) - return UWX_ERR_BADUDESC; - TRACE_I_DECODE_BODY_1L("(B4) label_state", b0, parm1) - label = (int) parm1; - status = uwx_label_scoreboard(env, scoreboard, label); - if (status != UWX_OK) - return (status); - } - - /* Format B4 (copy_state) */ - else if (b0 == 0xf8) { - status = uwx_get_uleb128(bstream, &parm1); - if (status != 0) - return UWX_ERR_BADUDESC; - TRACE_I_DECODE_BODY_1L("(B4) copy_state", b0, parm1) - label = (int) parm1; - status = uwx_copy_scoreboard(env, scoreboard, label); - if (status != UWX_OK) - return (status); - for (i = 0; i < env->nsbreg; i++) { - newrstate[i] = scoreboard->rstate[i]; - tspill[i] = rhdr->rlen; - } - } - - /* Format X1 */ - else if (b0 == 0xf9) { - TRACE_I_DECODE_BODY_1("(X1)", b0) - b1 = uwx_get_byte(bstream); - if (b1 < 0) - return UWX_ERR_BADUDESC; - /* Don't support X-format descriptors yet */ - return UWX_ERR_CANTUNWIND; - } - - /* Format X2 */ - else if (b0 == 0xfa) { - TRACE_I_DECODE_BODY_1("(X2)", b0) - b1 = uwx_get_byte(bstream); - if (b1 < 0) - return UWX_ERR_BADUDESC; - b2 = uwx_get_byte(bstream); - if (b2 < 0) - return UWX_ERR_BADUDESC; - /* Don't support X-format descriptors yet */ - return UWX_ERR_CANTUNWIND; - } - - /* Format X3 */ - else if (b0 == 0xfb) { - TRACE_I_DECODE_BODY_1("(X3)", b0) - b1 = uwx_get_byte(bstream); - if (b1 < 0) - return UWX_ERR_BADUDESC; - b2 = uwx_get_byte(bstream); - if (b2 < 0) - return UWX_ERR_BADUDESC; - /* Don't support X-format descriptors yet */ - return UWX_ERR_CANTUNWIND; - } - - /* Format X4 */ - else if (b0 == 0xfc) { - TRACE_I_DECODE_BODY_1("(X4)", b0) - b1 = uwx_get_byte(bstream); - if (b1 < 0) - return UWX_ERR_BADUDESC; - b2 = uwx_get_byte(bstream); - if (b2 < 0) - return UWX_ERR_BADUDESC; - b3 = uwx_get_byte(bstream); - if (b3 < 0) - return UWX_ERR_BADUDESC; - /* Don't support X-format descriptors yet */ - return UWX_ERR_CANTUNWIND; - } - - /* Invalid descriptor record */ - else { - TRACE_I_DECODE_BODY_1("(?)", b0) - return UWX_ERR_BADUDESC; - } - } - - /* Update the scoreboard. */ - - for (i = 0; i < env->nsbreg; i++) { - if (ip_slot > tspill[i]) - scoreboard->rstate[i] = newrstate[i]; - } - - /* If we've passed the point in the epilogue where sp */ - /* is restored, update the scoreboard entry for PSP */ - /* and reset any entries for registers saved in memory. */ - - if (rhdr->ecount > 0 && ip_slot > t_sp_restore) { - scoreboard->rstate[SBREG_PSP] = UWX_DISP_SPPLUS(0); - for (i = 0; i < env->nsbreg; i++) { - if (UWX_GET_DISP_CODE(scoreboard->rstate[i]) == UWX_DISP_SPREL(0) || - UWX_GET_DISP_CODE(scoreboard->rstate[i]) == UWX_DISP_PSPREL(0)) - scoreboard->rstate[i] = UWX_DISP_NONE; - } - } - - return UWX_OK; -} - |